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
32 static char *angelDebugFilename
= NULL
;
33 static FILE *angelDebugLogFile
= NULL
;
34 static int angelDebugLogEnable
= 0;
36 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(__CYGWIN32__) || 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)
71 if (!angelDebugLogFile
)
75 fprintf (angelDebugLogFile
,"ADP log file closed at %s\n",asctime(localtime(&t
)));
77 fclose (angelDebugLogFile
);
78 angelDebugLogFile
= NULL
;
81 void DevSW_SetLogEnable (int logEnableFlag
)
83 if (logEnableFlag
&& !angelDebugLogFile
)
85 else if (!logEnableFlag
&& angelDebugLogFile
)
88 angelDebugLogEnable
= logEnableFlag
;
92 void DevSW_SetLogfile (const char *filename
)
96 if (angelDebugFilename
)
98 free (angelDebugFilename
);
99 angelDebugFilename
= NULL
;
102 if (filename
&& *filename
)
104 angelDebugFilename
= strdup (filename
);
105 if (angelDebugLogEnable
)
111 #define WordAt(p) ((unsigned long) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)))
113 static void dumpPacket(FILE *fp
, char *label
, struct data_packet
*p
)
117 unsigned char channel
;
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
]);
127 channel
= p
->data
[0];
129 r
= WordAt(p
->data
+4);
131 fprintf(fp
,"R=%08x ",r
);
132 fprintf(fp
,"%s ", r
&0x80000000 ? "H<-T" : "H->T");
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;
150 switch (r
& 0xffffff)
152 case ADP_Booted
: fprintf(fp
," ADP_Booted "); break;
153 #if defined(ADP_TargetResetIndication)
154 case ADP_TargetResetIndication
: fprintf(fp
," ADP_TargetResetIndication "); break;
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;
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;
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;
211 default: fprintf(fp
," BadReason "); break;
216 if (((r
& 0xffffff) == ADP_CPUread
||
217 (r
& 0xffffff) == ADP_CPUwrite
) && (r
&0x80000000)==0)
219 fprintf(fp
,"%02x ", p
->data
[i
]);
223 for (; i
<p
->len
; i
+=4)
224 fprintf(fp
,"%08x ",WordAt(p
->data
+i
));
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.
235 static const unsigned int allocsize
= ADP_BUFFER_MIN_SIZE
;
237 #define illegalDevChanID(type) ((type) >= DC_NUM_CHANNELS)
239 /**********************************************************************/
242 * Function: initialise_read
243 * Purpose: Set up a read request for another packet
246 * In/Out: ds State structure to be initialised
252 static int initialise_read(DevSWState
*ds
)
254 struct data_packet
*dp
;
257 * try to claim the structure that will
258 * eventually hold the new packet.
260 if ((ds
->ds_nextreadpacket
= DevSW_AllocatePacket(allocsize
)) == NULL
)
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.
268 dp
= &ds
->ds_activeread
.dc_packet
;
269 dp
->buf_len
= allocsize
;
270 dp
->data
= ds
->ds_nextreadpacket
->pk_buffer
;
272 ds
->ds_activeread
.dc_context
= NULL
;
278 * Function: initialise_write
279 * Purpose: Set up a write request for another packet
282 * Input: packet The packet to be written
284 * type The type of the packet
286 * In/Out: dc The structure to be intialised
290 static void initialise_write(DriverCall
*dc
, Packet
*packet
, DevChanID type
)
292 struct data_packet
*dp
= &dc
->dc_packet
;
294 dp
->len
= packet
->pk_length
;
295 dp
->data
= packet
->pk_buffer
;
299 * we are required to clear the state structure for the driver
301 dc
->dc_context
= NULL
;
305 * Function: enqueue_packet
306 * Purpose: move a newly read packet onto the appropriate queue
310 * In/Out: ds State structure with new packet
314 static void enqueue_packet(DevSWState
*ds
)
316 struct data_packet
*dp
= &ds
->ds_activeread
.dc_packet
;
317 Packet
*packet
= ds
->ds_nextreadpacket
;
320 * transfer the length
322 packet
->pk_length
= dp
->len
;
325 * take this packet out of the incoming slot
327 ds
->ds_nextreadpacket
= NULL
;
330 * try to put it on the correct input queue
332 if (illegalDevChanID(dp
->type
))
334 /* this shouldn't happen */
335 WARN("Illegal type for Rx packet");
336 DevSW_FreePacket(packet
);
339 Adp_addToQueue(&ds
->ds_readqueue
[dp
->type
], packet
);
343 * Function: flush_packet
344 * Purpose: Send a packet to the device driver
347 * Input: device The device to be written to
349 * In/Out: dc Describes the packet to be sent
353 * Post-conditions: If the whole packet was accepted by the device
354 * driver, then dc->dc_packet.data will be
357 static void flush_packet(const DeviceDescr
*device
, DriverCall
*dc
)
359 if (device
->DeviceWrite(dc
) > 0)
361 * the whole packet was swallowed
363 dc
->dc_packet
.data
= NULL
;
366 /**********************************************************************/
369 * These are the externally visible functions. They are documented in
372 Packet
*DevSW_AllocatePacket(const unsigned int length
)
376 if ((pk
= malloc(sizeof(*pk
))) == NULL
)
378 WARN("malloc failure");
382 if ((pk
->pk_buffer
= malloc(length
+CHAN_HEADER_SIZE
)) == NULL
)
384 WARN("malloc failure");
392 void DevSW_FreePacket(Packet
*pk
)
398 AdpErrs
DevSW_Open(DeviceDescr
*device
, const char *name
, const char *arg
,
399 const DevChanID type
)
404 * is this the very first open call for this driver?
406 if ((ds
= (DevSWState
*)(device
->SwitcherState
)) == NULL
)
409 * yes, it is: initialise state
411 if ((ds
= malloc(sizeof(*ds
))) == NULL
)
413 return adp_malloc_failure
;
415 (void)memset(ds
, 0, sizeof(*ds
));
416 device
->SwitcherState
= (void *)ds
;
420 * check that we haven't already been opened for this type
422 if ((ds
->ds_opendevchans
& (1 << type
)) != 0)
423 return adp_device_already_open
;
426 * if no opens have been done for this device, then do it now
428 if (ds
->ds_opendevchans
== 0)
429 if (device
->DeviceOpen(name
, arg
) < 0)
430 return adp_device_open_failed
;
435 ds
->ds_opendevchans
|= (1 << type
);
439 AdpErrs
DevSW_Match(const DeviceDescr
*device
, const char *name
,
442 return (device
->DeviceMatch(name
, arg
) == -1) ? adp_failed
: adp_ok
;
445 AdpErrs
DevSW_Close (DeviceDescr
*device
, const DevChanID type
)
447 DevSWState
*ds
= (DevSWState
*)(device
->SwitcherState
);
450 if ((ds
->ds_opendevchans
& (1 << type
)) == 0)
451 return adp_device_not_open
;
453 ds
->ds_opendevchans
&= ~(1 << type
);
456 * if this is the last close for this channel, then inform the driver
458 if (ds
->ds_opendevchans
== 0)
459 device
->DeviceClose();
462 * release all packets of the appropriate type
464 for (pk
= Adp_removeFromQueue(&(ds
->ds_readqueue
[type
]));
466 pk
= Adp_removeFromQueue(&(ds
->ds_readqueue
[type
])))
467 DevSW_FreePacket(pk
);
470 free ((char *) device
->SwitcherState
);
471 device
->SwitcherState
= 0x0;
477 AdpErrs
DevSW_Read(const DeviceDescr
*device
, const DevChanID type
,
478 Packet
**packet
, bool block
)
481 DevSWState
*ds
= device
->SwitcherState
;
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.
490 * have we got a packet currently pending?
492 if (ds
->ds_nextreadpacket
== NULL
)
496 if (initialise_read(ds
) < 0) {
498 * we failed to initialise the next packet, but can
499 * still return a packet that has already arrived.
501 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
504 read_err
= device
->DeviceRead(&ds
->ds_activeread
, block
);
508 * driver has pulled in a complete packet, queue it up
511 printf("got a complete packet\n");
514 if (angelDebugLogEnable
)
515 dumpPacket(angelDebugLogFile
,"rx:",&ds
->ds_activeread
.dc_packet
);
518 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
522 * OK, return the head of the read queue for the given type
524 /* enqueue_packet(ds); */
525 *packet
= Adp_removeFromQueue(&ds
->ds_readqueue
[type
]);
529 printf("got a bad packet\n");
533 return adp_bad_packet
;
535 panic("DevSW_Read: bad read status %d", read_err
);
537 return 0; /* get rid of a potential compiler warning */
541 AdpErrs
DevSW_FlushPendingWrite(const DeviceDescr
*device
)
543 struct DriverCall
*dc
;
544 struct data_packet
*dp
;
546 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
550 * try to flush any packet that is still being written
552 if (dp
->data
!= NULL
)
554 flush_packet(device
, dc
);
556 /* see if it has gone */
557 if (dp
->data
!= NULL
)
558 return adp_write_busy
;
567 AdpErrs
DevSW_Write(const DeviceDescr
*device
, Packet
*packet
, DevChanID type
)
569 struct DriverCall
*dc
;
570 struct data_packet
*dp
;
572 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
575 if (illegalDevChanID(type
))
576 return adp_illegal_args
;
579 * try to flush any packet that is still being written
581 if (DevSW_FlushPendingWrite(device
) != adp_ok
)
582 return adp_write_busy
;
585 * we can take this packet - set things up, then try to get rid of it
587 initialise_write(dc
, packet
, type
);
589 if (angelDebugLogEnable
)
590 dumpPacket(angelDebugLogFile
,"tx:",&dc
->dc_packet
);
592 flush_packet(device
, dc
);
597 AdpErrs
DevSW_Ioctl(const DeviceDescr
*device
, const int opcode
, void *args
)
599 return (device
->DeviceIoctl(opcode
, args
) < 0) ? adp_failed
: adp_ok
;
602 bool DevSW_WriteFinished(const DeviceDescr
*device
)
604 struct DriverCall
*dc
;
605 struct data_packet
*dp
;
607 dc
= &((DevSWState
*)(device
->SwitcherState
))->ds_activewrite
;
610 return (dp
== NULL
|| dp
->data
== NULL
);