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