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