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 2 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #ifndef _DEVICE_TABLE_C_
23 #define _DEVICE_TABLE_C_
24
25 #include "device_table.h"
26
27 #if HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30
31 #include <ctype.h>
32
33
34 /* Helper functions */
35
36
37 /* Go through the devices various reg properties for those that
38 specify attach addresses */
39
40
41 void
generic_device_init_address(device * me)42 generic_device_init_address(device *me)
43 {
44 static const char *(reg_property_names[]) = {
45 "attach-addresses",
46 "assigned-addresses",
47 "reg",
48 "alternate-reg" ,
49 NULL
50 };
51 const char **reg_property_name;
52 int nr_valid_reg_properties = 0;
53 for (reg_property_name = reg_property_names;
54 *reg_property_name != NULL;
55 reg_property_name++) {
56 if (device_find_property(me, *reg_property_name) != NULL) {
57 reg_property_spec reg;
58 int reg_entry;
59 for (reg_entry = 0;
60 device_find_reg_array_property(me, *reg_property_name, reg_entry,
61 ®);
62 reg_entry++) {
63 unsigned_word attach_address;
64 int attach_space;
65 unsigned attach_size;
66 if (!device_address_to_attach_address(device_parent(me),
67 ®.address,
68 &attach_space, &attach_address,
69 me))
70 continue;
71 if (!device_size_to_attach_size(device_parent(me),
72 ®.size,
73 &attach_size, me))
74 continue;
75 device_attach_address(device_parent(me),
76 attach_callback,
77 attach_space, attach_address, attach_size,
78 access_read_write_exec,
79 me);
80 nr_valid_reg_properties++;
81 }
82 /* if first option matches don't try for any others */
83 if (reg_property_name == reg_property_names)
84 break;
85 }
86 }
87 }
88
89 int
generic_device_unit_decode(device * bus,const char * unit,device_unit * phys)90 generic_device_unit_decode(device *bus,
91 const char *unit,
92 device_unit *phys)
93 {
94 memset(phys, 0, sizeof(device_unit));
95 if (unit == NULL)
96 return 0;
97 else {
98 int nr_cells = 0;
99 const int max_nr_cells = device_nr_address_cells(bus);
100 while (1) {
101 char *end = NULL;
102 unsigned long val;
103 val = strtoul(unit, &end, 0);
104 /* parse error? */
105 if (unit == end)
106 return -1;
107 /* two many cells? */
108 if (nr_cells >= max_nr_cells)
109 return -1;
110 /* save it */
111 phys->cells[nr_cells] = val;
112 nr_cells++;
113 unit = end;
114 /* more to follow? */
115 if (isspace(*unit) || *unit == '\0')
116 break;
117 if (*unit != ',')
118 return -1;
119 unit++;
120 }
121 if (nr_cells < max_nr_cells) {
122 /* shift everything to correct position */
123 int i;
124 for (i = 1; i <= nr_cells; i++)
125 phys->cells[max_nr_cells - i] = phys->cells[nr_cells - i];
126 for (i = 0; i < (max_nr_cells - nr_cells); i++)
127 phys->cells[i] = 0;
128 }
129 phys->nr_cells = max_nr_cells;
130 return max_nr_cells;
131 }
132 }
133
134 int
generic_device_unit_encode(device * bus,const device_unit * phys,char * buf,int sizeof_buf)135 generic_device_unit_encode(device *bus,
136 const device_unit *phys,
137 char *buf,
138 int sizeof_buf)
139 {
140 int i;
141 int len;
142 char *pos = buf;
143 /* skip leading zero's */
144 for (i = 0; i < phys->nr_cells; i++) {
145 if (phys->cells[i] != 0)
146 break;
147 }
148 /* don't output anything if empty */
149 if (phys->nr_cells == 0) {
150 strcpy(pos, "");
151 len = 0;
152 }
153 else if (i == phys->nr_cells) {
154 /* all zero */
155 strcpy(pos, "0");
156 len = 1;
157 }
158 else {
159 for (; i < phys->nr_cells; i++) {
160 if (pos != buf) {
161 strcat(pos, ",");
162 pos = strchr(pos, '\0');
163 }
164 if (phys->cells[i] < 10)
165 sprintf(pos, "%ld", (unsigned long)phys->cells[i]);
166 else
167 sprintf(pos, "0x%lx", (unsigned long)phys->cells[i]);
168 pos = strchr(pos, '\0');
169 }
170 len = pos - buf;
171 }
172 if (len >= sizeof_buf)
173 error("generic_unit_encode - buffer overflow\n");
174 return len;
175 }
176
177 int
generic_device_address_to_attach_address(device * me,const device_unit * address,int * attach_space,unsigned_word * attach_address,device * client)178 generic_device_address_to_attach_address(device *me,
179 const device_unit *address,
180 int *attach_space,
181 unsigned_word *attach_address,
182 device *client)
183 {
184 int i;
185 for (i = 0; i < address->nr_cells - 2; i++) {
186 if (address->cells[i] != 0)
187 device_error(me, "Only 32bit addresses supported");
188 }
189 if (address->nr_cells >= 2)
190 *attach_space = address->cells[address->nr_cells - 2];
191 else
192 *attach_space = 0;
193 *attach_address = address->cells[address->nr_cells - 1];
194 return 1;
195 }
196
197 int
generic_device_size_to_attach_size(device * me,const device_unit * size,unsigned * nr_bytes,device * client)198 generic_device_size_to_attach_size(device *me,
199 const device_unit *size,
200 unsigned *nr_bytes,
201 device *client)
202 {
203 int i;
204 for (i = 0; i < size->nr_cells - 1; i++) {
205 if (size->cells[i] != 0)
206 device_error(me, "Only 32bit sizes supported");
207 }
208 *nr_bytes = size->cells[0];
209 return *nr_bytes;
210 }
211
212
213 /* ignore/passthrough versions of each function */
214
215 void
passthrough_device_address_attach(device * me,attach_type attach,int space,unsigned_word addr,unsigned nr_bytes,access_type access,device * client)216 passthrough_device_address_attach(device *me,
217 attach_type attach,
218 int space,
219 unsigned_word addr,
220 unsigned nr_bytes,
221 access_type access,
222 device *client) /*callback/default*/
223 {
224 device_attach_address(device_parent(me), attach,
225 space, addr, nr_bytes,
226 access,
227 client);
228 }
229
230 void
passthrough_device_address_detach(device * me,attach_type attach,int space,unsigned_word addr,unsigned nr_bytes,access_type access,device * client)231 passthrough_device_address_detach(device *me,
232 attach_type attach,
233 int space,
234 unsigned_word addr,
235 unsigned nr_bytes,
236 access_type access,
237 device *client) /*callback/default*/
238 {
239 device_detach_address(device_parent(me), attach,
240 space, addr, nr_bytes, access,
241 client);
242 }
243
244 unsigned
passthrough_device_dma_read_buffer(device * me,void * dest,int space,unsigned_word addr,unsigned nr_bytes)245 passthrough_device_dma_read_buffer(device *me,
246 void *dest,
247 int space,
248 unsigned_word addr,
249 unsigned nr_bytes)
250 {
251 return device_dma_read_buffer(device_parent(me), dest,
252 space, addr, nr_bytes);
253 }
254
255 unsigned
passthrough_device_dma_write_buffer(device * me,const void * source,int space,unsigned_word addr,unsigned nr_bytes,int violate_read_only_section)256 passthrough_device_dma_write_buffer(device *me,
257 const void *source,
258 int space,
259 unsigned_word addr,
260 unsigned nr_bytes,
261 int violate_read_only_section)
262 {
263 return device_dma_write_buffer(device_parent(me), source,
264 space, addr,
265 nr_bytes,
266 violate_read_only_section);
267 }
268
269 int
ignore_device_unit_decode(device * me,const char * unit,device_unit * phys)270 ignore_device_unit_decode(device *me,
271 const char *unit,
272 device_unit *phys)
273 {
274 memset(phys, 0, sizeof(device_unit));
275 return 0;
276 }
277
278
279 static const device_callbacks passthrough_callbacks = {
280 { NULL, }, /* init */
281 { passthrough_device_address_attach,
282 passthrough_device_address_detach, },
283 { NULL, }, /* IO */
284 { passthrough_device_dma_read_buffer, passthrough_device_dma_write_buffer, },
285 { NULL, }, /* interrupt */
286 { generic_device_unit_decode,
287 generic_device_unit_encode, },
288 };
289
290
291 static const device_descriptor ob_device_table[] = {
292 /* standard OpenBoot devices */
293 { "aliases", NULL, &passthrough_callbacks },
294 { "options", NULL, &passthrough_callbacks },
295 { "chosen", NULL, &passthrough_callbacks },
296 { "packages", NULL, &passthrough_callbacks },
297 { "cpus", NULL, &passthrough_callbacks },
298 { "openprom", NULL, &passthrough_callbacks },
299 { "init", NULL, &passthrough_callbacks },
300 { NULL },
301 };
302
303 const device_descriptor *const device_table[] = {
304 ob_device_table,
305 #include "hw.c"
306 NULL,
307 };
308
309
310 #endif /* _DEVICE_TABLE_C_ */
311