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