Home | History | Annotate | Line # | Download | only in ppc
hw_shm.c revision 1.2
      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.1  christos typedef struct _hw_shm_device {
     81  1.1  christos   unsigned_word physical_address;
     82  1.1  christos   char *shm_address;
     83  1.1  christos   unsigned sizeof_memory;
     84  1.1  christos   key_t key;
     85  1.1  christos   int id;
     86  1.1  christos } hw_shm_device;
     87  1.1  christos 
     88  1.1  christos static void
     89  1.1  christos hw_shm_init_data(device *me)
     90  1.1  christos {
     91  1.1  christos   hw_shm_device *shm = (hw_shm_device*)device_data(me);
     92  1.1  christos   reg_property_spec reg;
     93  1.1  christos   int i;
     94  1.1  christos 
     95  1.1  christos   /* Obtain the Key Value */
     96  1.1  christos   if (device_find_property(me, "key") == NULL)
     97  1.1  christos     error("shm_init_data() required key property is missing\n");
     98  1.1  christos 
     99  1.1  christos   shm->key = (key_t) device_find_integer_property(me, "key");
    100  1.2  christos   DTRACE(shm, ("shm key (0x%08jx)\n", (intmax_t)shm->key) );
    101  1.1  christos 
    102  1.1  christos   /* Figure out where this memory is in address space and how long it is */
    103  1.1  christos   if ( !device_find_reg_array_property(me, "reg", 0, &reg) )
    104  1.1  christos     error("hw_shm_init_data() no address registered\n");
    105  1.1  christos 
    106  1.1  christos   /* Determine the address and length being as paranoid as possible */
    107  1.1  christos   shm->physical_address = 0xffffffff;
    108  1.1  christos   shm->sizeof_memory = 0xffffffff;
    109  1.1  christos 
    110  1.1  christos   for ( i=0 ; i<reg.address.nr_cells; i++ ) {
    111  1.1  christos     if (reg.address.cells[0] == 0 && reg.size.cells[0] == 0)
    112  1.1  christos       continue;
    113  1.1  christos 
    114  1.1  christos     if ( shm->physical_address != 0xffffffff )
    115  1.1  christos       device_error(me, "Only single celled address ranges supported\n");
    116  1.1  christos 
    117  1.1  christos     shm->physical_address = reg.address.cells[i];
    118  1.1  christos     DTRACE(shm, ("shm physical_address=0x%x\n", shm->physical_address));
    119  1.1  christos 
    120  1.1  christos     shm->sizeof_memory = reg.size.cells[i];
    121  1.1  christos     DTRACE(shm, ("shm length=0x%x\n", shm->sizeof_memory));
    122  1.1  christos   }
    123  1.1  christos 
    124  1.1  christos   if ( shm->physical_address == 0xffffffff )
    125  1.1  christos     device_error(me, "Address not specified\n" );
    126  1.1  christos 
    127  1.1  christos   if ( shm->sizeof_memory == 0xffffffff )
    128  1.1  christos     device_error(me, "Length not specified\n" );
    129  1.1  christos 
    130  1.1  christos   /* Now actually attach to or create the shared memory area */
    131  1.1  christos   shm->id = shmget(shm->key, shm->sizeof_memory, IPC_CREAT | 0660);
    132  1.1  christos   if (shm->id == -1)
    133  1.1  christos     error("hw_shm_init_data() shmget failed\n");
    134  1.1  christos 
    135  1.1  christos   shm->shm_address = shmat(shm->id, (char *)0, SHM_RND);
    136  1.1  christos   if (shm->shm_address == (void *)-1)
    137  1.1  christos     error("hw_shm_init_data() shmat failed\n");
    138  1.1  christos }
    139  1.1  christos 
    140  1.1  christos static void
    141  1.1  christos hw_shm_attach_address_callback(device *me,
    142  1.1  christos 				attach_type attach,
    143  1.1  christos 				int space,
    144  1.1  christos 				unsigned_word addr,
    145  1.1  christos 				unsigned nr_bytes,
    146  1.1  christos 				access_type access,
    147  1.1  christos 				device *client) /*callback/default*/
    148  1.1  christos {
    149  1.1  christos   if (space != 0)
    150  1.1  christos     error("shm_attach_address_callback() invalid address space\n");
    151  1.1  christos 
    152  1.1  christos   if (nr_bytes == 0)
    153  1.1  christos     error("shm_attach_address_callback() invalid size\n");
    154  1.1  christos }
    155  1.1  christos 
    156  1.1  christos 
    157  1.1  christos static unsigned
    158  1.1  christos hw_shm_io_read_buffer(device *me,
    159  1.1  christos 			 void *dest,
    160  1.1  christos 			 int space,
    161  1.1  christos 			 unsigned_word addr,
    162  1.1  christos 			 unsigned nr_bytes,
    163  1.1  christos 			 cpu *processor,
    164  1.1  christos 			 unsigned_word cia)
    165  1.1  christos {
    166  1.1  christos   hw_shm_device *shm = (hw_shm_device*)device_data(me);
    167  1.1  christos 
    168  1.1  christos   /* do we need to worry about out of range addresses? */
    169  1.1  christos 
    170  1.1  christos   DTRACE(shm, ("read %p %x %x %x\n", \
    171  1.1  christos      shm->shm_address, shm->physical_address, addr, nr_bytes) );
    172  1.1  christos 
    173  1.1  christos   memcpy(dest, &shm->shm_address[addr - shm->physical_address], nr_bytes);
    174  1.1  christos   return nr_bytes;
    175  1.1  christos }
    176  1.1  christos 
    177  1.1  christos 
    178  1.1  christos static unsigned
    179  1.1  christos hw_shm_io_write_buffer(device *me,
    180  1.1  christos 			  const void *source,
    181  1.1  christos 			  int space,
    182  1.1  christos 			  unsigned_word addr,
    183  1.1  christos 			  unsigned nr_bytes,
    184  1.1  christos 			  cpu *processor,
    185  1.1  christos 			  unsigned_word cia)
    186  1.1  christos {
    187  1.1  christos   hw_shm_device *shm = (hw_shm_device*)device_data(me);
    188  1.1  christos 
    189  1.1  christos   /* do we need to worry about out of range addresses? */
    190  1.1  christos 
    191  1.1  christos   DTRACE(shm, ("write %p %x %x %x\n", \
    192  1.1  christos      shm->shm_address, shm->physical_address, addr, nr_bytes) );
    193  1.1  christos 
    194  1.1  christos   memcpy(&shm->shm_address[addr - shm->physical_address], source, nr_bytes);
    195  1.1  christos   return nr_bytes;
    196  1.1  christos }
    197  1.1  christos 
    198  1.1  christos static device_callbacks const hw_shm_callbacks = {
    199  1.1  christos   { generic_device_init_address, hw_shm_init_data },
    200  1.1  christos   { hw_shm_attach_address_callback, }, /* address */
    201  1.1  christos   { hw_shm_io_read_buffer,
    202  1.1  christos     hw_shm_io_write_buffer }, /* IO */
    203  1.1  christos   { NULL, }, /* DMA */
    204  1.1  christos   { NULL, }, /* interrupt */
    205  1.1  christos   { NULL, }, /* unit */
    206  1.1  christos   NULL,
    207  1.1  christos };
    208  1.1  christos 
    209  1.1  christos static void *
    210  1.1  christos hw_shm_create(const char *name,
    211  1.1  christos 		 const device_unit *unit_address,
    212  1.1  christos 		 const char *args)
    213  1.1  christos {
    214  1.1  christos   hw_shm_device *shm = ZALLOC(hw_shm_device);
    215  1.1  christos   return shm;
    216  1.1  christos }
    217  1.1  christos 
    218  1.1  christos 
    219  1.1  christos 
    220  1.1  christos const device_descriptor hw_shm_device_descriptor[] = {
    221  1.1  christos   { "shm", hw_shm_create, &hw_shm_callbacks },
    222  1.1  christos   { NULL },
    223  1.1  christos };
    224  1.1  christos 
    225  1.1  christos #endif /* _HW_SHM_C_ */
    226