]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/ppc/device_table.c
sim: clean up C11 header includes
[thirdparty/binutils-gdb.git] / sim / ppc / device_table.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
17
18 */
19
20
21 #ifndef _DEVICE_TABLE_C_
22 #define _DEVICE_TABLE_C_
23
24 #include "device_table.h"
25
26 #include <stdlib.h>
27 #include <ctype.h>
28
29
30 /* Helper functions */
31
32
33 /* Go through the devices various reg properties for those that
34 specify attach addresses */
35
36
37 void
38 generic_device_init_address(device *me)
39 {
40 static const char *(reg_property_names[]) = {
41 "attach-addresses",
42 "assigned-addresses",
43 "reg",
44 "alternate-reg" ,
45 NULL
46 };
47 const char **reg_property_name;
48 int nr_valid_reg_properties = 0;
49 for (reg_property_name = reg_property_names;
50 *reg_property_name != NULL;
51 reg_property_name++) {
52 if (device_find_property(me, *reg_property_name) != NULL) {
53 reg_property_spec reg;
54 int reg_entry;
55 for (reg_entry = 0;
56 device_find_reg_array_property(me, *reg_property_name, reg_entry,
57 &reg);
58 reg_entry++) {
59 unsigned_word attach_address;
60 int attach_space;
61 unsigned attach_size;
62 if (!device_address_to_attach_address(device_parent(me),
63 &reg.address,
64 &attach_space, &attach_address,
65 me))
66 continue;
67 if (!device_size_to_attach_size(device_parent(me),
68 &reg.size,
69 &attach_size, me))
70 continue;
71 device_attach_address(device_parent(me),
72 attach_callback,
73 attach_space, attach_address, attach_size,
74 access_read_write_exec,
75 me);
76 nr_valid_reg_properties++;
77 }
78 /* if first option matches don't try for any others */
79 if (reg_property_name == reg_property_names)
80 break;
81 }
82 }
83 }
84
85 int
86 generic_device_unit_decode(device *bus,
87 const char *unit,
88 device_unit *phys)
89 {
90 memset(phys, 0, sizeof(device_unit));
91 if (unit == NULL)
92 return 0;
93 else {
94 int nr_cells = 0;
95 const int max_nr_cells = device_nr_address_cells(bus);
96 while (1) {
97 char *end = NULL;
98 unsigned long val;
99 val = strtoul(unit, &end, 0);
100 /* parse error? */
101 if (unit == end)
102 return -1;
103 /* two many cells? */
104 if (nr_cells >= max_nr_cells)
105 return -1;
106 /* save it */
107 phys->cells[nr_cells] = val;
108 nr_cells++;
109 unit = end;
110 /* more to follow? */
111 if (isspace(*unit) || *unit == '\0')
112 break;
113 if (*unit != ',')
114 return -1;
115 unit++;
116 }
117 if (nr_cells < max_nr_cells) {
118 /* shift everything to correct position */
119 int i;
120 for (i = 1; i <= nr_cells; i++)
121 phys->cells[max_nr_cells - i] = phys->cells[nr_cells - i];
122 for (i = 0; i < (max_nr_cells - nr_cells); i++)
123 phys->cells[i] = 0;
124 }
125 phys->nr_cells = max_nr_cells;
126 return max_nr_cells;
127 }
128 }
129
130 int
131 generic_device_unit_encode(device *bus,
132 const device_unit *phys,
133 char *buf,
134 int sizeof_buf)
135 {
136 int i;
137 int len;
138 char *pos = buf;
139 /* skip leading zero's */
140 for (i = 0; i < phys->nr_cells; i++) {
141 if (phys->cells[i] != 0)
142 break;
143 }
144 /* don't output anything if empty */
145 if (phys->nr_cells == 0) {
146 strcpy(pos, "");
147 len = 0;
148 }
149 else if (i == phys->nr_cells) {
150 /* all zero */
151 strcpy(pos, "0");
152 len = 1;
153 }
154 else {
155 for (; i < phys->nr_cells; i++) {
156 if (pos != buf) {
157 strcat(pos, ",");
158 pos = strchr(pos, '\0');
159 }
160 if (phys->cells[i] < 10)
161 sprintf(pos, "%ld", (unsigned long)phys->cells[i]);
162 else
163 sprintf(pos, "0x%lx", (unsigned long)phys->cells[i]);
164 pos = strchr(pos, '\0');
165 }
166 len = pos - buf;
167 }
168 if (len >= sizeof_buf)
169 error("generic_unit_encode - buffer overflow\n");
170 return len;
171 }
172
173 int
174 generic_device_address_to_attach_address(device *me,
175 const device_unit *address,
176 int *attach_space,
177 unsigned_word *attach_address,
178 device *client)
179 {
180 int i;
181 for (i = 0; i < address->nr_cells - 2; i++) {
182 if (address->cells[i] != 0)
183 device_error(me, "Only 32bit addresses supported");
184 }
185 if (address->nr_cells >= 2)
186 *attach_space = address->cells[address->nr_cells - 2];
187 else
188 *attach_space = 0;
189 *attach_address = address->cells[address->nr_cells - 1];
190 return 1;
191 }
192
193 int
194 generic_device_size_to_attach_size(device *me,
195 const device_unit *size,
196 unsigned *nr_bytes,
197 device *client)
198 {
199 int i;
200 for (i = 0; i < size->nr_cells - 1; i++) {
201 if (size->cells[i] != 0)
202 device_error(me, "Only 32bit sizes supported");
203 }
204 *nr_bytes = size->cells[0];
205 return *nr_bytes;
206 }
207
208
209 /* ignore/passthrough versions of each function */
210
211 void
212 passthrough_device_address_attach(device *me,
213 attach_type attach,
214 int space,
215 unsigned_word addr,
216 unsigned nr_bytes,
217 access_type access,
218 device *client) /*callback/default*/
219 {
220 device_attach_address(device_parent(me), attach,
221 space, addr, nr_bytes,
222 access,
223 client);
224 }
225
226 void
227 passthrough_device_address_detach(device *me,
228 attach_type attach,
229 int space,
230 unsigned_word addr,
231 unsigned nr_bytes,
232 access_type access,
233 device *client) /*callback/default*/
234 {
235 device_detach_address(device_parent(me), attach,
236 space, addr, nr_bytes, access,
237 client);
238 }
239
240 unsigned
241 passthrough_device_dma_read_buffer(device *me,
242 void *dest,
243 int space,
244 unsigned_word addr,
245 unsigned nr_bytes)
246 {
247 return device_dma_read_buffer(device_parent(me), dest,
248 space, addr, nr_bytes);
249 }
250
251 unsigned
252 passthrough_device_dma_write_buffer(device *me,
253 const void *source,
254 int space,
255 unsigned_word addr,
256 unsigned nr_bytes,
257 int violate_read_only_section)
258 {
259 return device_dma_write_buffer(device_parent(me), source,
260 space, addr,
261 nr_bytes,
262 violate_read_only_section);
263 }
264
265 int
266 ignore_device_unit_decode(device *me,
267 const char *unit,
268 device_unit *phys)
269 {
270 memset(phys, 0, sizeof(device_unit));
271 return 0;
272 }
273
274
275 static const device_callbacks passthrough_callbacks = {
276 { NULL, }, /* init */
277 { passthrough_device_address_attach,
278 passthrough_device_address_detach, },
279 { NULL, }, /* IO */
280 { passthrough_device_dma_read_buffer, passthrough_device_dma_write_buffer, },
281 { NULL, }, /* interrupt */
282 { generic_device_unit_decode,
283 generic_device_unit_encode, },
284 };
285
286
287 static const device_descriptor ob_device_table[] = {
288 /* standard OpenBoot devices */
289 { "aliases", NULL, &passthrough_callbacks },
290 { "options", NULL, &passthrough_callbacks },
291 { "chosen", NULL, &passthrough_callbacks },
292 { "packages", NULL, &passthrough_callbacks },
293 { "cpus", NULL, &passthrough_callbacks },
294 { "openprom", NULL, &passthrough_callbacks },
295 { "init", NULL, &passthrough_callbacks },
296 { NULL },
297 };
298
299 const device_descriptor *const device_table[] = {
300 ob_device_table,
301 #include "hw.c"
302 NULL,
303 };
304
305
306 #endif /* _DEVICE_TABLE_C_ */