This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/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 /* that's all */
269 return adp_ok;
270 }
271
272 AdpErrs DevSW_Read(const DeviceDescr *device, const DevChanID type,
273 Packet **packet, bool block)
274 {
275 int read_err;
276 DevSWState *ds = device->SwitcherState;
277
278 /*
279 * To try to get information out of the device driver as
280 * quickly as possible, we try and read more packets, even
281 * if a completed packet is already available.
282 */
283
284 /*
285 * have we got a packet currently pending?
286 */
287 if (ds->ds_nextreadpacket == NULL)
288 /*
289 * no - set things up
290 */
291 if (initialise_read(ds) < 0) {
292 /*
293 * we failed to initialise the next packet, but can
294 * still return a packet that has already arrived.
295 */
296 *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
297 return adp_ok;
298 }
299 read_err = device->DeviceRead(&ds->ds_activeread, block);
300 switch (read_err) {
301 case 1:
302 /*
303 * driver has pulled in a complete packet, queue it up
304 */
305 #ifdef RET_DEBUG
306 printf("got a complete packet\n");
307 #endif
308 enqueue_packet(ds);
309 *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
310 return adp_ok;
311 case 0:
312 /*
313 * OK, return the head of the read queue for the given type
314 */
315 /* enqueue_packet(ds); */
316 *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
317 return adp_ok;
318 case -1:
319 #ifdef RET_DEBUG
320 printf("got a bad packet\n");
321 #endif
322 /* bad packet */
323 *packet = NULL;
324 return adp_bad_packet;
325 default:
326 panic("DevSW_Read: bad read status %d", read_err);
327 }
328 return 0; /* get rid of a potential compiler warning */
329 }
330
331
332 AdpErrs DevSW_FlushPendingWrite(const DeviceDescr *device)
333 {
334 struct DriverCall *dc;
335 struct data_packet *dp;
336
337 dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
338 dp = &dc->dc_packet;
339
340 /*
341 * try to flush any packet that is still being written
342 */
343 if (dp->data != NULL)
344 {
345 flush_packet(device, dc);
346
347 /* see if it has gone */
348 if (dp->data != NULL)
349 return adp_write_busy;
350 else
351 return adp_ok;
352 }
353 else
354 return adp_ok;
355 }
356
357
358 AdpErrs DevSW_Write(const DeviceDescr *device, Packet *packet, DevChanID type)
359 {
360 struct DriverCall *dc;
361 struct data_packet *dp;
362
363 dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
364 dp = &dc->dc_packet;
365
366 if (illegalDevChanID(type))
367 return adp_illegal_args;
368
369 /*
370 * try to flush any packet that is still being written
371 */
372 if (DevSW_FlushPendingWrite(device) != adp_ok)
373 return adp_write_busy;
374
375 /*
376 * we can take this packet - set things up, then try to get rid of it
377 */
378 initialise_write(dc, packet, type);
379 flush_packet(device, dc);
380
381 return adp_ok;
382 }
383
384 AdpErrs DevSW_Ioctl(const DeviceDescr *device, const int opcode, void *args)
385 {
386 return (device->DeviceIoctl(opcode, args) < 0) ? adp_failed : adp_ok;
387 }
388
389 bool DevSW_WriteFinished(const DeviceDescr *device)
390 {
391 struct DriverCall *dc;
392 struct data_packet *dp;
393
394 dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
395 dp = &dc->dc_packet;
396
397 return (dp == NULL || dp->data == NULL);
398 }
399
400 /* EOF devsw.c */
This page took 0.037995 seconds and 5 git commands to generate.