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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [sim/] [ppc/] [hw_sem.c] - Blame information for rev 308

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com>
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
19
    */
20
 
21
 
22
#ifndef _HW_SEM_C_
23
#define _HW_SEM_C_
24
 
25
#include "device_table.h"
26
 
27
#ifdef HAVE_STRING_H
28
#include <string.h>
29
#else
30
#ifdef HAVE_STRINGS_H
31
#include <strings.h>
32
#endif
33
#endif
34
 
35
#include <sys/ipc.h>
36
#include <sys/sem.h>
37
 
38
#include <errno.h>
39
 
40
/* DEVICE
41
 
42
 
43
   sem - provide access to a unix semaphore
44
 
45
 
46
   DESCRIPTION
47
 
48
 
49
   This device implements an interface to a unix semaphore.
50
 
51
 
52
   PROPERTIES
53
 
54
 
55
   reg = <address> <size> (required)
56
 
57
   Determine where the memory lives in the parents address space.
58
 
59
   key = <integer> (required)
60
 
61
   This is the key of the unix semaphore.
62
 
63
   EXAMPLES
64
 
65
 
66
   Enable tracing of the sem:
67
 
68
   |  bash$ psim -t sem-device \
69
 
70
 
71
   Configure a UNIX semaphore using key 0x12345678 mapped into psim
72
   address space at 0xfff00000:
73
 
74
   |  -o '/sem@0xfff00000/reg 0xfff00000 0x80000' \
75
   |  -o '/sem@0xfff00000/key 0x12345678' \
76
 
77
   sim/ppc/run -o '/#address-cells 1' \
78
         -o '/sem@0xfff00000/reg 0xfff00000 12' \
79
         -o '/sem@0xfff00000/key 0x12345678' ../psim-hello/hello
80
 
81
   REGISTERS
82
 
83
   offset 0 - lock count
84
   offset 4 - lock operation
85
   offset 8 - unlock operation
86
 
87
   All reads return the current or resulting count.
88
 
89
   BUGS
90
 
91
   None known.
92
 
93
   */
94
 
95
typedef struct _hw_sem_device {
96
  unsigned_word physical_address;
97
  key_t key;
98
  int id;
99
  int initial;
100
  int count;
101
} hw_sem_device;
102
 
103
#ifndef HAVE_UNION_SEMUN
104
union semun {
105
  int val;
106
  struct semid_ds *buf;
107
  unsigned short int *array;
108
#if defined(__linux__)
109
  struct seminfo *__buf;
110
#endif
111
};
112
#endif
113
 
114
static void
115
hw_sem_init_data(device *me)
116
{
117
  hw_sem_device *sem = (hw_sem_device*)device_data(me);
118
  const device_unit *d;
119
  int status;
120
  union semun help;
121
 
122
  /* initialize the properties of the sem */
123
 
124
  if (device_find_property(me, "key") == NULL)
125
    error("sem_init_data() required key property is missing\n");
126
 
127
  if (device_find_property(me, "value") == NULL)
128
    error("sem_init_data() required value property is missing\n");
129
 
130
  sem->key = (key_t) device_find_integer_property(me, "key");
131
  DTRACE(sem, ("semaphore key (%d)\n", sem->key) );
132
 
133
  sem->initial = (int) device_find_integer_property(me, "value");
134
  DTRACE(sem, ("semaphore initial value (%d)\n", sem->initial) );
135
 
136
  d = device_unit_address(me);
137
  sem->physical_address = d->cells[ d->nr_cells-1 ];
138
  DTRACE(sem, ("semaphore physical_address=0x%x\n", sem->physical_address));
139
 
140
  /* Now to initialize the semaphore */
141
 
142
  if ( sem->initial != -1 ) {
143
 
144
    sem->id = semget(sem->key, 1, IPC_CREAT | 0660);
145
    if (sem->id == -1)
146
      error("hw_sem_init_data() semget failed\n");
147
 
148
    help.val = sem->initial;
149
    status = semctl( sem->id, 0, SETVAL, help );
150
    if (status == -1)
151
      error("hw_sem_init_data() semctl -- set value failed\n");
152
 
153
  } else {
154
    sem->id = semget(sem->key, 1, 0660);
155
    if (sem->id == -1)
156
      error("hw_sem_init_data() semget failed\n");
157
  }
158
 
159
  sem->count = semctl( sem->id, 0, GETVAL, help );
160
  if (sem->count == -1)
161
    error("hw_sem_init_data() semctl -- get value failed\n");
162
  DTRACE(sem, ("semaphore OS value (%d)\n", sem->count) );
163
}
164
 
