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