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
30 static char *angelDebugFilename
= NULL
;
31 static FILE *angelDebugLogFile
= NULL
;
32 static int angelDebugLogEnable
= 0;
34 static void openLogFile ()
39 if (angelDebugFilename
== NULL
|| *angelDebugFilename
=='\0')
42 angelDebugLogFile
= fopen (angelDebugFilename
,"a");
44 if (!angelDebugLogFile
)
46 fprintf (stderr
,"Error opening log file '%s'\n",angelDebugFilename
);
50 /* The following line is equivalent to: */
51 /* setlinebuf (angelDebugLogFile); */
52 setvbuf(angelDebugLogFile
, (char *)NULL
, _IOLBF
, 0);
55 fprintf (angelDebugLogFile
,"ADP log file opened at %s\n",asctime(localtime(&t
)));
59 static void closeLogFile (void)
64 if (!angelDebugLogFile
)
68 fprintf (angelDebugLogFile
,"ADP log file closed at %s\n",asctime(localtime(&t
)));
70 fclose (angelDebugLogFile
);
71 angelDebugLogFile
= NULL
;
74 void DevSW_SetLogEnable (int logEnableFlag
)
76 if (logEnableFlag
&& !angelDebugLogFile
)
78 else if (!logEnableFlag
&& angelDebugLogFile
)
81 angelDebugLogEnable
= logEnableFlag
;
85 void DevSW_SetLogfile (const char *filename
)
89 if (angelDebugFilename
)
91 free (angelDebugFilename
);
92 angelDebugFilename
= NULL
;
95 if (filename
&& *filename
)
97 angelDebugFilename
= strdup (filename
);
98 if (angelDebugLogEnable
)
104 #define WordAt(p) ((unsigned long) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)))
106 static void dumpPacket(FILE *fp
, char *label
, struct data_packet
*p
)
114 fprintf(fp
,"%s [T=%d L=%d] ",label
,p
->type
,p
->len
);
115 for (i
=0; i
<p
->len
; ++i
)
116 fprintf(fp
,"%02x ",p
->data
[i
]);
119 r
= WordAt(p
->data
+4);
121 fprintf(fp
,"R=%08x ",r
);
122 fprintf(fp
,"%s ", r
&0x80000000 ? "H<-T" : "H->T");
124 switch ((r
>>16) & 0xff)
126 case CI_PRIVATE
: fprintf(fp
,"CI_PRIVATE: "); break;
127 case CI_HADP
: fprintf(fp
,"CI_HADP: "); break;
128 case CI_TADP
: fprintf(fp
,"CI_TADP: "); break;
129 case CI_HBOOT
: fprintf(fp
,"CI_HBOOT: "); break;
130 case CI_TBOOT
: fprintf(fp
,"CI_TBOOT: "); break;
131 case CI_CLIB
: fprintf(fp
,"CI_CLIB: "); break;
132 case CI_HUDBG
: fprintf(fp
,"CI_HUDBG: "); break;
133 case CI_TUDBG
: fprintf(fp
,"CI_TUDBG: "); break;
134 case CI_HTDCC
: fprintf(fp
,"CI_HTDCC: "); break;
135 case CI_TTDCC
: fprintf(fp
,"CI_TTDCC: "); break;
136 case CI_TLOG
: fprintf(fp
,"CI_TLOG: "); break;
137 default: fprintf(fp
,"BadChan: "); break;
140 switch (r
& 0xffffff)
142 case ADP_Booted
: fprintf(fp
," ADP_Booted "); break;
143 #if defined(ADP_TargetResetIndication)
144 case ADP_TargetResetIndication
: fprintf(fp
," ADP_TargetResetIndication "); break;
146 case ADP_Reboot
: fprintf(fp
," ADP_Reboot "); break;
147 case ADP_Reset
: fprintf(fp
," ADP_Reset "); break;
148 #if defined(ADP_HostResetIndication)
149 case ADP_HostResetIndication
: fprintf(fp
," ADP_HostResetIndication "); break;
151 case ADP_ParamNegotiate
: fprintf(fp
," ADP_ParamNegotiate "); break;
152 case ADP_LinkCheck
: fprintf(fp
," ADP_LinkCheck "); break;
153 case ADP_HADPUnrecognised
: fprintf(fp
," ADP_HADPUnrecognised "); break;
154 case ADP_Info
: fprintf(fp
," ADP_Info "); break;
155 case ADP_Control
: fprintf(fp
," ADP_Control "); break;
156 case ADP_Read
: fprintf(fp
," ADP_Read "); break;
157 case ADP_Write
: fprintf(fp
," ADP_Write "); break;
158 case ADP_CPUread
: fprintf(fp
," ADP_CPUread "); break;
159 case ADP_CPUwrite
: fprintf(fp
," ADP_CPUwrite "); break;
160 case ADP_CPread
: fprintf(fp
," ADP_CPread "); break;
161 case ADP_CPwrite
: fprintf(fp
," ADP_CPwrite "); break;
162 case ADP_SetBreak
: fprintf(fp
," ADP_SetBreak "); break;
163 case ADP_ClearBreak
: fprintf(fp
," ADP_ClearBreak "); break;
164 case ADP_SetWatch
: fprintf(fp
," ADP_SetWatch "); break;
165 case ADP_ClearWatch
: fprintf(fp
," ADP_ClearWatch "); break;
166 case ADP_Execute
: fprintf(fp
," ADP_Execute "); break;
167 case ADP_Step
: fprintf(fp
," ADP_Step "); break;
168 case ADP_InterruptRequest
: fprintf(fp
," ADP_InterruptRequest "); break;
169 case ADP_HW_Emulation
: fprintf(fp
," ADP_HW_Emulation "); break;
170 case ADP_ICEbreakerHADP
: fprintf(fp
," ADP_ICEbreakerHADP "); break;
171 case ADP_ICEman
: fprintf(fp
," ADP_ICEman "); break;
172 case ADP_Profile
: fprintf(fp
," ADP_Profile "); break;
173 case ADP_InitialiseApplication
: fprintf(fp
," ADP_InitialiseApplication "); break;
174 case ADP_End
: fprintf(fp
," ADP_End "); break;
175 case ADP_TADPUnrecognised
: fprintf(fp
," ADP_TADPUnrecognised "); break;
176 case ADP_Stopped
: fprintf(fp
," ADP_Stopped "); break;
177 case ADP_TDCC_ToHost
: fprintf(fp
," ADP_TDCC_ToHost "); break;
178 case ADP_TDCC_FromHost
: fprintf(fp
," ADP_TDCC_FromHost "); break;
179 default: fprintf(fp
," BadReason "); break;
184 if (((r
& 0xffffff) == ADP_CPUread
||
185 (r
& 0xffffff) == ADP_CPUwrite
) && (r
&0x80000000)==0)
187 fprintf(fp
,"%02x ", p
->data
[i
]);
191 for (; i
<p
->len
; i
+=4)
192 fprintf(fp
,"%08x ",WordAt(p
->data
+i
));
199 * TODO: this should be adjustable - it could be done by defining
200 * a reason code for DevSW_Ioctl. It could even be a
201 * per-devicechannel parameter.
203 static const unsigned int allocsize
= ADP_BUFFER_MIN_SIZE
;
205 #define illegalDevChanID(type) ((type) >= DC_NUM_CHANNELS)
207 /**********************************************************************/
210 * Function: initialise_read
211 * Purpose: Set up a read request for another packet
214 * In/Out: ds State structure to be initialised
220 static int initialise_read(DevSWState
*ds
)
222 struct data_packet
*dp
;
225 * try to claim the structure that will
226 * eventually hold the new packet.
228 if ((ds
->ds_nextreadpacket
= DevSW_AllocatePacket(allocsize
)) == NULL
)
232 * Calls into the device driver use the DriverCall structure: use
233 * the buffer we have just allocated, and declare its size. We
234 * are also obliged to clear the driver's context pointer.
236 dp
= &ds
->ds_activeread
.dc_packet
;
237 dp
->buf_len
= allocsize
;
238 dp
->data
= ds
->ds_nextreadpacket
->pk_buffer
;
240 ds
->ds_activeread
.dc_context
= NULL
;
246 * Function: initialise_write
247 * Purpose: Set up a write request for another packet
250 * Input: packet The packet to be written
252 * type The type of the packet
254 * In/Out: dc The structure to be intialised
258 static void initialise_write(DriverCall
*dc
, Packet
*packet
, DevChanID type
)
260 struct data_packet
*dp
= &dc
->dc_packet
;
262 dp
->len
= packet
->pk_length
;
263 dp
->data
= packet
->pk_buffer
;
267 * we are required to clear the state structure for the driver
269 dc
->dc_context
= NULL
;
273 * Function: enqueue_packet
274 * Purpose: move a newly read packet onto the appropriate queue
278 * In/Out: ds State structure with new packet
282 static void enqueue_packet(DevSWState
*ds
)
284 struct data_packet
*dp
= &ds
->ds_activeread
.dc_packet
;
285 Packet
*packet
= ds
->ds_nextreadpacket
;
288 * transfer the length
290 packet
->pk_length
= dp
->len
;
293 * take this packet out of the incoming slot
295 ds
->ds_nextreadpacket
= NULL
;
298 * try to put it on the correct input queue
300 if (illegalDevChanID(dp
->type
))
302 /* this shouldn't happen */
303 WARN("Illegal type for Rx packet");
304 DevSW_FreePacket(packet
);
307 Adp_addToQueue(&ds
->ds_readqueue
[dp
->type
], packet
);
311 * Function: flush_packet
312 * Purpose: Send a packet to the device driver
315 * Input: device The device to be written to
317 * In/Out: dc Describes the packet to be sent
321 * Post-conditions: If the whole packet was accepted by the device
322 * driver, then dc->dc_packet.data will be
325 static void flush_packet(const DeviceDescr
*device
, DriverCall
*dc
)
327 if (device
->DeviceWrite(dc
) > 0)
329 * the whole packet was swallowed
331 dc
->dc_packet
.data
= NULL
;
334 /**********************************************************************/
337 * These are the externally visible functions. They are documented in
340 Packet
*DevSW_AllocatePacket(const unsigned int length
)
344 if ((pk
= malloc(sizeof(*pk
))) == NULL
)
346 WARN("malloc failure");
350 if ((pk
->pk_buffer
= malloc(length
+CHAN_HEADER_SIZE
)) == NULL
)
352 WARN("malloc failure");
360 void DevSW_FreePacket(Packet
*pk
)
366 AdpErrs
DevSW_Open(DeviceDescr
*device
, const char *name
, const char *arg
,
367 const DevChanID type
)
372 * is this the very first open call for this driver?
374 if ((ds
= (DevSWState
*)(device
->SwitcherState
)) == NULL
)
377 * yes, it is: initialise state
379 if ((ds
= malloc(sizeof(*ds
))) == NULL
)
381 return adp_malloc_failure
;
383 (void)memset(ds
, 0, sizeof(*ds
));
384 device
->SwitcherState
= (void *)ds
;
388 * check that we haven't already been opened for this type
390 if ((ds
->ds_opendevchans
& (1 << type
)) != 0)
391 return adp_device_already_open
;
394 * if no opens have been done for this device, then do it now
396 if (ds
->ds_opendevchans
== 0)
397 if (device
->DeviceOpen(name
, arg
) < 0)
398 return adp_device_open_failed
;
403 ds
->ds_opendevchans
|= (1 << type
);
407 AdpErrs
DevSW_Match(const DeviceDescr
*device
, const char *name
,
410 return (device
->DeviceMatch(name
, arg
) == -1) ? adp_failed
: adp_ok
;
413 AdpErrs
DevSW_Close(const DeviceDescr
*device
, const DevChanID type
)
415 DevSWState
*ds
= (DevSWState
*)(device
->SwitcherState
);
418 if ((ds
->ds_opendevchans
& (1 << type
)) == 0)
419 return adp_device_not_open
;
421 ds
->ds_opendevchans
&= ~(1 << type
);
424 * if this is the last close for this channel, then inform the driver
426 if (ds
->ds_opendevchans
== 0)
427 device
->DeviceClose();
430 * release all packets of the appropriate type
432 for (pk
= Adp_removeFromQueue(&(ds
->ds_readqueue
[type
]));
434 pk
= Adp_removeFromQueue(&(ds
->ds_readqueue
[type
])))
435 DevSW_FreePacket(pk
);
438 free ((char *) device
->SwitcherState
);
439 device
->SwitcherState
= 0x0;
445 AdpErrs
DevSW_Read(const DeviceDescr
*device
, const DevChanID type
,
446 Packet
**packet
, bool block
)
449 DevSWState
*ds
= device
->SwitcherState
;
452 * To try to get information out of the device driver as
453 * quickly as possible, we try and read more packets, even
454 * if a completed packet is already available.
458 * have we got a packet currently pending?
460 if (ds
->ds_nextreadpacket
== NULL
)
464 if (initialise_read(ds
) < 0) {
466 * we failed to initialise the next packet, but can
467 * still return a packet that has already arrived.
469 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
472 read_err
= device
->DeviceRead(&ds
->ds_activeread
, block
);
476 * driver has pulled in a complete packet, queue it up
479 printf("got a complete packet\n");
482 if (angelDebugLogEnable
)
483 dumpPacket(angelDebugLogFile
,"rx:",&ds
->ds_activeread
.dc_packet
);
486 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
490 * OK, return the head of the read queue for the given type
492 /* enqueue_packet(ds); */
493 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
497 printf("got a bad packet\n");
501 return adp_bad_packet
;
503 panic("DevSW_Read: bad read status %d", read_err
);
505 return 0; /* get rid of a potential compiler warning */
509 AdpErrs
DevSW_FlushPendingWrite(const DeviceDescr
*device
)
511 struct DriverCall
*dc
;
512 struct data_packet
*dp
;
514 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
518 * try to flush any packet that is still being written
520 if (dp
->data
!= NULL
)
522 flush_packet(device
, dc
);
524 /* see if it has gone */
525 if (dp
->data
!= NULL
)
526 return adp_write_busy
;
535 AdpErrs
DevSW_Write(const DeviceDescr
*device
, Packet
*packet
, DevChanID type
)
537 struct DriverCall
*dc
;
538 struct data_packet
*dp
;
540 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
543 if (illegalDevChanID(type
))
544 return adp_illegal_args
;
547 * try to flush any packet that is still being written
549 if (DevSW_FlushPendingWrite(device
) != adp_ok
)
550 return adp_write_busy
;
553 * we can take this packet - set things up, then try to get rid of it
555 initialise_write(dc
, packet
, type
);
557 if (angelDebugLogEnable
)
558 dumpPacket(angelDebugLogFile
,"tx:",&dc
->dc_packet
);
560 flush_packet(device
, dc
);
565 AdpErrs
DevSW_Ioctl(const DeviceDescr
*device
, const int opcode
, void *args
)
567 return (device
->DeviceIoctl(opcode
, args
) < 0) ? adp_failed
: adp_ok
;
570 bool DevSW_WriteFinished(const DeviceDescr
*device
)
572 struct DriverCall
*dc
;
573 struct data_packet
*dp
;
575 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
578 return (dp
== NULL
|| dp
->data
== NULL
);