OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [sim/] [ppc/] [hw_sem.c] - Diff between revs 835 and 841

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 835 Rev 841
/*  This file is part of the program psim.
/*  This file is part of the program psim.
 
 
    Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com>
    Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com>
 
 
    This program is free software; you can redistribute it and/or modify
    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
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    (at your option) any later version.
 
 
    This program is distributed in the hope that it will be useful,
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    GNU General Public License for more details.
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 
    */
    */
 
 
 
 
#ifndef _HW_SEM_C_
#ifndef _HW_SEM_C_
#define _HW_SEM_C_
#define _HW_SEM_C_
 
 
#include "device_table.h"
#include "device_table.h"
 
 
#ifdef HAVE_STRING_H
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#else
#else
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRINGS_H
#include <strings.h>
#include <strings.h>
#endif
#endif
#endif
#endif
 
 
#include <sys/ipc.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/sem.h>
 
 
#include <errno.h>
#include <errno.h>
 
 
/* DEVICE
/* DEVICE
 
 
 
 
   sem - provide access to a unix semaphore
   sem - provide access to a unix semaphore
 
 
 
 
   DESCRIPTION
   DESCRIPTION
 
 
 
 
   This device implements an interface to a unix semaphore.
   This device implements an interface to a unix semaphore.
 
 
 
 
   PROPERTIES
   PROPERTIES
 
 
 
 
   reg = <address> <size> (required)
   reg = <address> <size> (required)
 
 
   Determine where the memory lives in the parents address space.
   Determine where the memory lives in the parents address space.
 
 
   key = <integer> (required)
   key = <integer> (required)
 
 
   This is the key of the unix semaphore.
   This is the key of the unix semaphore.
 
 
   EXAMPLES
   EXAMPLES
 
 
 
 
   Enable tracing of the sem:
   Enable tracing of the sem:
 
 
   |  bash$ psim -t sem-device \
   |  bash$ psim -t sem-device \
 
 
 
 
   Configure a UNIX semaphore using key 0x12345678 mapped into psim
   Configure a UNIX semaphore using key 0x12345678 mapped into psim
   address space at 0xfff00000:
   address space at 0xfff00000:
 
 
   |  -o '/sem@0xfff00000/reg 0xfff00000 0x80000' \
   |  -o '/sem@0xfff00000/reg 0xfff00000 0x80000' \
   |  -o '/sem@0xfff00000/key 0x12345678' \
   |  -o '/sem@0xfff00000/key 0x12345678' \
 
 
   sim/ppc/run -o '/#address-cells 1' \
   sim/ppc/run -o '/#address-cells 1' \
         -o '/sem@0xfff00000/reg 0xfff00000 12' \
         -o '/sem@0xfff00000/reg 0xfff00000 12' \
         -o '/sem@0xfff00000/key 0x12345678' ../psim-hello/hello
         -o '/sem@0xfff00000/key 0x12345678' ../psim-hello/hello
 
 
   REGISTERS
   REGISTERS
 
 
   offset 0 - lock count
   offset 0 - lock count
   offset 4 - lock operation
   offset 4 - lock operation
   offset 8 - unlock operation
   offset 8 - unlock operation
 
 
   All reads return the current or resulting count.
   All reads return the current or resulting count.
 
 
   BUGS
   BUGS
 
 
   None known.
   None known.
 
 
   */
   */
 
 
