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
31 static char *angelDebugFilename
= NULL
;
32 static FILE *angelDebugLogFile
= NULL
;
33 static int angelDebugLogEnable
= 0;
35 static void openLogFile ()
40 if (angelDebugFilename
== NULL
|| *angelDebugFilename
=='\0')
43 angelDebugLogFile
= fopen (angelDebugFilename
,"a");
45 if (!angelDebugLogFile
)
47 fprintf (stderr
,"Error opening log file '%s'\n",angelDebugFilename
);
51 /* The following line is equivalent to: */
52 /* setlinebuf (angelDebugLogFile); */
53 setvbuf(angelDebugLogFile
, (char *)NULL
, _IOLBF
, 0);
56 fprintf (angelDebugLogFile
,"ADP log file opened at %s\n",asctime(localtime(&t
)));
60 static void closeLogFile (void)
65 if (!angelDebugLogFile
)
69 fprintf (angelDebugLogFile
,"ADP log file closed at %s\n",asctime(localtime(&t
)));
71 fclose (angelDebugLogFile
);
72 angelDebugLogFile
= NULL
;
75 void DevSW_SetLogEnable (int logEnableFlag
)
77 if (logEnableFlag
&& !angelDebugLogFile
)
79 else if (!logEnableFlag
&& angelDebugLogFile
)
82 angelDebugLogEnable
= logEnableFlag
;
86 void DevSW_SetLogfile (const char *filename
)
90 if (angelDebugFilename
)
92 free (angelDebugFilename
);
93 angelDebugFilename
= NULL
;
96 if (filename
&& *filename
)
98 angelDebugFilename
= strdup (filename
);
99 if (angelDebugLogEnable
)
105 #define WordAt(p) ((unsigned long) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)))
107 static void dumpPacket(FILE *fp
, char *label
, struct data_packet
*p
)
111 unsigned char channel
;
116 fprintf(fp
,"%s [T=%d L=%d] ",label
,p
->type
,p
->len
);
117 for (i
=0; i
<p
->len
; ++i
)
118 fprintf(fp
,"%02x ",p
->data
[i
]);
121 channel
= p
->data
[0];
123 r
= WordAt(p
->data
+4);
125 fprintf(fp
,"R=%08x ",r
);
126 fprintf(fp
,"%s ", r
&0x80000000 ? "H<-T" : "H->T");
130 case CI_PRIVATE
: fprintf(fp
,"CI_PRIVATE: "); break;
131 case CI_HADP
: fprintf(fp
,"CI_HADP: "); break;
132 case CI_TADP
: fprintf(fp
,"CI_TADP: "); break;
133 case CI_HBOOT
: fprintf(fp
,"CI_HBOOT: "); break;
134 case CI_TBOOT
: fprintf(fp
,"CI_TBOOT: "); break;
135 case CI_CLIB
: fprintf(fp
,"CI_CLIB: "); break;
136 case CI_HUDBG
: fprintf(fp
,"CI_HUDBG: "); break;
137 case CI_TUDBG
: fprintf(fp
,"CI_TUDBG: "); break;
138 case CI_HTDCC
: fprintf(fp
,"CI_HTDCC: "); break;
139 case CI_TTDCC
: fprintf(fp
,"CI_TTDCC: "); break;
140 case CI_TLOG
: fprintf(fp
,"CI_TLOG: "); break;
141 default: fprintf(fp
,"BadChan: "); break;
144 switch (r
& 0xffffff)
146 case ADP_Booted
: fprintf(fp
," ADP_Booted "); break;
147 #if defined(ADP_TargetResetIndication)
148 case ADP_TargetResetIndication
: fprintf(fp
," ADP_TargetResetIndication "); break;
150 case ADP_Reboot
: fprintf(fp
," ADP_Reboot "); break;
151 case ADP_Reset
: fprintf(fp
," ADP_Reset "); break;
152 #if defined(ADP_HostResetIndication)
153 case ADP_HostResetIndication
: fprintf(fp
," ADP_HostResetIndication "); break;
155 case ADP_ParamNegotiate
: fprintf(fp
," ADP_ParamNegotiate "); break;
156 case ADP_LinkCheck
: fprintf(fp
," ADP_LinkCheck "); break;
157 case ADP_HADPUnrecognised
: fprintf(fp
," ADP_HADPUnrecognised "); break;
158 case ADP_Info
: fprintf(fp
," ADP_Info "); break;
159 case ADP_Control
: fprintf(fp
," ADP_Control "); break;
160 case ADP_Read
: fprintf(fp
," ADP_Read "); break;
161 case ADP_Write
: fprintf(fp
," ADP_Write "); break;
162 case ADP_CPUread
: fprintf(fp
," ADP_CPUread "); break;
163 case ADP_CPUwrite
: fprintf(fp
," ADP_CPUwrite "); break;
164 case ADP_CPread
: fprintf(fp
," ADP_CPread "); break;
165 case ADP_CPwrite
: fprintf(fp
," ADP_CPwrite "); break;
166 case ADP_SetBreak
: fprintf(fp
," ADP_SetBreak "); break;
167 case ADP_ClearBreak
: fprintf(fp
," ADP_ClearBreak "); break;
168 case ADP_SetWatch
: fprintf(fp
," ADP_SetWatch "); break;
169 case ADP_ClearWatch
: fprintf(fp
," ADP_ClearWatch "); break;
170 case ADP_Execute
: fprintf(fp
," ADP_Execute "); break;
171 case ADP_Step
: fprintf(fp
," ADP_Step "); break;
172 case ADP_InterruptRequest
: fprintf(fp
," ADP_InterruptRequest "); break;
173 case ADP_HW_Emulation
: fprintf(fp
," ADP_HW_Emulation "); break;
174 case ADP_ICEbreakerHADP
: fprintf(fp
," ADP_ICEbreakerHADP "); break;
175 case ADP_ICEman
: fprintf(fp
," ADP_ICEman "); break;
176 case ADP_Profile
: fprintf(fp
," ADP_Profile "); break;
177 case ADP_InitialiseApplication
: fprintf(fp
," ADP_InitialiseApplication "); break;
178 case ADP_End
: fprintf(fp
," ADP_End "); break;
179 case ADP_TADPUnrecognised
: fprintf(fp
," ADP_TADPUnrecognised "); break;
180 case ADP_Stopped
: fprintf(fp
," ADP_Stopped "); break;
181 case ADP_TDCC_ToHost
: fprintf(fp
," ADP_TDCC_ToHost "); break;
182 case ADP_TDCC_FromHost
: fprintf(fp
," ADP_TDCC_FromHost "); break;
184 case CL_Unrecognised
: fprintf(fp
," CL_Unrecognised "); break;
185 case CL_WriteC
: fprintf(fp
," CL_WriteC "); break;
186 case CL_Write0
: fprintf(fp
," CL_Write0 "); break;
187 case CL_ReadC
: fprintf(fp
," CL_ReadC "); break;
188 case CL_System
: fprintf(fp
," CL_System "); break;
189 case CL_GetCmdLine
: fprintf(fp
," CL_GetCmdLine "); break;
190 case CL_Clock
: fprintf(fp
," CL_Clock "); break;
191 case CL_Time
: fprintf(fp
," CL_Time "); break;
192 case CL_Remove
: fprintf(fp
," CL_Remove "); break;
193 case CL_Rename
: fprintf(fp
," CL_Rename "); break;
194 case CL_Open
: fprintf(fp
," CL_Open "); break;
195 case CL_Close
: fprintf(fp
," CL_Close "); break;
196 case CL_Write
: fprintf(fp
," CL_Write "); break;
197 case CL_WriteX
: fprintf(fp
," CL_WriteX "); break;
198 case CL_Read
: fprintf(fp
," CL_Read "); break;
199 case CL_ReadX
: fprintf(fp
," CL_ReadX "); break;
200 case CL_Seek
: fprintf(fp
," CL_Seek "); break;
201 case CL_Flen
: fprintf(fp
," CL_Flen "); break;
202 case CL_IsTTY
: fprintf(fp
," CL_IsTTY "); break;
203 case CL_TmpNam
: fprintf(fp
," CL_TmpNam "); break;
205 default: fprintf(fp
," BadReason "); break;
210 if (((r
& 0xffffff) == ADP_CPUread
||
211 (r
& 0xffffff) == ADP_CPUwrite
) && (r
&0x80000000)==0)
213 fprintf(fp
,"%02x ", p
->data
[i
]);
217 for (; i
<p
->len
; i
+=4)
218 fprintf(fp
,"%08x ",WordAt(p
->data
+i
));
225 * TODO: this should be adjustable - it could be done by defining
226 * a reason code for DevSW_Ioctl. It could even be a
227 * per-devicechannel parameter.
229 static const unsigned int allocsize
= ADP_BUFFER_MIN_SIZE
;
231 #define illegalDevChanID(type) ((type) >= DC_NUM_CHANNELS)
233 /**********************************************************************/
236 * Function: initialise_read
237 * Purpose: Set up a read request for another packet
240 * In/Out: ds State structure to be initialised
246 static int initialise_read(DevSWState
*ds
)
248 struct data_packet
*dp
;
251 * try to claim the structure that will
252 * eventually hold the new packet.
254 if ((ds
->ds_nextreadpacket
= DevSW_AllocatePacket(allocsize
)) == NULL
)
258 * Calls into the device driver use the DriverCall structure: use
259 * the buffer we have just allocated, and declare its size. We
260 * are also obliged to clear the driver's context pointer.
262 dp
= &ds
->ds_activeread
.dc_packet
;
263 dp
->buf_len
= allocsize
;
264 dp
->data
= ds
->ds_nextreadpacket
->pk_buffer
;
266 ds
->ds_activeread
.dc_context
= NULL
;
272 * Function: initialise_write
273 * Purpose: Set up a write request for another packet
276 * Input: packet The packet to be written
278 * type The type of the packet
280 * In/Out: dc The structure to be intialised
284 static void initialise_write(DriverCall
*dc
, Packet
*packet
, DevChanID type
)
286 struct data_packet
*dp
= &dc
->dc_packet
;
288 dp
->len
= packet
->pk_length
;
289 dp
->data
= packet
->pk_buffer
;
293 * we are required to clear the state structure for the driver
295 dc
->dc_context
= NULL
;
299 * Function: enqueue_packet
300 * Purpose: move a newly read packet onto the appropriate queue
304 * In/Out: ds State structure with new packet
308 static void enqueue_packet(DevSWState
*ds
)
310 struct data_packet
*dp
= &ds
->ds_activeread
.dc_packet
;
311 Packet
*packet
= ds
->ds_nextreadpacket
;
314 * transfer the length
316 packet
->pk_length
= dp
->len
;
319 * take this packet out of the incoming slot
321 ds
->ds_nextreadpacket
= NULL
;
324 * try to put it on the correct input queue
326 if (illegalDevChanID(dp
->type
))
328 /* this shouldn't happen */
329 WARN("Illegal type for Rx packet");
330 DevSW_FreePacket(packet
);
333 Adp_addToQueue(&ds
->ds_readqueue
[dp
->type
], packet
);
337 * Function: flush_packet
338 * Purpose: Send a packet to the device driver
341 * Input: device The device to be written to
343 * In/Out: dc Describes the packet to be sent
347 * Post-conditions: If the whole packet was accepted by the device
348 * driver, then dc->dc_packet.data will be
351 static void flush_packet(const DeviceDescr
*device
, DriverCall
*dc
)
353 if (device
->DeviceWrite(dc
) > 0)
355 * the whole packet was swallowed
357 dc
->dc_packet
.data
= NULL
;
360 /**********************************************************************/
363 * These are the externally visible functions. They are documented in
366 Packet
*DevSW_AllocatePacket(const unsigned int length
)
370 if ((pk
= malloc(sizeof(*pk
))) == NULL
)
372 WARN("malloc failure");
376 if ((pk
->pk_buffer
= malloc(length
+CHAN_HEADER_SIZE
)) == NULL
)
378 WARN("malloc failure");
386 void DevSW_FreePacket(Packet
*pk
)
392 AdpErrs
DevSW_Open(DeviceDescr
*device
, const char *name
, const char *arg
,
393 const DevChanID type
)
398 * is this the very first open call for this driver?
400 if ((ds
= (DevSWState
*)(device
->SwitcherState
)) == NULL
)
403 * yes, it is: initialise state
405 if ((ds
= malloc(sizeof(*ds
))) == NULL
)
407 return adp_malloc_failure
;
409 (void)memset(ds
, 0, sizeof(*ds
));
410 device
->SwitcherState
= (void *)ds
;
414 * check that we haven't already been opened for this type
416 if ((ds
->ds_opendevchans
& (1 << type
)) != 0)
417 return adp_device_already_open
;
420 * if no opens have been done for this device, then do it now
422 if (ds
->ds_opendevchans
== 0)
423 if (device
->DeviceOpen(name
, arg
) < 0)
424 return adp_device_open_failed
;
429 ds
->ds_opendevchans
|= (1 << type
);
433 AdpErrs
DevSW_Match(const DeviceDescr
*device
, const char *name
,
436 return (device
->DeviceMatch(name
, arg
) == -1) ? adp_failed
: adp_ok
;
439 AdpErrs
DevSW_Close (DeviceDescr
*device
, const DevChanID type
)
441 DevSWState
*ds
= (DevSWState
*)(device
->SwitcherState
);
444 if ((ds
->ds_opendevchans
& (1 << type
)) == 0)
445 return adp_device_not_open
;
447 ds
->ds_opendevchans
&= ~(1 << type
);
450 * if this is the last close for this channel, then inform the driver
452 if (ds
->ds_opendevchans
== 0)
453 device
->DeviceClose();
456 * release all packets of the appropriate type
458 for (pk
= Adp_removeFromQueue(&(ds
->ds_readqueue
[type
]));
460 pk
= Adp_removeFromQueue(&(ds
->ds_readqueue
[type
])))
461 DevSW_FreePacket(pk
);
464 free ((char *) device
->SwitcherState
);
465 device
->SwitcherState
= 0x0;
471 AdpErrs
DevSW_Read(const DeviceDescr
*device
, const DevChanID type
,
472 Packet
**packet
, bool block
)
475 DevSWState
*ds
= device
->SwitcherState
;
478 * To try to get information out of the device driver as
479 * quickly as possible, we try and read more packets, even
480 * if a completed packet is already available.
484 * have we got a packet currently pending?
486 if (ds
->ds_nextreadpacket
== NULL
)
490 if (initialise_read(ds
) < 0) {
492 * we failed to initialise the next packet, but can
493 * still return a packet that has already arrived.
495 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
498 read_err
= device
->DeviceRead(&ds
->ds_activeread
, block
);
502 * driver has pulled in a complete packet, queue it up
505 printf("got a complete packet\n");
508 if (angelDebugLogEnable
)
509 dumpPacket(angelDebugLogFile
,"rx:",&ds
->ds_activeread
.dc_packet
);
512 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
516 * OK, return the head of the read queue for the given type
518 /* enqueue_packet(ds); */
519 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
523 printf("got a bad packet\n");
527 return adp_bad_packet
;
529 panic("DevSW_Read: bad read status %d", read_err
);
531 return 0; /* get rid of a potential compiler warning */
535 AdpErrs
DevSW_FlushPendingWrite(const DeviceDescr
*device
)
537 struct DriverCall
*dc
;
538 struct data_packet
*dp
;
540 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
544 * try to flush any packet that is still being written
546 if (dp
->data
!= NULL
)
548 flush_packet(device
, dc
);
550 /* see if it has gone */
551 if (dp
->data
!= NULL
)
552 return adp_write_busy
;
561 AdpErrs
DevSW_Write(const DeviceDescr
*device
, Packet
*packet
, DevChanID type
)
563 struct DriverCall
*dc
;
564 struct data_packet
*dp
;
566 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
569 if (illegalDevChanID(type
))
570 return adp_illegal_args
;
573 * try to flush any packet that is still being written
575 if (DevSW_FlushPendingWrite(device
) != adp_ok
)
576 return adp_write_busy
;
579 * we can take this packet - set things up, then try to get rid of it
581 initialise_write(dc
, packet
, type
);
583 if (angelDebugLogEnable
)
584 dumpPacket(angelDebugLogFile
,"tx:",&dc
->dc_packet
);
586 flush_packet(device
, dc
);
591 AdpErrs
DevSW_Ioctl(const DeviceDescr
*device
, const int opcode
, void *args
)
593 return (device
->DeviceIoctl(opcode
, args
) < 0) ? adp_failed
: adp_ok
;
596 bool DevSW_WriteFinished(const DeviceDescr
*device
)
598 struct DriverCall
*dc
;
599 struct data_packet
*dp
;
601 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
604 return (dp
== NULL
|| dp
->data
== NULL
);