2 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
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
33 static char *angelDebugFilename
= NULL
;
34 static FILE *angelDebugLogFile
= NULL
;
35 static int angelDebugLogEnable
= 0;
37 static void openLogFile ()
41 if (angelDebugFilename
== NULL
|| *angelDebugFilename
=='\0')
44 angelDebugLogFile
= fopen (angelDebugFilename
,"a");
46 if (!angelDebugLogFile
)
48 fprintf (stderr
,"Error opening log file '%s'\n",angelDebugFilename
);
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
);
62 fprintf (angelDebugLogFile
,"ADP log file opened at %s\n",asctime(localtime(&t
)));
66 static void closeLogFile (void)
70 if (!angelDebugLogFile
)
74 fprintf (angelDebugLogFile
,"ADP log file closed at %s\n",asctime(localtime(&t
)));
76 fclose (angelDebugLogFile
);
77 angelDebugLogFile
= NULL
;
80 void DevSW_SetLogEnable (int logEnableFlag
)
82 if (logEnableFlag
&& !angelDebugLogFile
)
84 else if (!logEnableFlag
&& angelDebugLogFile
)
87 angelDebugLogEnable
= logEnableFlag
;
91 void DevSW_SetLogfile (const char *filename
)
95 if (angelDebugFilename
)
97 free (angelDebugFilename
);
98 angelDebugFilename
= NULL
;
101 if (filename
&& *filename
)
103 angelDebugFilename
= strdup (filename
);
104 if (angelDebugLogEnable
)
110 #define WordAt(p) ((unsigned long) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)))
112 static void dumpPacket(FILE *fp
, char *label
, struct data_packet
*p
)
116 unsigned char channel
;
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
]);
126 channel
= p
->data
[0];
128 r
= WordAt(p
->data
+4);
130 fprintf(fp
,"R=%08x ",r
);
131 fprintf(fp
,"%s ", r
&0x80000000 ? "H<-T" : "H->T");
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;
149 switch (r
& 0xffffff)
151 case ADP_Booted
: fprintf(fp
," ADP_Booted "); break;
152 #if defined(ADP_TargetResetIndication)
153 case ADP_TargetResetIndication
: fprintf(fp
," ADP_TargetResetIndication "); break;
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;
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;
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;
210 default: fprintf(fp
," BadReason "); break;
215 if (((r
& 0xffffff) == ADP_CPUread
||
216 (r
& 0xffffff) == ADP_CPUwrite
) && (r
&0x80000000)==0)
218 fprintf(fp
,"%02x ", p
->data
[i
]);
222 for (; i
<p
->len
; i
+=4)
223 fprintf(fp
,"%08x ",WordAt(p
->data
+i
));
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.
234 static const unsigned int allocsize
= ADP_BUFFER_MIN_SIZE
;
236 #define illegalDevChanID(type) ((type) >= DC_NUM_CHANNELS)
238 /**********************************************************************/
241 * Function: initialise_read
242 * Purpose: Set up a read request for another packet
245 * In/Out: ds State structure to be initialised
251 static int initialise_read(DevSWState
*ds
)
253 struct data_packet
*dp
;
256 * try to claim the structure that will
257 * eventually hold the new packet.
259 if ((ds
->ds_nextreadpacket
= DevSW_AllocatePacket(allocsize
)) == NULL
)
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.
267 dp
= &ds
->ds_activeread
.dc_packet
;
268 dp
->buf_len
= allocsize
;
269 dp
->data
= ds
->ds_nextreadpacket
->pk_buffer
;
271 ds
->ds_activeread
.dc_context
= NULL
;
277 * Function: initialise_write
278 * Purpose: Set up a write request for another packet
281 * Input: packet The packet to be written
283 * type The type of the packet
285 * In/Out: dc The structure to be intialised
289 static void initialise_write(DriverCall
*dc
, Packet
*packet
, DevChanID type
)
291 struct data_packet
*dp
= &dc
->dc_packet
;
293 dp
->len
= packet
->pk_length
;
294 dp
->data
= packet
->pk_buffer
;
298 * we are required to clear the state structure for the driver
300 dc
->dc_context
= NULL
;
304 * Function: enqueue_packet
305 * Purpose: move a newly read packet onto the appropriate queue
309 * In/Out: ds State structure with new packet
313 static void enqueue_packet(DevSWState
*ds
)
315 struct data_packet
*dp
= &ds
->ds_activeread
.dc_packet
;
316 Packet
*packet
= ds
->ds_nextreadpacket
;
319 * transfer the length
321 packet
->pk_length
= dp
->len
;
324 * take this packet out of the incoming slot
326 ds
->ds_nextreadpacket
= NULL
;
329 * try to put it on the correct input queue
331 if (illegalDevChanID(dp
->type
))
333 /* this shouldn't happen */
334 WARN("Illegal type for Rx packet");
335 DevSW_FreePacket(packet
);
338 Adp_addToQueue(&ds
->ds_readqueue
[dp
->type
], packet
);
342 * Function: flush_packet
343 * Purpose: Send a packet to the device driver
346 * Input: device The device to be written to
348 * In/Out: dc Describes the packet to be sent
352 * Post-conditions: If the whole packet was accepted by the device
353 * driver, then dc->dc_packet.data will be
356 static void flush_packet(const DeviceDescr
*device
, DriverCall
*dc
)
358 if (device
->DeviceWrite(dc
) > 0)
360 * the whole packet was swallowed
362 dc
->dc_packet
.data
= NULL
;
365 /**********************************************************************/
368 * These are the externally visible functions. They are documented in
371 Packet
*DevSW_AllocatePacket(const unsigned int length
)
375 if ((pk
= malloc(sizeof(*pk
))) == NULL
)
377 WARN("malloc failure");
381 if ((pk
->pk_buffer
= malloc(length
+CHAN_HEADER_SIZE
)) == NULL
)
383 WARN("malloc failure");
391 void DevSW_FreePacket(Packet
*pk
)
397 AdpErrs
DevSW_Open(DeviceDescr
*device
, const char *name
, const char *arg
,
398 const DevChanID type
)
403 * is this the very first open call for this driver?
405 if ((ds
= (DevSWState
*)(device
->SwitcherState
)) == NULL
)
408 * yes, it is: initialise state
410 if ((ds
= malloc(sizeof(*ds
))) == NULL
)
412 return adp_malloc_failure
;
414 (void)memset(ds
, 0, sizeof(*ds
));
415 device
->SwitcherState
= (void *)ds
;
419 * check that we haven't already been opened for this type
421 if ((ds
->ds_opendevchans
& (1 << type
)) != 0)
422 return adp_device_already_open
;
425 * if no opens have been done for this device, then do it now
427 if (ds
->ds_opendevchans
== 0)
428 if (device
->DeviceOpen(name
, arg
) < 0)
429 return adp_device_open_failed
;
434 ds
->ds_opendevchans
|= (1 << type
);
438 AdpErrs
DevSW_Match(const DeviceDescr
*device
, const char *name
,
441 return (device
->DeviceMatch(name
, arg
) == -1) ? adp_failed
: adp_ok
;
444 AdpErrs
DevSW_Close (DeviceDescr
*device
, const DevChanID type
)
446 DevSWState
*ds
= (DevSWState
*)(device
->SwitcherState
);
449 if ((ds
->ds_opendevchans
& (1 << type
)) == 0)
450 return adp_device_not_open
;
452 ds
->ds_opendevchans
&= ~(1 << type
);
455 * if this is the last close for this channel, then inform the driver
457 if (ds
->ds_opendevchans
== 0)
458 device
->DeviceClose();
461 * release all packets of the appropriate type
463 for (pk
= Adp_removeFromQueue(&(ds
->ds_readqueue
[type
]));
465 pk
= Adp_removeFromQueue(&(ds
->ds_readqueue
[type
])))
466 DevSW_FreePacket(pk
);
469 free ((char *) device
->SwitcherState
);
470 device
->SwitcherState
= 0x0;
476 AdpErrs
DevSW_Read(const DeviceDescr
*device
, const DevChanID type
,
477 Packet
**packet
, bool block
)
480 DevSWState
*ds
= device
->SwitcherState
;
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.
489 * have we got a packet currently pending?
491 if (ds
->ds_nextreadpacket
== NULL
)
495 if (initialise_read(ds
) < 0) {
497 * we failed to initialise the next packet, but can
498 * still return a packet that has already arrived.
500 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
503 read_err
= device
->DeviceRead(&ds
->ds_activeread
, block
);
507 * driver has pulled in a complete packet, queue it up
510 printf("got a complete packet\n");
513 if (angelDebugLogEnable
)
514 dumpPacket(angelDebugLogFile
,"rx:",&ds
->ds_activeread
.dc_packet
);
517 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
521 * OK, return the head of the read queue for the given type
523 /* enqueue_packet(ds); */
524 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
528 printf("got a bad packet\n");
532 return adp_bad_packet
;
534 panic("DevSW_Read: bad read status %d", read_err
);
536 return 0; /* get rid of a potential compiler warning */
540 AdpErrs
DevSW_FlushPendingWrite(const DeviceDescr
*device
)
542 struct DriverCall
*dc
;
543 struct data_packet
*dp
;
545 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
549 * try to flush any packet that is still being written
551 if (dp
->data
!= NULL
)
553 flush_packet(device
, dc
);
555 /* see if it has gone */
556 if (dp
->data
!= NULL
)
557 return adp_write_busy
;
566 AdpErrs
DevSW_Write(const DeviceDescr
*device
, Packet
*packet
, DevChanID type
)
568 struct DriverCall
*dc
;
569 struct data_packet
*dp
;
571 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
574 if (illegalDevChanID(type
))
575 return adp_illegal_args
;
578 * try to flush any packet that is still being written
580 if (DevSW_FlushPendingWrite(device
) != adp_ok
)
581 return adp_write_busy
;
584 * we can take this packet - set things up, then try to get rid of it
586 initialise_write(dc
, packet
, type
);
588 if (angelDebugLogEnable
)
589 dumpPacket(angelDebugLogFile
,"tx:",&dc
->dc_packet
);
591 flush_packet(device
, dc
);
596 AdpErrs
DevSW_Ioctl(const DeviceDescr
*device
, const int opcode
, void *args
)
598 return (device
->DeviceIoctl(opcode
, args
) < 0) ? adp_failed
: adp_ok
;
601 bool DevSW_WriteFinished(const DeviceDescr
*device
)
603 struct DriverCall
*dc
;
604 struct data_packet
*dp
;
606 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
609 return (dp
== NULL
|| dp
->data
== NULL
);