1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park #include <string.h>
9*54fd6939SJiyong Park
10*54fd6939SJiyong Park #include <common/debug.h>
11*54fd6939SJiyong Park #include <drivers/io/io_driver.h>
12*54fd6939SJiyong Park #include <drivers/io/io_dummy.h>
13*54fd6939SJiyong Park #include <drivers/io/io_storage.h>
14*54fd6939SJiyong Park
15*54fd6939SJiyong Park struct file_state {
16*54fd6939SJiyong Park int in_use;
17*54fd6939SJiyong Park size_t size;
18*54fd6939SJiyong Park };
19*54fd6939SJiyong Park
20*54fd6939SJiyong Park static struct file_state current_file = {0};
21*54fd6939SJiyong Park
22*54fd6939SJiyong Park /* Identify the device type as dummy */
device_type_dummy(void)23*54fd6939SJiyong Park static io_type_t device_type_dummy(void)
24*54fd6939SJiyong Park {
25*54fd6939SJiyong Park return IO_TYPE_DUMMY;
26*54fd6939SJiyong Park }
27*54fd6939SJiyong Park
28*54fd6939SJiyong Park /* Dummy device functions */
29*54fd6939SJiyong Park static int dummy_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
30*54fd6939SJiyong Park static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
31*54fd6939SJiyong Park io_entity_t *entity);
32*54fd6939SJiyong Park static int dummy_block_len(io_entity_t *entity, size_t *length);
33*54fd6939SJiyong Park static int dummy_block_read(io_entity_t *entity, uintptr_t buffer,
34*54fd6939SJiyong Park size_t length, size_t *length_read);
35*54fd6939SJiyong Park static int dummy_block_close(io_entity_t *entity);
36*54fd6939SJiyong Park static int dummy_dev_close(io_dev_info_t *dev_info);
37*54fd6939SJiyong Park
38*54fd6939SJiyong Park
39*54fd6939SJiyong Park static const io_dev_connector_t dummy_dev_connector = {
40*54fd6939SJiyong Park .dev_open = dummy_dev_open
41*54fd6939SJiyong Park };
42*54fd6939SJiyong Park
43*54fd6939SJiyong Park
44*54fd6939SJiyong Park static const io_dev_funcs_t dummy_dev_funcs = {
45*54fd6939SJiyong Park .type = device_type_dummy,
46*54fd6939SJiyong Park .open = dummy_block_open,
47*54fd6939SJiyong Park .seek = NULL,
48*54fd6939SJiyong Park .size = dummy_block_len,
49*54fd6939SJiyong Park .read = dummy_block_read,
50*54fd6939SJiyong Park .write = NULL,
51*54fd6939SJiyong Park .close = dummy_block_close,
52*54fd6939SJiyong Park .dev_init = NULL,
53*54fd6939SJiyong Park .dev_close = dummy_dev_close,
54*54fd6939SJiyong Park };
55*54fd6939SJiyong Park
56*54fd6939SJiyong Park
57*54fd6939SJiyong Park static const io_dev_info_t dummy_dev_info = {
58*54fd6939SJiyong Park .funcs = &dummy_dev_funcs,
59*54fd6939SJiyong Park .info = (uintptr_t)NULL
60*54fd6939SJiyong Park };
61*54fd6939SJiyong Park
62*54fd6939SJiyong Park
63*54fd6939SJiyong Park /* Open a connection to the dummy device */
dummy_dev_open(const uintptr_t dev_spec,io_dev_info_t ** dev_info)64*54fd6939SJiyong Park static int dummy_dev_open(const uintptr_t dev_spec __attribute__((unused)),
65*54fd6939SJiyong Park io_dev_info_t **dev_info)
66*54fd6939SJiyong Park {
67*54fd6939SJiyong Park assert(dev_info != NULL);
68*54fd6939SJiyong Park *dev_info = (io_dev_info_t *)&dummy_dev_info;
69*54fd6939SJiyong Park
70*54fd6939SJiyong Park return 0;
71*54fd6939SJiyong Park }
72*54fd6939SJiyong Park
73*54fd6939SJiyong Park
74*54fd6939SJiyong Park /* Close a connection to the dummy device */
dummy_dev_close(io_dev_info_t * dev_info)75*54fd6939SJiyong Park static int dummy_dev_close(io_dev_info_t *dev_info)
76*54fd6939SJiyong Park {
77*54fd6939SJiyong Park return 0;
78*54fd6939SJiyong Park }
79*54fd6939SJiyong Park
80*54fd6939SJiyong Park
81*54fd6939SJiyong Park /* Open a file on the dummy device */
dummy_block_open(io_dev_info_t * dev_info,const uintptr_t spec,io_entity_t * entity)82*54fd6939SJiyong Park static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
83*54fd6939SJiyong Park io_entity_t *entity)
84*54fd6939SJiyong Park {
85*54fd6939SJiyong Park int result;
86*54fd6939SJiyong Park const io_block_spec_t *block_spec = (io_block_spec_t *)spec;
87*54fd6939SJiyong Park
88*54fd6939SJiyong Park if (current_file.in_use == 0) {
89*54fd6939SJiyong Park assert(block_spec != NULL);
90*54fd6939SJiyong Park assert(entity != NULL);
91*54fd6939SJiyong Park
92*54fd6939SJiyong Park current_file.in_use = 1;
93*54fd6939SJiyong Park current_file.size = block_spec->length;
94*54fd6939SJiyong Park entity->info = (uintptr_t)¤t_file;
95*54fd6939SJiyong Park result = 0;
96*54fd6939SJiyong Park } else {
97*54fd6939SJiyong Park WARN("A Dummy device is already active. Close first.\n");
98*54fd6939SJiyong Park result = -ENOMEM;
99*54fd6939SJiyong Park }
100*54fd6939SJiyong Park
101*54fd6939SJiyong Park return result;
102*54fd6939SJiyong Park }
103*54fd6939SJiyong Park
104*54fd6939SJiyong Park
105*54fd6939SJiyong Park /* Return the size of a file on the dummy device */
dummy_block_len(io_entity_t * entity,size_t * length)106*54fd6939SJiyong Park static int dummy_block_len(io_entity_t *entity, size_t *length)
107*54fd6939SJiyong Park {
108*54fd6939SJiyong Park assert(entity != NULL);
109*54fd6939SJiyong Park assert(length != NULL);
110*54fd6939SJiyong Park
111*54fd6939SJiyong Park *length = ((struct file_state *)entity->info)->size;
112*54fd6939SJiyong Park
113*54fd6939SJiyong Park return 0;
114*54fd6939SJiyong Park }
115*54fd6939SJiyong Park
116*54fd6939SJiyong Park
117*54fd6939SJiyong Park /* Read data from a file on the dummy device */
dummy_block_read(io_entity_t * entity,uintptr_t buffer,size_t length,size_t * length_read)118*54fd6939SJiyong Park static int dummy_block_read(io_entity_t *entity, uintptr_t buffer,
119*54fd6939SJiyong Park size_t length, size_t *length_read)
120*54fd6939SJiyong Park {
121*54fd6939SJiyong Park assert(length_read != NULL);
122*54fd6939SJiyong Park
123*54fd6939SJiyong Park *length_read = length;
124*54fd6939SJiyong Park
125*54fd6939SJiyong Park return 0;
126*54fd6939SJiyong Park }
127*54fd6939SJiyong Park
128*54fd6939SJiyong Park
129*54fd6939SJiyong Park /* Close a file on the dummy device */
dummy_block_close(io_entity_t * entity)130*54fd6939SJiyong Park static int dummy_block_close(io_entity_t *entity)
131*54fd6939SJiyong Park {
132*54fd6939SJiyong Park assert(entity != NULL);
133*54fd6939SJiyong Park
134*54fd6939SJiyong Park entity->info = 0;
135*54fd6939SJiyong Park current_file.in_use = 0;
136*54fd6939SJiyong Park
137*54fd6939SJiyong Park return 0;
138*54fd6939SJiyong Park }
139*54fd6939SJiyong Park
140*54fd6939SJiyong Park
141*54fd6939SJiyong Park /* Exported functions */
142*54fd6939SJiyong Park
143*54fd6939SJiyong Park /* Register the dummy driver with the IO abstraction */
register_io_dev_dummy(const io_dev_connector_t ** dev_con)144*54fd6939SJiyong Park int register_io_dev_dummy(const io_dev_connector_t **dev_con)
145*54fd6939SJiyong Park {
146*54fd6939SJiyong Park int result;
147*54fd6939SJiyong Park
148*54fd6939SJiyong Park assert(dev_con != NULL);
149*54fd6939SJiyong Park
150*54fd6939SJiyong Park result = io_register_device(&dummy_dev_info);
151*54fd6939SJiyong Park if (result == 0)
152*54fd6939SJiyong Park *dev_con = &dummy_dev_connector;
153*54fd6939SJiyong Park
154*54fd6939SJiyong Park return result;
155*54fd6939SJiyong Park }
156