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