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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 391 void DevSW_FreePacket(Packet *pk) 392 { 393 free(pk->pk_buffer); 394 free(pk); 395 } 396 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 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 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 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 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 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 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 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