import gdb-1999-11-08 snapshot
[deliverable/binutils-gdb.git] / gdb / rdi-share / devsw.c
CommitLineData
c906108c
SS
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>
5c44784c 17#include <string.h>
c906108c
SS
18
19#include "adp.h"
20#include "hsys.h"
21#include "rxtx.h"
22#include "drivers.h"
23#include "buffers.h"
24#include "devclnt.h"
25#include "adperr.h"
26#include "devsw.h"
27#include "hostchan.h"
28#include "logging.h"
29
5c44784c
JM
30static char *angelDebugFilename = NULL;
31static FILE *angelDebugLogFile = NULL;
32static int angelDebugLogEnable = 0;
33
34static void openLogFile ()
35{
36 time_t t;
37 struct tm lt;
38
39 if (angelDebugFilename == NULL || *angelDebugFilename =='\0')
40 return;
41
42 angelDebugLogFile = fopen (angelDebugFilename,"a");
43
44 if (!angelDebugLogFile)
45 {
46 fprintf (stderr,"Error opening log file '%s'\n",angelDebugFilename);
47 perror ("fopen");
48 }
49 else
11cf8741
JM
50 /* The following line is equivalent to: */
51 /* setlinebuf (angelDebugLogFile); */
52 setvbuf(angelDebugLogFile, (char *)NULL, _IOLBF, 0);
5c44784c
JM
53
54 time (&t);
55 fprintf (angelDebugLogFile,"ADP log file opened at %s\n",asctime(localtime(&t)));
56}
57
58
59static void closeLogFile (void)
60{
61 time_t t;
62 struct tm lt;
63
64 if (!angelDebugLogFile)
65 return;
66
67 time (&t);
68 fprintf (angelDebugLogFile,"ADP log file closed at %s\n",asctime(localtime(&t)));
69
70 fclose (angelDebugLogFile);
71 angelDebugLogFile = NULL;
72}
73
74void DevSW_SetLogEnable (int logEnableFlag)
75{
76 if (logEnableFlag && !angelDebugLogFile)
77 openLogFile ();
78 else if (!logEnableFlag && angelDebugLogFile)
79 closeLogFile ();
80
81 angelDebugLogEnable = logEnableFlag;
82}
83
84
85void DevSW_SetLogfile (const char *filename)
86{
87 closeLogFile ();
88
89 if (angelDebugFilename)
90 {
91 free (angelDebugFilename);
92 angelDebugFilename = NULL;
93 }
94
95 if (filename && *filename)
96 {
97 angelDebugFilename = strdup (filename);
98 if (angelDebugLogEnable)
99 openLogFile ();
100 }
101}
102
103
104#define WordAt(p) ((unsigned long) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)))
105
106static void dumpPacket(FILE *fp, char *label, struct data_packet *p)
107{
108 unsigned r;
109 int i;
110
111 if (!fp)
112 return;
113
114 fprintf(fp,"%s [T=%d L=%d] ",label,p->type,p->len);
115 for (i=0; i<p->len; ++i)
116 fprintf(fp,"%02x ",p->data[i]);
117 fprintf(fp,"\n");
118
119 r = WordAt(p->data+4);
120
121 fprintf(fp,"R=%08x ",r);
122 fprintf(fp,"%s ", r&0x80000000 ? "H<-T" : "H->T");
123
124 switch ((r>>16) & 0xff)
125 {
126 case CI_PRIVATE: fprintf(fp,"CI_PRIVATE: "); break;
127 case CI_HADP: fprintf(fp,"CI_HADP: "); break;
128 case CI_TADP: fprintf(fp,"CI_TADP: "); break;
129 case CI_HBOOT: fprintf(fp,"CI_HBOOT: "); break;
130 case CI_TBOOT: fprintf(fp,"CI_TBOOT: "); break;
131 case CI_CLIB: fprintf(fp,"CI_CLIB: "); break;
132 case CI_HUDBG: fprintf(fp,"CI_HUDBG: "); break;
133 case CI_TUDBG: fprintf(fp,"CI_TUDBG: "); break;
134 case CI_HTDCC: fprintf(fp,"CI_HTDCC: "); break;
135 case CI_TTDCC: fprintf(fp,"CI_TTDCC: "); break;
136 case CI_TLOG: fprintf(fp,"CI_TLOG: "); break;
137 default: fprintf(fp,"BadChan: "); break;
138 }
139
140 switch (r & 0xffffff)
141 {
142 case ADP_Booted: fprintf(fp," ADP_Booted "); break;
143#if defined(ADP_TargetResetIndication)
144 case ADP_TargetResetIndication: fprintf(fp," ADP_TargetResetIndication "); break;
145#endif
146 case ADP_Reboot: fprintf(fp," ADP_Reboot "); break;
147 case ADP_Reset: fprintf(fp," ADP_Reset "); break;
148#if defined(ADP_HostResetIndication)
149 case ADP_HostResetIndication: fprintf(fp," ADP_HostResetIndication "); break;
150#endif
151 case ADP_ParamNegotiate: fprintf(fp," ADP_ParamNegotiate "); break;
152 case ADP_LinkCheck: fprintf(fp," ADP_LinkCheck "); break;
153 case ADP_HADPUnrecognised: fprintf(fp," ADP_HADPUnrecognised "); break;
154 case ADP_Info: fprintf(fp," ADP_Info "); break;
155 case ADP_Control: fprintf(fp," ADP_Control "); break;
156 case ADP_Read: fprintf(fp," ADP_Read "); break;
157 case ADP_Write: fprintf(fp," ADP_Write "); break;
158 case ADP_CPUread: fprintf(fp," ADP_CPUread "); break;
159 case ADP_CPUwrite: fprintf(fp," ADP_CPUwrite "); break;
160 case ADP_CPread: fprintf(fp," ADP_CPread "); break;
161 case ADP_CPwrite: fprintf(fp," ADP_CPwrite "); break;
162 case ADP_SetBreak: fprintf(fp," ADP_SetBreak "); break;
163 case ADP_ClearBreak: fprintf(fp," ADP_ClearBreak "); break;
164 case ADP_SetWatch: fprintf(fp," ADP_SetWatch "); break;
165 case ADP_ClearWatch: fprintf(fp," ADP_ClearWatch "); break;
166 case ADP_Execute: fprintf(fp," ADP_Execute "); break;
167 case ADP_Step: fprintf(fp," ADP_Step "); break;
168 case ADP_InterruptRequest: fprintf(fp," ADP_InterruptRequest "); break;
169 case ADP_HW_Emulation: fprintf(fp," ADP_HW_Emulation "); break;
170 case ADP_ICEbreakerHADP: fprintf(fp," ADP_ICEbreakerHADP "); break;
171 case ADP_ICEman: fprintf(fp," ADP_ICEman "); break;
172 case ADP_Profile: fprintf(fp," ADP_Profile "); break;
173 case ADP_InitialiseApplication: fprintf(fp," ADP_InitialiseApplication "); break;
174 case ADP_End: fprintf(fp," ADP_End "); break;
175 case ADP_TADPUnrecognised: fprintf(fp," ADP_TADPUnrecognised "); break;
176 case ADP_Stopped: fprintf(fp," ADP_Stopped "); break;
177 case ADP_TDCC_ToHost: fprintf(fp," ADP_TDCC_ToHost "); break;
178 case ADP_TDCC_FromHost: fprintf(fp," ADP_TDCC_FromHost "); break;
179 default: fprintf(fp," BadReason "); break;
180 }
181
182 i = 20;
183
184 if (((r & 0xffffff) == ADP_CPUread ||
185 (r & 0xffffff) == ADP_CPUwrite) && (r&0x80000000)==0)
186 {
187 fprintf(fp,"%02x ", p->data[i]);
188 ++i;
189 }
190
191 for (; i<p->len; i+=4)
192 fprintf(fp,"%08x ",WordAt(p->data+i));
193
194 fprintf(fp,"\n");
195}
196
197
c906108c
SS
198/*
199 * TODO: this should be adjustable - it could be done by defining
200 * a reason code for DevSW_Ioctl. It could even be a
201 * per-devicechannel parameter.
202 */
203static const unsigned int allocsize = ADP_BUFFER_MIN_SIZE;
204
205#define illegalDevChanID(type) ((type) >= DC_NUM_CHANNELS)
206
207/**********************************************************************/
208
209/*
210 * Function: initialise_read
211 * Purpose: Set up a read request for another packet
212 *
213 * Params:
214 * In/Out: ds State structure to be initialised
215 *
216 * Returns:
217 * OK: 0
218 * Error: -1
219 */
220static int initialise_read(DevSWState *ds)
221{
222 struct data_packet *dp;
223
224 /*
225 * try to claim the structure that will
226 * eventually hold the new packet.
227 */
228 if ((ds->ds_nextreadpacket = DevSW_AllocatePacket(allocsize)) == NULL)
229 return -1;
230
231 /*
232 * Calls into the device driver use the DriverCall structure: use
233 * the buffer we have just allocated, and declare its size. We
234 * are also obliged to clear the driver's context pointer.
235 */
236 dp = &ds->ds_activeread.dc_packet;
237 dp->buf_len = allocsize;
238 dp->data = ds->ds_nextreadpacket->pk_buffer;
239
240 ds->ds_activeread.dc_context = NULL;
241
242 return 0;
243}
244
245/*
246 * Function: initialise_write
247 * Purpose: Set up a write request for another packet
248 *
249 * Params:
250 * Input: packet The packet to be written
251 *
252 * type The type of the packet
253 *
254 * In/Out: dc The structure to be intialised
255 *
256 * Returns: Nothing
257 */
258static void initialise_write(DriverCall *dc, Packet *packet, DevChanID type)
259{
260 struct data_packet *dp = &dc->dc_packet;
261
262 dp->len = packet->pk_length;
263 dp->data = packet->pk_buffer;
264 dp->type = type;
265
266 /*
267 * we are required to clear the state structure for the driver
268 */
269 dc->dc_context = NULL;
270}
271
272/*
273 * Function: enqueue_packet
274 * Purpose: move a newly read packet onto the appropriate queue
275 * of read packets
276 *
277 * Params:
278 * In/Out: ds State structure with new packet
279 *
280 * Returns: Nothing
281 */
282static void enqueue_packet(DevSWState *ds)
283{
284 struct data_packet *dp = &ds->ds_activeread.dc_packet;
285 Packet *packet = ds->ds_nextreadpacket;
286
287 /*
288 * transfer the length
289 */
290 packet->pk_length = dp->len;
291
292 /*
293 * take this packet out of the incoming slot
294 */
295 ds->ds_nextreadpacket = NULL;
296
297 /*
298 * try to put it on the correct input queue
299 */
300 if (illegalDevChanID(dp->type))
301 {
302 /* this shouldn't happen */
303 WARN("Illegal type for Rx packet");
304 DevSW_FreePacket(packet);
305 }
306 else
307 Adp_addToQueue(&ds->ds_readqueue[dp->type], packet);
308}
309
310/*
311 * Function: flush_packet
312 * Purpose: Send a packet to the device driver
313 *
314 * Params:
315 * Input: device The device to be written to
316 *
317 * In/Out: dc Describes the packet to be sent
318 *
319 * Returns: Nothing
320 *
321 * Post-conditions: If the whole packet was accepted by the device
322 * driver, then dc->dc_packet.data will be
323 * set to NULL.
324 */
325static void flush_packet(const DeviceDescr *device, DriverCall *dc)
326{
327 if (device->DeviceWrite(dc) > 0)
328 /*
329 * the whole packet was swallowed
330 */
331 dc->dc_packet.data = NULL;
332}
333
334/**********************************************************************/
335
336/*
337 * These are the externally visible functions. They are documented in
338 * devsw.h
339 */
340Packet *DevSW_AllocatePacket(const unsigned int length)
341{
342 Packet *pk;
343
344 if ((pk = malloc(sizeof(*pk))) == NULL)
345 {
346 WARN("malloc failure");
347 return NULL;
348 }
349
350 if ((pk->pk_buffer = malloc(length+CHAN_HEADER_SIZE)) == NULL)
351 {
352 WARN("malloc failure");
353 free(pk);
354 return NULL;
355 }
356
357 return pk;
358}
359
360void DevSW_FreePacket(Packet *pk)
361{
362 free(pk->pk_buffer);
363 free(pk);
364}
365
366AdpErrs DevSW_Open(DeviceDescr *device, const char *name, const char *arg,
367 const DevChanID type)
368{
369 DevSWState *ds;
370
371 /*
372 * is this the very first open call for this driver?
373 */
374 if ((ds = (DevSWState *)(device->SwitcherState)) == NULL)
375 {
376 /*
377 * yes, it is: initialise state
378 */
379 if ((ds = malloc(sizeof(*ds))) == NULL)
380 /* give up */
381 return adp_malloc_failure;
382
383 (void)memset(ds, 0, sizeof(*ds));
384 device->SwitcherState = (void *)ds;
385 }
386
387 /*
388 * check that we haven't already been opened for this type
389 */
390 if ((ds->ds_opendevchans & (1 << type)) != 0)
391 return adp_device_already_open;
392
393 /*
394 * if no opens have been done for this device, then do it now
395 */
396 if (ds->ds_opendevchans == 0)
397 if (device->DeviceOpen(name, arg) < 0)
398 return adp_device_open_failed;
399
400 /*
401 * open has finished
402 */
403 ds->ds_opendevchans |= (1 << type);
404 return adp_ok;
405}
406
407AdpErrs DevSW_Match(const DeviceDescr *device, const char *name,
408 const char *arg)
409{
410 return (device->DeviceMatch(name, arg) == -1) ? adp_failed : adp_ok;
411}
412
413AdpErrs DevSW_Close(const DeviceDescr *device, const DevChanID type)
414{
415 DevSWState *ds = (DevSWState *)(device->SwitcherState);
416 Packet *pk;
417
418 if ((ds->ds_opendevchans & (1 << type)) == 0)
419 return adp_device_not_open;
420
421 ds->ds_opendevchans &= ~(1 << type);
422
423 /*
424 * if this is the last close for this channel, then inform the driver
425 */
426 if (ds->ds_opendevchans == 0)
427 device->DeviceClose();
428
429 /*
430 * release all packets of the appropriate type
431 */
432 for (pk = Adp_removeFromQueue(&(ds->ds_readqueue[type]));
433 pk != NULL;
434 pk = Adp_removeFromQueue(&(ds->ds_readqueue[type])))
435 DevSW_FreePacket(pk);
436
437 /* Free memory */
438 free ((char *) device->SwitcherState);
439 device->SwitcherState = 0x0;
440
441 /* that's all */
442 return adp_ok;
443}
444
445AdpErrs DevSW_Read(const DeviceDescr *device, const DevChanID type,
446 Packet **packet, bool block)
447{
448 int read_err;
449 DevSWState *ds = device->SwitcherState;
450
451 /*
452 * To try to get information out of the device driver as
453 * quickly as possible, we try and read more packets, even
454 * if a completed packet is already available.
455 */
456
457 /*
458 * have we got a packet currently pending?
459 */
460 if (ds->ds_nextreadpacket == NULL)
461 /*
462 * no - set things up
463 */
464 if (initialise_read(ds) < 0) {
465 /*
466 * we failed to initialise the next packet, but can
467 * still return a packet that has already arrived.
468 */
469 *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
470 return adp_ok;
471 }
472 read_err = device->DeviceRead(&ds->ds_activeread, block);
473 switch (read_err) {
474 case 1:
475 /*
476 * driver has pulled in a complete packet, queue it up
477 */
478#ifdef RET_DEBUG
479 printf("got a complete packet\n");
480#endif
5c44784c
JM
481
482 if (angelDebugLogEnable)
483 dumpPacket(angelDebugLogFile,"rx:",&ds->ds_activeread.dc_packet);
484
c906108c
SS
485 enqueue_packet(ds);
486 *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
487 return adp_ok;
488 case 0:
489 /*
490 * OK, return the head of the read queue for the given type
491 */
492 /* enqueue_packet(ds); */
493 *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
494 return adp_ok;
495 case -1:
496#ifdef RET_DEBUG
497 printf("got a bad packet\n");
498#endif
499 /* bad packet */
500 *packet = NULL;
501 return adp_bad_packet;
502 default:
503 panic("DevSW_Read: bad read status %d", read_err);
504 }
505 return 0; /* get rid of a potential compiler warning */
506}
507
508
509AdpErrs DevSW_FlushPendingWrite(const DeviceDescr *device)
510{
511 struct DriverCall *dc;
512 struct data_packet *dp;
513
514 dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
515 dp = &dc->dc_packet;
516
517 /*
518 * try to flush any packet that is still being written
519 */
520 if (dp->data != NULL)
521 {
522 flush_packet(device, dc);
523
524 /* see if it has gone */
525 if (dp->data != NULL)
526 return adp_write_busy;
527 else
528 return adp_ok;
529 }
530 else
531 return adp_ok;
532}
533
534
535AdpErrs DevSW_Write(const DeviceDescr *device, Packet *packet, DevChanID type)
536{
537 struct DriverCall *dc;
538 struct data_packet *dp;
539
540 dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
541 dp = &dc->dc_packet;
542
543 if (illegalDevChanID(type))
544 return adp_illegal_args;
545
546 /*
547 * try to flush any packet that is still being written
548 */
549 if (DevSW_FlushPendingWrite(device) != adp_ok)
550 return adp_write_busy;
551
552 /*
553 * we can take this packet - set things up, then try to get rid of it
554 */
555 initialise_write(dc, packet, type);
5c44784c
JM
556
557 if (angelDebugLogEnable)
558 dumpPacket(angelDebugLogFile,"tx:",&dc->dc_packet);
559
c906108c
SS
560 flush_packet(device, dc);
561
562 return adp_ok;
563}
564
565AdpErrs DevSW_Ioctl(const DeviceDescr *device, const int opcode, void *args)
566{
567 return (device->DeviceIoctl(opcode, args) < 0) ? adp_failed : adp_ok;
568}
569
570bool DevSW_WriteFinished(const DeviceDescr *device)
571{
572 struct DriverCall *dc;
573 struct data_packet *dp;
574
575 dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
576 dp = &dc->dc_packet;
577
578 return (dp == NULL || dp->data == NULL);
579}
580
581/* EOF devsw.c */
This page took 0.056632 seconds and 4 git commands to generate.