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) 1997,2008, Joel Sherrill <joel (at) OARcorp.com>
      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.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.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 _HW_SHM_C_
     22  1.1  christos #define _HW_SHM_C_
     23  1.1  christos 
     24  1.1  christos #include "device_table.h"
     25  1.1  christos 
     26  1.1  christos #include <string.h>
     27  1.1  christos #include <sys/ipc.h>
     28  1.1  christos #include <sys/shm.h>
     29  1.1  christos 
     30  1.1  christos 
     31  1.1  christos /* DEVICE
     32  1.1  christos 
     33  1.1  christos 
     34  1.1  christos    shm - map unix shared memory into psim address space
     35  1.1  christos 
     36  1.1  christos 
     37  1.1  christos    DESCRIPTION
     38  1.1  christos 
     39  1.1  christos 
     40  1.1  christos    This device implements an area of memory which is mapped into UNIX
     41  1.1  christos    shared memory.
     42  1.1  christos 
     43  1.1  christos 
     44  1.1  christos    PROPERTIES
     45  1.1  christos 
     46  1.1  christos 
     47  1.1  christos    reg = <address> <size> (required)
     48  1.1  christos 
     49  1.1  christos    Determine where the memory lives in the parents address space.
     50  1.1  christos    The SHM area is assumed to be of the same length.
     51  1.1  christos 
     52  1.1  christos    key = <integer> (required)
     53  1.1  christos 
     54  1.1  christos    This is the key of the unix shared memory area.
     55  1.1  christos 
     56  1.1  christos    EXAMPLES
     57  1.1  christos 
     58  1.1  christos 
     59  1.1  christos    Enable tracing of the shm:
     60  1.1  christos 
     61  1.1  christos    |  bash$ psim -t shm-device \
     62  1.1  christos 
     63  1.1  christos 
     64  1.1  christos    Configure a 512 kilobytes of UNIX shared memory with the key 0x12345678
     65  1.1  christos    mapped into psim address space at 0x0c000000.
     66  1.1  christos 
     67  1.1  christos    |  -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
     68  1.1  christos    |  -o '/shm@0x0c000000/key 0x12345678' \
     69  1.1  christos 
     70  1.1  christos    sim/ppc/run -o '/#address-cells 1' \
     71  1.1  christos          -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
     72  1.1  christos          -o '/shm@0x0c000000/key 0x12345678' ../psim-hello/hello
     73  1.1  christos 
     74  1.1  christos    BUGS
     75  1.1  christos 
     76  1.1  christos    None known.
     77  1.1  christos 
     78  1.1  christos    */
     79  1.1  christos 
     80  1.3  christos #ifdef HAVE_SYSV_SHM
     81  1.3  christos 
     82  1.1  christos typedef struct _hw_shm_device {
     83  1.1  christos   unsigned_word physical_address;
     84  1.1  christos   char *shm_address;
     85  1.1  christos   unsigned sizeof_memory;
     86  1.1  christos   key_t key;
     87  1.1  christos   int id;
     88  1.1  christos } hw_shm_device;
     89  1.1  christos 
     90  1.1  christos static void
     91  1.1  christos hw_shm_init_data(device *me)
     92  1.1  christos {
     93  1.1  christos   hw_shm_device *shm = (hw_shm_device*)device_data(me);
     94  1.1  christos   reg_property_spec reg;
     95  1.1  christos   int i;
     96  1.1  christos 
     97  1.1  christos   /* Obtain the Key Value */
     98  1.1  christos   if (device_find_property(me, "key") == NULL)
     99  1.1  christos     error("shm_init_data() required key property is missing\n");
    100  1.1  christos 
    101  1.1  christos   shm->key = (key_t) device_find_integer_property(me, "key");
    102  1.2  christos   DTRACE(shm, ("shm key (0x%08jx)\n", (intmax_t)shm->key) );
    103  1.1  christos 
    104  1.1  christos   /* Figure out where this memory is in address space and how long it is */
    105  1.1  christos   if ( !device_find_reg_array_property(me, "reg", 0, &reg) )
    106  1.1  christos     error("hw_shm_init_data() no address registered\n");
    107  1.1  christos 
    108  1.1  christos   /* Determine the address and length being as paranoid as possible */
    109  1.1  christos   shm->physical_address = 0xffffffff;
    110  1.1  christos   shm->sizeof_memory = 0xffffffff;
    111  1.1  christos 
    112  1.1  christos   for ( i=0 ; i<reg.address.nr_cells; i++ ) {
    113  1.1  christos     if (reg.address.cells[0] == 0 && reg.size.cells[0] == 0)
    114  1.1  christos       continue;
    115  1.1  christos 
    116  1.1  christos     if ( shm->physical_address != 0xffffffff )
    117  1.1  christos       device_error(me, "Only single celled address ranges supported\n");
    118  1.1  christos 
    119  1.1  christos     shm->physical_address = reg.address.cells[i];
    120  1.1  christos     DTRACE(shm, ("shm physical_address=0x%x\n", shm->physical_address));
    121  1.1  christos 
    122  1.1  christos     shm->sizeof_memory = reg.size.cells[i];
    123  1.1  christos     DTRACE(shm, ("shm length=0x%x\n", shm->sizeof_memory));
    124  1.1  christos   }
    125  1.1  christos 
    126  1.1  christos   if ( shm->physical_address == 0xffffffff )
    127  1.1  christos     device_error(me, "Address not specified\n" );
    128  1.1  christos 
    129  1.1  christos   if ( shm->sizeof_memory == 0xffffffff )
    130  1.1  christos     device_error(me, "Length not specified\n" );
    131  1.1  christos 
    132  1.1  christos   /* Now actually attach to or create the shared memory area */
    133  1.1  christos   shm->id = shmget(shm->key, shm->sizeof_memory, IPC_CREAT | 0660);
    134  1.1  christos   if (shm->id == -1)
    135  1.1  christos     error("hw_shm_init_data() shmget failed\n");
    136  1.1  christos 
    137  1.1  christos   shm->shm_address = shmat(shm->id, (char *)0, SHM_RND);
    138  1.1  christos   if (shm->shm_address == (void *)-1)
    139  1.1  christos     error("hw_shm_init_data() shmat failed\n");
    140  1.1  christos }
    141  1.1  christos 
    142  1.1  christos static void
    143  1.1  christos hw_shm_attach_address_callback(device *me,
    144  1.1  christos 				attach_type attach,
    145  1.1  christos 				int space,
    146  1.1  christos 				unsigned_word addr,
    147  1.1  christos 				unsigned nr_bytes,
    148  1.1  christos 				access_type access,
    149  1.1  christos 				device *client) /*callback/default*/
    150  1.1  christos {
    151  1.1  christos   if (space != 0)
    152  1.1  christos     error("shm_attach_address_callback() invalid address space\n");
    153  1.1  christos 
    154  1.1  christos   if (nr_bytes == 0)
    155  1.1  christos     error("shm_attach_address_callback() invalid size\n");
    156  1.1  christos }
    157  1.1  christos 
    158  1.1  christos 
    159  1.1  christos static unsigned
    160  1.1  christos hw_shm_io_read_buffer(device *me,
    161  1.1  christos 			 void *dest,
    162  1.1  christos 			 int space,
    163  1.1  christos 			 unsigned_word addr,
    164  1.1  christos 			 unsigned nr_bytes,
    165  1.1  christos 			 cpu *processor,
    166  1.1  christos 			 unsigned_word cia)
    167  1.1  christos {
    168  1.1  christos   hw_shm_device *shm = (hw_shm_device*)device_data(me);
    169  1.1  christos 
    170  1.1  christos   /* do we need to worry about out of range addresses? */
    171  1.1  christos 
    172  1.1  christos   DTRACE(shm, ("read %p %x %x %x\n", \
    173  1.1  christos      shm->shm_address, shm->physical_address, addr, nr_bytes) );
    174  1.1  christos 
    175  1.1  christos   memcpy(dest, &shm->shm_address[addr - shm->physical_address], nr_bytes);
    176  1.1  christos   return nr_bytes;
    177  1.1  christos }
    178  1.1  christos 
    179  1.1  christos 
    180  1.1  christos static unsigned
    181  1.1  christos hw_shm_io_write_buffer(device *me,
    182  1.1  christos 			  const void *source,
    183  1.1  christos 			  int space,
    184  1.1  christos 			  unsigned_word addr,
    185  1.1  christos 			  unsigned nr_bytes,
    186  1.1  christos 			  cpu *processor,
    187  1.1  christos 			  unsigned_word cia)
    188  1.1  christos {
    189  1.1  christos   hw_shm_device *shm = (hw_shm_device*)device_data(me);
    190  1.1  christos 
    191  1.1  christos   /* do we need to worry about out of range addresses? */
    192  1.1  christos 
    193  1.1  christos   DTRACE(shm, ("write %p %x %x %x\n", \
    194  1.1  christos      shm->shm_address, shm->physical_address, addr, nr_bytes) );
    195  1.1  christos 
    196  1.1  christos   memcpy(&shm->shm_address[addr - shm->physical_address], source, nr_bytes);
    197  1.1  christos   return nr_bytes;
    198  1.1  christos }
    199  1.1  christos 
    200  1.1  christos static device_callbacks const hw_shm_callbacks = {
    201  1.1  christos   { generic_device_init_address, hw_shm_init_data },
    202  1.1  christos   { hw_shm_attach_address_callback, }, /* address */
    203  1.1  christos   { hw_shm_io_read_buffer,
    204  1.1  christos     hw_shm_io_write_buffer }, /* IO */
    205  1.1  christos   { NULL, }, /* DMA */
    206  1.1  christos   { NULL, }, /* interrupt */
    207  1.1  christos   { NULL, }, /* unit */
    208  1.1  christos   NULL,
    209  1.1  christos };
    210  1.1  christos 
    211  1.1  christos static void *
    212  1.1  christos hw_shm_create(const char *name,
    213  1.1  christos 		 const device_unit *unit_address,
    214  1.1  christos 		 const char *args)
    215  1.1  christos {
    216  1.1  christos   hw_shm_device *shm = ZALLOC(hw_shm_device);
    217  1.1  christos   return shm;
    218  1.1  christos }
    219  1.1  christos 
    220  1.1  christos 
    221  1.1  christos 
    222  1.1  christos const device_descriptor hw_shm_device_descriptor[] = {
    223  1.1  christos   { "shm", hw_shm_create, &hw_shm_callbacks },
    224  1.1  christos   { NULL },
    225  1.1  christos };
    226  1.1  christos 
    227  1.3  christos #else
    228  1.3  christos 
    229  1.3  christos const device_descriptor hw_shm_device_descriptor[] = {
    230  1.3  christos   { NULL },
    231  1.3  christos };
    232  1.3  christos 
    233  1.3  christos #endif /* HAVE_SYSV_SHM */
    234  1.3  christos 
    235  1.1  christos #endif /* _HW_SHM_C_ */
    236