/*  This file is part of the program psim.

    Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, see <http://www.gnu.org/licenses/>.
 
    */


#ifndef _HW_SHM_C_
#define _HW_SHM_C_

#include "device_table.h"

#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif

#include <sys/ipc.h>
#include <sys/shm.h>


/* DEVICE


   shm - map unix shared memory into psim address space


   DESCRIPTION


   This device implements an area of memory which is mapped into UNIX
   shared memory.


   PROPERTIES


   reg = <address> <size> (required)

   Determine where the memory lives in the parents address space.
   The SHM area is assumed to be of the same length.

   key = <integer> (required)

   This is the key of the unix shared memory area.

   EXAMPLES


   Enable tracing of the shm:

   |  bash$ psim -t shm-device \


   Configure a 512 kilobytes of UNIX shared memory with the key 0x12345678
   mapped into psim address space at 0x0c000000.

   |  -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
   |  -o '/shm@0x0c000000/key 0x12345678' \

   sim/ppc/run -o '/#address-cells 1' \
         -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
         -o '/shm@0x0c000000/key 0x12345678' ../psim-hello/hello

   BUGS

   None known.

   */

typedef struct _hw_shm_device {
  unsigned_word physical_address;
  char *shm_address;
  unsigned sizeof_memory;
  key_t key;
  int id;
} hw_shm_device;

static void
hw_shm_init_data(device *me)
{
  hw_shm_device *shm = (hw_shm_device*)device_data(me);
  const device_unit *d;
  reg_property_spec reg;
  int i;

  /* Obtain the Key Value */
  if (device_find_property(me, "key") == NULL)
    error("shm_init_data() required key property is missing\n");

  shm->key = (key_t) device_find_integer_property(me, "key");
  DTRACE(shm, ("shm key (0x%08x)\n", shm->key) );
  
  /* Figure out where this memory is in address space and how long it is */
  if ( !device_find_reg_array_property(me, "reg", 0, &reg) )
    error("hw_shm_init_data() no address registered\n");

  /* Determine the address and length being as paranoid as possible */
  shm->physical_address = 0xffffffff;
  shm->sizeof_memory = 0xffffffff;

  for ( i=0 ; i<reg.address.nr_cells; i++ ) {
    if (reg.address.cells[0] == 0 && reg.size.cells[0] == 0)
      continue;

    if ( shm->physical_address != 0xffffffff )
      device_error(me, "Only single celled address ranges supported\n");

    shm->physical_address = reg.address.cells[i];
    DTRACE(shm, ("shm physical_address=0x%x\n", shm->physical_address));

    shm->sizeof_memory = reg.size.cells[i];
    DTRACE(shm, ("shm length=0x%x\n", shm->sizeof_memory));
  }

  if ( shm->physical_address == 0xffffffff )
    device_error(me, "Address not specified\n" );

  if ( shm->sizeof_memory == 0xffffffff )
    device_error(me, "Length not specified\n" );

  /* Now actually attach to or create the shared memory area */
  shm->id = shmget(shm->key, shm->sizeof_memory, IPC_CREAT | 0660);
  if (shm->id == -1)
    error("hw_shm_init_data() shmget failed\n");

  shm->shm_address = shmat(shm->id, (char *)0, SHM_RND);
  if (shm->shm_address == (void *)-1)
    error("hw_shm_init_data() shmat failed\n");
}

static void
hw_shm_attach_address_callback(device *me,
				attach_type attach,
				int space,
				unsigned_word addr,
				unsigned nr_bytes,
				access_type access,
				device *client) /*callback/default*/
{
  hw_shm_device *shm = (hw_shm_device*)device_data(me);

  if (space != 0)
    error("shm_attach_address_callback() invalid address space\n");

  if (nr_bytes == 0)
    error("shm_attach_address_callback() invalid size\n");
}


static unsigned
hw_shm_io_read_buffer(device *me,
			 void *dest,
			 int space,
			 unsigned_word addr,
			 unsigned nr_bytes,
			 cpu *processor,
			 unsigned_word cia)
{
  hw_shm_device *shm = (hw_shm_device*)device_data(me);

  /* do we need to worry about out of range addresses? */

  DTRACE(shm, ("read %p %x %x %x\n", \
     shm->shm_address, shm->physical_address, addr, nr_bytes) );

  memcpy(dest, &shm->shm_address[addr - shm->physical_address], nr_bytes);
  return nr_bytes;
}


static unsigned
hw_shm_io_write_buffer(device *me,
			  const void *source,
			  int space,
			  unsigned_word addr,
			  unsigned nr_bytes,
			  cpu *processor,
			  unsigned_word cia)
{
  hw_shm_device *shm = (hw_shm_device*)device_data(me);

  /* do we need to worry about out of range addresses? */

  DTRACE(shm, ("write %p %x %x %x\n", \
     shm->shm_address, shm->physical_address, addr, nr_bytes) );

  memcpy(&shm->shm_address[addr - shm->physical_address], source, nr_bytes);
  return nr_bytes;
}

static device_callbacks const hw_shm_callbacks = {
  { generic_device_init_address, hw_shm_init_data },
  { hw_shm_attach_address_callback, }, /* address */
  { hw_shm_io_read_buffer,
    hw_shm_io_write_buffer }, /* IO */
  { NULL, }, /* DMA */
  { NULL, }, /* interrupt */
  { NULL, }, /* unit */
  NULL,
};

static void *
hw_shm_create(const char *name,
		 const device_unit *unit_address,
		 const char *args)
{
  hw_shm_device *shm = ZALLOC(hw_shm_device);
  return shm;
}



const device_descriptor hw_shm_device_descriptor[] = {
  { "shm", hw_shm_create, &hw_shm_callbacks },
  { NULL },
};

#endif /* _HW_SHM_C_ */
