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