165
static void
166
hw_sem_attach_address_callback(device *me,
167
                                attach_type attach,
168
                                int space,
169
                                unsigned_word addr,
170
                                unsigned nr_bytes,
171
                                access_type access,
172
                                device *client) /*callback/default*/
173
{
174
  hw_sem_device *sem = (hw_sem_device*)device_data(me);
175
 
176
  if (space != 0)
177
    error("sem_attach_address_callback() invalid address space\n");
178
 
179
  if (nr_bytes == 12)
180
    error("sem_attach_address_callback() invalid size\n");
181
 
182
  sem->physical_address = addr;
183
  DTRACE(sem, ("semaphore physical_address=0x%x\n", addr));
184
}
185
 
186
static unsigned
187
hw_sem_io_read_buffer(device *me,
188
                         void *dest,
189
                         int space,
190
                         unsigned_word addr,
191
                         unsigned nr_bytes,
192
                         cpu *processor,
193
                         unsigned_word cia)
194
{
195
  hw_sem_device *sem = (hw_sem_device*)device_data(me);
196
  struct sembuf sb;
197
  int status;
198
  unsigned32 u32;
199
  union semun help;
200
 
201
  /* do we need to worry about out of range addresses? */
202
 
203
  DTRACE(sem, ("semaphore read addr=0x%x length=%d\n", addr, nr_bytes));
204
 
205
  if (!(addr >= sem->physical_address && addr <= sem->physical_address + 11))
206
    error("hw_sem_io_read_buffer() invalid address - out of range\n");
207
 
208
  if ((addr % 4) != 0)
209
    error("hw_sem_io_read_buffer() invalid address - alignment\n");
210
 
211
  if (nr_bytes != 4)
212
    error("hw_sem_io_read_buffer() invalid length\n");
213
 
214
  switch ( (addr - sem->physical_address) / 4 ) {
215
 
216
    case 0:  /* OBTAIN CURRENT VALUE */
217
      break;
218
 
219
    case 1:  /* LOCK */
220
      sb.sem_num = 0;
221
      sb.sem_op  = -1;
222
      sb.sem_flg = 0;
223
 
224
      status = semop(sem->id, &sb, 1);
225
      if (status == -1) {
226
        perror( "hw_sem.c: lock" );
227
        error("hw_sem_io_read_buffer() sem lock\n");
228
      }
229
 
230
      DTRACE(sem, ("semaphore lock %d\n", sem->count));
231
      break;
232
 
233
    case 2: /* UNLOCK */
234
      sb.sem_num = 0;
235
      sb.sem_op  = 1;
236
      sb.sem_flg = 0;
237
 
238
      status = semop(sem->id, &sb, 1);
239
      if (status == -1) {
240
        perror( "hw_sem.c: unlock" );
241
        error("hw_sem_io_read_buffer() sem unlock\n");
242
      }
243
      DTRACE(sem, ("semaphore unlock %d\n", sem->count));
244
      break;
245
 
246
    default:
247
      error("hw_sem_io_read_buffer() invalid address - unknown error\n");
248
      break;
249
  }
250
 
251
  /* assume target is big endian */
252
  u32 = H2T_4(semctl( sem->id, 0, GETVAL, help ));
253
 
254
  DTRACE(sem, ("semaphore OS value (%d)\n", u32) );
255
  if (u32 == 0xffffffff) {
256
    perror( "hw_sem.c: getval" );
257
    error("hw_sem_io_read_buffer() semctl -- get value failed\n");
258
  }
259
 
260
  memcpy(dest, &u32, nr_bytes);
261
  return nr_bytes;
262
 
263
}
264
 
265
static device_callbacks const hw_sem_callbacks = {
266
  { generic_device_init_address, hw_sem_init_data },
267
  { hw_sem_attach_address_callback, }, /* address */
268
  { hw_sem_io_read_buffer, NULL }, /* IO */
269
  { NULL, }, /* DMA */
270
  { NULL, }, /* interrupt */
271
  { NULL, }, /* unit */
272
  NULL,
273
};
274
 
275
static void *
276
hw_sem_create(const char *name,
277
                 const device_unit *unit_address,
278
                 const char *args)
279
{
280
  hw_sem_device *sem = ZALLOC(hw_sem_device);
281
  return sem;
282
}
283
 
284
const device_descriptor hw_sem_device_descriptor[] = {
285
  { "sem", hw_sem_create, &hw_sem_callbacks },
286
  { NULL },
287
};
288
 
289
#endif /* _HW_SEM_C_ */

powered by: WebSVN 2.1.0

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