OSDN Git Service

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