]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/rdi-share/devsw.c
Initial creation of sourceware repository
[thirdparty/binutils-gdb.git] / gdb / rdi-share / devsw.c
1 /*
2 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
3 *
4 * This software may be freely used, copied, modified, and distributed
5 * provided that the above copyright notice is preserved in all copies of the
6 * software.
7 */
8
9 /* -*-C-*-
10 *
11 * $Revision$
12 * $Date$
13 *
14 */
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 #include "adp.h"
19 #include "hsys.h"
20 #include "rxtx.h"
21 #include "drivers.h"
22 #include "buffers.h"
23 #include "devclnt.h"
24 #include "adperr.h"
25 #include "devsw.h"
26 #include "hostchan.h"
27 #include "logging.h"
28
29 /*
30 * TODO: this should be adjustable - it could be done by defining
31 * a reason code for DevSW_Ioctl. It could even be a
32 * per-devicechannel parameter.
33 */
34 static const unsigned int allocsize = ADP_BUFFER_MIN_SIZE;
35
36 #define illegalDevChanID(type) ((type) >= DC_NUM_CHANNELS)
37
38 /**********************************************************************/
39
40 /*
41 * Function: initialise_read
42 * Purpose: Set up a read request for another packet
43 *
44 * Params:
45 * In/Out: ds State structure to be initialised
46 *
47 * Returns:
48 * OK: 0
49 * Error: -1
50 */
51 static int initialise_read(DevSWState *ds)
52 {
53 struct data_packet *dp;
54
55 /*
56 * try to claim the structure that will
57 * eventually hold the new packet.
58 */
59 if ((ds->ds_nextreadpacket = DevSW_AllocatePacket(allocsize)) == NULL)
60 return -1;
61
62 /*
63 * Calls into the device driver use the DriverCall structure: use
64 * the buffer we have just allocated, and declare its size. We
65 * are also obliged to clear the driver's context pointer.
66 */
67 dp = &ds->ds_activeread.dc_packet;
68 dp->buf_len = allocsize;
69 dp->data = ds->ds_nextreadpacket->pk_buffer;
70
71 ds->ds_activeread.dc_context = NULL;
72
73 return 0;
74 }
75
76 /*
77 * Function: initialise_write
78 * Purpose: Set up a write request for another packet
79 *
80 * Params:
81 * Input: packet The packet to be written
82 *
83 * type The type of the packet
84 *
85 * In/Out: dc The structure to be intialised
86 *
87 * Returns: Nothing
88 */
89 static void initialise_write(DriverCall *dc, Packet *packet, DevChanID type)
90 {
91 struct data_packet *dp = &dc->dc_packet;
92
93 dp->len = packet->pk_length;
94 dp->data = packet->pk_buffer;
95 dp->type = type;
96
97 /*
98 * we are required to clear the state structure for the driver
99 */
100 dc->dc_context = NULL;
101 }
102
103 /*
104 * Function: enqueue_packet
105 * Purpose: move a newly read packet onto the appropriate queue
106 * of read packets
107 *
108 * Params:
109 * In/Out: ds State structure with new packet
110 *
111 * Returns: Nothing
112 */
113 static void enqueue_packet(DevSWState *ds)
114 {
115 struct data_packet *dp = &ds->ds_activeread.dc_packet;
116 Packet *packet = ds->ds_nextreadpacket;
117
118 /*
119 * transfer the length
120 */
121 packet->pk_length = dp->len;
122
123 /*
124 * take this packet out of the incoming slot
125 */
126 ds->ds_nextreadpacket = NULL;
127
128 /*
129 * try to put it on the correct input queue
130 */
131 if (illegalDevChanID(dp->type))
132 {
133 /* this shouldn't happen */
134 WARN("Illegal type for Rx packet");
135 DevSW_FreePacket(packet);
136 }
137 else
138 Adp_addToQueue(&ds->ds_readqueue[dp->type], packet);
139 }
140
141 /*
142 * Function: flush_packet
143 * Purpose: Send a packet to the device driver
144 *
145 * Params:
146 * Input: device The device to be written to
147 *
148 * In/Out: dc Describes the packet to be sent
149 *
150 * Returns: Nothing
151 *
152 * Post-conditions: If the whole packet was accepted by the device
153 * driver, then dc->dc_packet.data will be
154 * set to NULL.
155 */
156 static void flush_packet(const DeviceDescr *device, DriverCall *dc)
157 {
158 if (device->DeviceWrite(dc) > 0)
159 /*
160 * the whole packet was swallowed
161 */
162 dc->dc_packet.data = NULL;
163 }
164
165 /**********************************************************************/
166
167 /*
168 * These are the externally visible functions. They are documented in
169 * devsw.h
170 */
171 Packet *DevSW_AllocatePacket(const unsigned int length)
172 {
173 Packet *pk;
174
175 if ((pk = malloc(sizeof(*pk))) == NULL)
176 {
177 WARN("malloc failure");
178 return NULL;
179 }
180
181 if ((pk->pk_buffer = malloc(length+CHAN_HEADER_SIZE)) == NULL)
182 {
183 WARN("malloc failure");
184 free(pk);
185 return NULL;
186 }
187
188 return pk;
189 }
190
191 void DevSW_FreePacket(Packet *pk)
192 {
193 free(pk->pk_buffer);
194 free(pk);
195 }
196
197 AdpErrs DevSW_Open(DeviceDescr *device, const char *name, const char *arg,
198 const DevChanID type)
199 {
200 DevSWState *ds;
201
202 /*
203 * is this the very first open call for this driver?
204 */
205 if ((ds = (DevSWState *)(device->SwitcherState)) == NULL)
206 {
207 /*
208 * yes, it is: initialise state
209 */
210 if ((ds = malloc(sizeof(*ds))) == NULL)
211 /* give up */
212 return adp_malloc_failure;
213
214 (void)memset(ds, 0, sizeof(*ds));
215 device->SwitcherState = (void *)ds;
216 }
217
218 /*
219 * check that we haven't already been opened for this type
220 */
221 if ((ds->ds_opendevchans & (1 << type)) != 0)
222 return adp_device_already_open;
223
224 /*
225 * if no opens have been done for this device, then do it now
226 */
227 if (ds->ds_opendevchans == 0)
228 if (device->DeviceOpen(name, arg) < 0)
229 return adp_device_open_failed;
230
231 /*
232 * open has finished
233 */
234 ds->ds_opendevchans |= (1 << type);
235 return adp_ok;
236 }
237
238 AdpErrs DevSW_Match(const DeviceDescr *device, const char *name,
239 const char *arg)
240 {
241 return (device->DeviceMatch(name, arg) == -1) ? adp_failed : adp_ok;
242 }
243
244 AdpErrs DevSW_Close(const DeviceDescr *device, const DevChanID type)
245 {
246 DevSWState *ds = (DevSWState *)(device->SwitcherState);
247 Packet *pk;
248
249 if ((ds->ds_opendevchans & (1 << type)) == 0)
250 return adp_device_not_open;
251
252 ds->ds_opendevchans &= ~(1 << type);
253
254 /*
255 * if this is the last close for this channel, then inform the driver
256 */
257 if (ds->ds_opendevchans == 0)
258 device->DeviceClose();
259
260 /*
261 * release all packets of the appropriate type
262 */
263 for (pk = Adp_removeFromQueue(&(ds->ds_readqueue[type]));
264 pk != NULL;
265 pk = Adp_removeFromQueue(&(ds->ds_readqueue[type])))
266 DevSW_FreePacket(pk);
267
268 /* Free memory */
269 free ((char *) device->SwitcherState);
270 device->SwitcherState = 0x0;
271
272 /* that's all */
273 return adp_ok;
274 }
275
276 AdpErrs DevSW_Read(const DeviceDescr *device, const DevChanID type,
277 Packet **packet, bool block)
278 {
279 int read_err;
280 DevSWState *ds = device->SwitcherState;
281
282 /*
283 * To try to get information out of the device driver as
284 * quickly as possible, we try and read more packets, even
285 * if a completed packet is already available.
286 */
287
288 /*
289 * have we got a packet currently pending?
290 */
291 if (ds->ds_nextreadpacket == NULL)
292 /*
293 * no - set things up
294 */
295 if (initialise_read(ds) < 0) {
296 /*
297 * we failed to initialise the next packet, but can
298 * still return a packet that has already arrived.
299 */
300 *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
301 return adp_ok;
302 }
303 read_err = device->DeviceRead(&ds->ds_activeread, block);
304 switch (read_err) {
305 case 1:
306 /*
307 * driver has pulled in a complete packet, queue it up
308 */
309 #ifdef RET_DEBUG
310 printf("got a complete packet\n");
311 #endif
312 enqueue_packet(ds);
313 *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
314 return adp_ok;
315 case 0:
316 /*
317 * OK, return the head of the read queue for the given type
318 */
319 /* enqueue_packet(ds); */
320 *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
321 return adp_ok;
322 case -1:
323 #ifdef RET_DEBUG
324 printf("got a bad packet\n");
325 #endif
326 /* bad packet */
327 *packet = NULL;
328 return adp_bad_packet;
329 default:
330 panic("DevSW_Read: bad read status %d", read_err);
331 }
332 return 0; /* get rid of a potential compiler warning */
333 }
334
335
336 AdpErrs DevSW_FlushPendingWrite(const DeviceDescr *device)
337 {
338 struct DriverCall *dc;
339 struct data_packet *dp;
340
341 dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
342 dp = &dc->dc_packet;
343
344 /*
345 * try to flush any packet that is still being written
346 */
347 if (dp->data != NULL)
348 {
349 flush_packet(device, dc);
350
351 /* see if it has gone */
352 if (dp->data != NULL)
353 return adp_write_busy;
354 else
355 return adp_ok;
356 }
357 else
358 return adp_ok;
359 }
360
361
362 AdpErrs DevSW_Write(const DeviceDescr *device, Packet *packet, DevChanID type)
363 {
364 struct DriverCall *dc;
365 struct data_packet *dp;
366
367 dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
368 dp = &dc->dc_packet;
369
370 if (illegalDevChanID(type))
371 return adp_illegal_args;
372
373 /*
374 * try to flush any packet that is still being written
375 */
376 if (DevSW_FlushPendingWrite(device) != adp_ok)
377 return adp_write_busy;
378
379 /*
380 * we can take this packet - set things up, then try to get rid of it
381 */
382 initialise_write(dc, packet, type);
383 flush_packet(device, dc);
384
385 return adp_ok;
386 }
387
388 AdpErrs DevSW_Ioctl(const DeviceDescr *device, const int opcode, void *args)
389 {
390 return (device->DeviceIoctl(opcode, args) < 0) ? adp_failed : adp_ok;
391 }
392
393 bool DevSW_WriteFinished(const DeviceDescr *device)
394 {
395 struct DriverCall *dc;
396 struct data_packet *dp;
397
398 dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
399 dp = &dc->dc_packet;
400
401 return (dp == NULL || dp->data == NULL);
402 }
403
404 /* EOF devsw.c */