1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
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.
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.
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.
22 #ifndef _DEVICE_TABLE_C_
23 #define _DEVICE_TABLE_C_
25 #include "device_table.h"
34 /* Helper functions */
37 /* Go through the devices various reg properties for those that
38 specify attach addresses */
42 generic_device_init_address(device *me)
44 static const char *(reg_property_names[]) = {
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;
60 device_find_reg_array_property(me, *reg_property_name, reg_entry,
63 unsigned_word attach_address;
66 if (!device_address_to_attach_address(device_parent(me),
68 &attach_space, &attach_address,
71 if (!device_size_to_attach_size(device_parent(me),
75 device_attach_address(device_parent(me),
77 attach_space, attach_address, attach_size,
78 access_read_write_exec,
80 nr_valid_reg_properties++;
82 /* if first option matches don't try for any others */
83 if (reg_property_name == reg_property_names)
90 generic_device_unit_decode(device *bus,
94 memset(phys, 0, sizeof(device_unit));
99 const int max_nr_cells = device_nr_address_cells(bus);
103 val = strtoul(unit, &end, 0);
107 /* two many cells? */
108 if (nr_cells >= max_nr_cells)
111 phys->cells[nr_cells] = val;
114 /* more to follow? */
115 if (isspace(*unit) || *unit == '\0')
121 if (nr_cells < max_nr_cells) {
122 /* shift everything to correct position */
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++)
129 phys->nr_cells = max_nr_cells;
135 generic_device_unit_encode(device *bus,
136 const device_unit *phys,
143 /* skip leading zero's */
144 for (i = 0; i < phys->nr_cells; i++) {
145 if (phys->cells[i] != 0)
148 /* don't output anything if empty */
149 if (phys->nr_cells == 0) {
153 else if (i == phys->nr_cells) {
159 for (; i < phys->nr_cells; i++) {
162 pos = strchr(pos, '\0');
164 if (phys->cells[i] < 10)
165 sprintf(pos, "%ld", (unsigned long)phys->cells[i]);
167 sprintf(pos, "0x%lx", (unsigned long)phys->cells[i]);
168 pos = strchr(pos, '\0');
172 if (len >= sizeof_buf)
173 error("generic_unit_encode - buffer overflow\n");
178 generic_device_address_to_attach_address(device *me,
179 const device_unit *address,
181 unsigned_word *attach_address,
185 for (i = 0; i < address->nr_cells - 2; i++) {
186 if (address->cells[i] != 0)
187 device_error(me, "Only 32bit addresses supported");
189 if (address->nr_cells >= 2)
190 *attach_space = address->cells[address->nr_cells - 2];
193 *attach_address = address->cells[address->nr_cells - 1];
198 generic_device_size_to_attach_size(device *me,
199 const device_unit *size,
204 for (i = 0; i < size->nr_cells - 1; i++) {
205 if (size->cells[i] != 0)
206 device_error(me, "Only 32bit sizes supported");
208 *nr_bytes = size->cells[0];
213 /* ignore/passthrough versions of each function */
216 passthrough_device_address_attach(device *me,
222 device *client) /*callback/default*/
224 device_attach_address(device_parent(me), attach,
225 space, addr, nr_bytes,
231 passthrough_device_address_detach(device *me,
237 device *client) /*callback/default*/
239 device_detach_address(device_parent(me), attach,
240 space, addr, nr_bytes, access,
245 passthrough_device_dma_read_buffer(device *me,
251 return device_dma_read_buffer(device_parent(me), dest,
252 space, addr, nr_bytes);
256 passthrough_device_dma_write_buffer(device *me,
261 int violate_read_only_section)
263 return device_dma_write_buffer(device_parent(me), source,
266 violate_read_only_section);
270 ignore_device_unit_decode(device *me,
274 memset(phys, 0, sizeof(device_unit));
279 static const device_callbacks passthrough_callbacks = {
280 { NULL, }, /* init */
281 { passthrough_device_address_attach,
282 passthrough_device_address_detach, },
284 { passthrough_device_dma_read_buffer, passthrough_device_dma_write_buffer, },
285 { NULL, }, /* interrupt */
286 { generic_device_unit_decode,
287 generic_device_unit_encode, },
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 },
303 const device_descriptor *const device_table[] = {
310 #endif /* _DEVICE_TABLE_C_ */