typedef struct _hw_sem_device {
typedef struct _hw_sem_device {
  unsigned_word physical_address;
  unsigned_word physical_address;
  key_t key;
  key_t key;
  int id;
  int id;
  int initial;
  int initial;
  int count;
  int count;
} hw_sem_device;
} hw_sem_device;
 
 
#ifndef HAVE_UNION_SEMUN
#ifndef HAVE_UNION_SEMUN
union semun {
union semun {
  int val;
  int val;
  struct semid_ds *buf;
  struct semid_ds *buf;
  unsigned short int *array;
  unsigned short int *array;
#if defined(__linux__)
#if defined(__linux__)
  struct seminfo *__buf;
  struct seminfo *__buf;
#endif
#endif
};
};
#endif
#endif
 
 
static void
static void
hw_sem_init_data(device *me)
hw_sem_init_data(device *me)
{
{
  hw_sem_device *sem = (hw_sem_device*)device_data(me);
  hw_sem_device *sem = (hw_sem_device*)device_data(me);
  const device_unit *d;
  const device_unit *d;
  int status;
  int status;
  union semun help;
  union semun help;
 
 
  /* initialize the properties of the sem */
  /* initialize the properties of the sem */
 
 
  if (device_find_property(me, "key") == NULL)
  if (device_find_property(me, "key") == NULL)
    error("sem_init_data() required key property is missing\n");
    error("sem_init_data() required key property is missing\n");
 
 
  if (device_find_property(me, "value") == NULL)
  if (device_find_property(me, "value") == NULL)
    error("sem_init_data() required value property is missing\n");
    error("sem_init_data() required value property is missing\n");
 
 
  sem->key = (key_t) device_find_integer_property(me, "key");
  sem->key = (key_t) device_find_integer_property(me, "key");
  DTRACE(sem, ("semaphore key (%d)\n", sem->key) );
  DTRACE(sem, ("semaphore key (%d)\n", sem->key) );
 
 
  sem->initial = (int) device_find_integer_property(me, "value");
  sem->initial = (int) device_find_integer_property(me, "value");
  DTRACE(sem, ("semaphore initial value (%d)\n", sem->initial) );
  DTRACE(sem, ("semaphore initial value (%d)\n", sem->initial) );
 
 
  d = device_unit_address(me);
  d = device_unit_address(me);
  sem->physical_address = d->cells[ d->nr_cells-1 ];
  sem->physical_address = d->cells[ d->nr_cells-1 ];
  DTRACE(sem, ("semaphore physical_address=0x%x\n", sem->physical_address));
  DTRACE(sem, ("semaphore physical_address=0x%x\n", sem->physical_address));
 
 
  /* Now to initialize the semaphore */
  /* Now to initialize the semaphore */
 
 
  if ( sem->initial != -1 ) {
  if ( sem->initial != -1 ) {
 
 
    sem->id = semget(sem->key, 1, IPC_CREAT | 0660);
    sem->id = semget(sem->key, 1, IPC_CREAT | 0660);
    if (sem->id == -1)
    if (sem->id == -1)
      error("hw_sem_init_data() semget failed\n");
      error("hw_sem_init_data() semget failed\n");
 
 
    help.val = sem->initial;
    help.val = sem->initial;
    status = semctl( sem->id, 0, SETVAL, help );
    status = semctl( sem->id, 0, SETVAL, help );
    if (status == -1)
    if (status == -1)
      error("hw_sem_init_data() semctl -- set value failed\n");
      error("hw_sem_init_data() semctl -- set value failed\n");
 
 
  } else {
  } else {
    sem->id = semget(sem->key, 1, 0660);
    sem->id = semget(sem->key, 1, 0660);
    if (sem->id == -1)
    if (sem->id == -1)
      error("hw_sem_init_data() semget failed\n");
      error("hw_sem_init_data() semget failed\n");
  }
  }
 
 
  sem->count = semctl( sem->id, 0, GETVAL, help );
  sem->count = semctl( sem->id, 0, GETVAL, help );
  if (sem->count == -1)
  if (sem->count == -1)
    error("hw_sem_init_data() semctl -- get value failed\n");
    error("hw_sem_init_data() semctl -- get value failed\n");
  DTRACE(sem, ("semaphore OS value (%d)\n", sem->count) );
  DTRACE(sem, ("semaphore OS value (%d)\n", sem->count) );
}
}
 
 
static void
static void
hw_sem_attach_address_callback(device *me,
hw_sem_attach_address_callback(device *me,
                                attach_type attach,
                                attach_type attach,
                                int space,
                                int space,
                                unsigned_word addr,
                                unsigned_word addr,
                                unsigned nr_bytes,
                                unsigned nr_bytes,
                                access_type access,
                                access_type access,
                                device *client) /*callback/default*/
                                device *client) /*callback/default*/
{
{
  hw_sem_device *sem = (hw_sem_device*)device_data(me);
  hw_sem_device *sem = (hw_sem_device*)device_data(me);
 
 
  if (space != 0)
  if (space != 0)
    error("sem_attach_address_callback() invalid address space\n");
    error("sem_attach_address_callback() invalid address space\n");
 
 
  if (nr_bytes == 12)
  if (nr_bytes == 12)
    error("sem_attach_address_callback() invalid size\n");
    error("sem_attach_address_callback() invalid size\n");
 
 
  sem->physical_address = addr;
  sem->physical_address = addr;
  DTRACE(sem, ("semaphore physical_address=0x%x\n", addr));
  DTRACE(sem, ("semaphore physical_address=0x%x\n", addr));
}
}
 
 
static unsigned
static unsigned
hw_sem_io_read_buffer(device *me,
hw_sem_io_read_buffer(device *me,
                         void *dest,
                         void *dest,
                         int space,
                         int space,
                         unsigned_word addr,
                         unsigned_word addr,
                         unsigned nr_bytes,
                         unsigned nr_bytes,
                         cpu *processor,
                         cpu *processor,
                         unsigned_word cia)
                         unsigned_word cia)
{
{
  hw_sem_device *sem = (hw_sem_device*)device_data(me);
  hw_sem_device *sem = (hw_sem_device*)device_data(me);
  struct sembuf sb;
  struct sembuf sb;
  int status;
  int status;
  unsigned32 u32;
  unsigned32 u32;
  union semun help;
  union semun help;
 
 
  /* do we need to worry about out of range addresses? */
  /* do we need to worry about out of range addresses? */
 
 
  DTRACE(sem, ("semaphore read addr=0x%x length=%d\n", addr, nr_bytes));
  DTRACE(sem, ("semaphore read addr=0x%x length=%d\n", addr, nr_bytes));
 
 
  if (!(addr >= sem->physical_address && addr <= sem->physical_address + 11))
  if (!(addr >= sem->physical_address && addr <= sem->physical_address + 11))
    error("hw_sem_io_read_buffer() invalid address - out of range\n");
    error("hw_sem_io_read_buffer() invalid address - out of range\n");
 
 
  if ((addr % 4) != 0)
  if ((addr % 4) != 0)
    error("hw_sem_io_read_buffer() invalid address - alignment\n");
    error("hw_sem_io_read_buffer() invalid address - alignment\n");
 
 
  if (nr_bytes != 4)
  if (nr_bytes != 4)
    error("hw_sem_io_read_buffer() invalid length\n");
    error("hw_sem_io_read_buffer() invalid length\n");
 
 
  switch ( (addr - sem->physical_address) / 4 ) {
  switch ( (addr - sem->physical_address) / 4 ) {
 
 
    case 0:  /* OBTAIN CURRENT VALUE */
    case 0:  /* OBTAIN CURRENT VALUE */
      break;
      break;
 
 
    case 1:  /* LOCK */
    case 1:  /* LOCK */
      sb.sem_num = 0;
      sb.sem_num = 0;
      sb.sem_op  = -1;
      sb.sem_op  = -1;
      sb.sem_flg = 0;
      sb.sem_flg = 0;
 
 
      status = semop(sem->id, &sb, 1);
      status = semop(sem->id, &sb, 1);
      if (status == -1) {
      if (status == -1) {
        perror( "hw_sem.c: lock" );
        perror( "hw_sem.c: lock" );
        error("hw_sem_io_read_buffer() sem lock\n");
        error("hw_sem_io_read_buffer() sem lock\n");
      }
      }
 
 
      DTRACE(sem, ("semaphore lock %d\n", sem->count));
      DTRACE(sem, ("semaphore lock %d\n", sem->count));
      break;
      break;
 
 
    case 2: /* UNLOCK */
    case 2: /* UNLOCK */
      sb.sem_num = 0;
      sb.sem_num = 0;
      sb.sem_op  = 1;
      sb.sem_op  = 1;
      sb.sem_flg = 0;
      sb.sem_flg = 0;
 
 
      status = semop(sem->id, &sb, 1);
      status = semop(sem->id, &sb, 1);
      if (status == -1) {
      if (status == -1) {
        perror( "hw_sem.c: unlock" );
        perror( "hw_sem.c: unlock" );
        error("hw_sem_io_read_buffer() sem unlock\n");
        error("hw_sem_io_read_buffer() sem unlock\n");
      }
      }
      DTRACE(sem, ("semaphore unlock %d\n", sem->count));
      DTRACE(sem, ("semaphore unlock %d\n", sem->count));
      break;
      break;
 
 
    default:
    default:
      error("hw_sem_io_read_buffer() invalid address - unknown error\n");
      error("hw_sem_io_read_buffer() invalid address - unknown error\n");
      break;
      break;
  }
  }
 
 
  /* assume target is big endian */
  /* assume target is big endian */
  u32 = H2T_4(semctl( sem->id, 0, GETVAL, help ));
  u32 = H2T_4(semctl( sem->id, 0, GETVAL, help ));
 
 
  DTRACE(sem, ("semaphore OS value (%d)\n", u32) );
  DTRACE(sem, ("semaphore OS value (%d)\n", u32) );
  if (u32 == 0xffffffff) {
  if (u32 == 0xffffffff) {
    perror( "hw_sem.c: getval" );
    perror( "hw_sem.c: getval" );
    error("hw_sem_io_read_buffer() semctl -- get value failed\n");
    error("hw_sem_io_read_buffer() semctl -- get value failed\n");
  }
  }
 
 
  memcpy(dest, &u32, nr_bytes);
  memcpy(dest, &u32, nr_bytes);
  return nr_bytes;
  return nr_bytes;
 
 
}
}
 
 
static device_callbacks const hw_sem_callbacks = {
static device_callbacks const hw_sem_callbacks = {
  { generic_device_init_address, hw_sem_init_data },
  { generic_device_init_address, hw_sem_init_data },
  { hw_sem_attach_address_callback, }, /* address */
  { hw_sem_attach_address_callback, }, /* address */
  { hw_sem_io_read_buffer, NULL }, /* IO */
  { hw_sem_io_read_buffer, NULL }, /* IO */
  { NULL, }, /* DMA */
  { NULL, }, /* DMA */
  { NULL, }, /* interrupt */
  { NULL, }, /* interrupt */
  { NULL, }, /* unit */
  { NULL, }, /* unit */
  NULL,
  NULL,
};
};
 
 
static void *
static void *
hw_sem_create(const char *name,
hw_sem_create(const char *name,
                 const device_unit *unit_address,
                 const device_unit *unit_address,
                 const char *args)
                 const char *args)
{
{
  hw_sem_device *sem = ZALLOC(hw_sem_device);
  hw_sem_device *sem = ZALLOC(hw_sem_device);
  return sem;
  return sem;
}
}
 
 
const device_descriptor hw_sem_device_descriptor[] = {
const device_descriptor hw_sem_device_descriptor[] = {
  { "sem", hw_sem_create, &hw_sem_callbacks },
  { "sem", hw_sem_create, &hw_sem_callbacks },
  { NULL },
  { NULL },
};
};
 
 
#endif /* _HW_SEM_C_ */
#endif /* _HW_SEM_C_ */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.