|
|
1.1 ! root 1: /* ! 2: * Written by Julian Elischer ([email protected]) ! 3: * for TRW Financial Systems for use under the MACH(2.5) operating system. ! 4: * ! 5: * TRW Financial Systems, in accordance with their agreement with Carnegie ! 6: * Mellon University, makes this software available to CMU to distribute ! 7: * or use in any manner that they see fit as long as this message is kept with ! 8: * the software. For this reason TFS also grants any other persons or ! 9: * organisations permission to use or modify this software. ! 10: * ! 11: * TFS supplies this software to be publicly redistributed ! 12: * on the understanding that TFS is not responsible for the correct ! 13: * functioning of this software in any circumstances. ! 14: * ! 15: * ! 16: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE ! 17: * -------------------- ----- ---------------------- ! 18: * CURRENT PATCH LEVEL: 1 00098 ! 19: * -------------------- ----- ---------------------- ! 20: * ! 21: * 16 Feb 93 Julian Elischer ADDED for SCSI system ! 22: * commenced: Sun Sep 27 18:14:01 PDT 1992 ! 23: */ ! 24: ! 25: #include <sys/types.h> ! 26: #include <ahb.h> ! 27: ! 28: #include <sys/param.h> ! 29: #include <sys/systm.h> ! 30: #include <sys/errno.h> ! 31: #include <sys/ioctl.h> ! 32: #include <sys/buf.h> ! 33: #include <sys/proc.h> ! 34: #include <sys/user.h> ! 35: ! 36: #ifdef MACH /* EITHER CMU OR OSF */ ! 37: #include <i386/ipl.h> ! 38: #include <i386at/scsi.h> ! 39: #include <i386at/scsiconf.h> ! 40: ! 41: #ifdef OSF /* OSF ONLY */ ! 42: #include <sys/table.h> ! 43: #include <i386/handler.h> ! 44: #include <i386/dispatcher.h> ! 45: #include <i386/AT386/atbus.h> ! 46: ! 47: #else OSF /* CMU ONLY */ ! 48: #include <i386at/atbus.h> ! 49: #include <i386/pio.h> ! 50: #endif OSF ! 51: #endif MACH /* end of MACH specific */ ! 52: ! 53: #ifdef __386BSD__ /* 386BSD specific */ ! 54: #define isa_dev isa_device ! 55: #define dev_unit id_unit ! 56: #define dev_addr id_iobase ! 57: ! 58: #include <i386/include/pio.h> ! 59: #include <i386/isa/isa_device.h> ! 60: #include <scsi/scsi_all.h> ! 61: #include <scsi/scsiconf.h> ! 62: #endif __386BSD__ ! 63: ! 64: /**/ ! 65: ! 66: #ifdef __386BSD__ ! 67: #ifdef DDB ! 68: int Debugger(); ! 69: #else ! 70: #define Debugger() panic("should call debugger here (adaptec.c)") ! 71: #endif /*DDB*/ ! 72: #endif __386BSD__ ! 73: ! 74: #ifdef MACH ! 75: int Debugger(); ! 76: #endif MACH ! 77: ! 78: typedef unsigned long int physaddr; ! 79: ! 80: #ifdef MACH ! 81: extern physaddr kvtophys(); ! 82: #define PHYSTOKV(x) phystokv(x) ! 83: #define KVTOPHYS(x) kvtophys(x) ! 84: #endif MACH ! 85: ! 86: #ifdef __386BSD__ ! 87: #define PHYSTOKV(x) (x | 0xFE000000) ! 88: #define KVTOPHYS(x) vtophys(x) ! 89: #endif __386BSD__ ! 90: ! 91: extern int delaycount; /* from clock setup code */ ! 92: #define NUM_CONCURRENT 16 /* number of concurrent ops per board */ ! 93: #define AHB_NSEG 33 /* number of dma segments supported */ ! 94: #define FUDGE(X) (X>>1) /* our loops are slower than spinwait() */ ! 95: /**/ ! 96: /***********************************************************************\ ! 97: * AHA1740 standard EISA Host ID regs (Offset from slot base) * ! 98: \***********************************************************************/ ! 99: #define HID0 0xC80 /* 0,1: msb of ID2, 3-7: ID1 */ ! 100: #define HID1 0xC81 /* 0-4: ID3, 4-7: LSB ID2 */ ! 101: #define HID2 0xC82 /* product, 0=174[20] 1 = 1744 */ ! 102: #define HID3 0xC83 /* firmware revision */ ! 103: ! 104: #define CHAR1(B1,B2) (((B1>>2) & 0x1F) | '@') ! 105: #define CHAR2(B1,B2) (((B1<<3) & 0x18) | ((B2>>5) & 0x7)|'@') ! 106: #define CHAR3(B1,B2) ((B2 & 0x1F) | '@') ! 107: ! 108: /* AHA1740 EISA board control registers (Offset from slot base) */ ! 109: #define EBCTRL 0xC84 ! 110: #define CDEN 0x01 ! 111: /***********************************************************************\ ! 112: * AHA1740 EISA board mode registers (Offset from slot base) * ! 113: \***********************************************************************/ ! 114: #define PORTADDR 0xCC0 ! 115: #define PORTADDR_ENHANCED 0x80 ! 116: #define BIOSADDR 0xCC1 ! 117: #define INTDEF 0xCC2 ! 118: #define SCSIDEF 0xCC3 ! 119: #define BUSDEF 0xCC4 ! 120: #define RESV0 0xCC5 ! 121: #define RESV1 0xCC6 ! 122: #define RESV2 0xCC7 ! 123: /**** bit definitions for INTDEF ****/ ! 124: #define INT9 0x00 ! 125: #define INT10 0x01 ! 126: #define INT11 0x02 ! 127: #define INT12 0x03 ! 128: #define INT14 0x05 ! 129: #define INT15 0x06 ! 130: #define INTHIGH 0x08 /* int high=ACTIVE (else edge) */ ! 131: #define INTEN 0x10 ! 132: /**** bit definitions for SCSIDEF ****/ ! 133: #define HSCSIID 0x0F /* our SCSI ID */ ! 134: #define RSTPWR 0x10 /* reset scsi bus on power up or reset */ ! 135: /**** bit definitions for BUSDEF ****/ ! 136: #define B0uS 0x00 /* give up bus immediatly */ ! 137: #define B4uS 0x01 /* delay 4uSec. */ ! 138: #define B8uS 0x02 ! 139: /***********************************************************************\ ! 140: * AHA1740 ENHANCED mode mailbox control regs (Offset from slot base) * ! 141: \***********************************************************************/ ! 142: #define MBOXOUT0 0xCD0 ! 143: #define MBOXOUT1 0xCD1 ! 144: #define MBOXOUT2 0xCD2 ! 145: #define MBOXOUT3 0xCD3 ! 146: ! 147: #define ATTN 0xCD4 ! 148: #define G2CNTRL 0xCD5 ! 149: #define G2INTST 0xCD6 ! 150: #define G2STAT 0xCD7 ! 151: ! 152: #define MBOXIN0 0xCD8 ! 153: #define MBOXIN1 0xCD9 ! 154: #define MBOXIN2 0xCDA ! 155: #define MBOXIN3 0xCDB ! 156: ! 157: #define G2STAT2 0xCDC ! 158: ! 159: /*******************************************************\ ! 160: * Bit definitions for the 5 control/status registers * ! 161: \*******************************************************/ ! 162: #define ATTN_TARGET 0x0F ! 163: #define ATTN_OPCODE 0xF0 ! 164: #define OP_IMMED 0x10 ! 165: #define AHB_TARG_RESET 0x80 ! 166: #define OP_START_ECB 0x40 ! 167: #define OP_ABORT_ECB 0x50 ! 168: ! 169: #define G2CNTRL_SET_HOST_READY 0x20 ! 170: #define G2CNTRL_CLEAR_EISA_INT 0x40 ! 171: #define G2CNTRL_HARD_RESET 0x80 ! 172: ! 173: #define G2INTST_TARGET 0x0F ! 174: #define G2INTST_INT_STAT 0xF0 ! 175: #define AHB_ECB_OK 0x10 ! 176: #define AHB_ECB_RECOVERED 0x50 ! 177: #define AHB_HW_ERR 0x70 ! 178: #define AHB_IMMED_OK 0xA0 ! 179: #define AHB_ECB_ERR 0xC0 ! 180: #define AHB_ASN 0xD0 /* for target mode */ ! 181: #define AHB_IMMED_ERR 0xE0 ! 182: ! 183: #define G2STAT_BUSY 0x01 ! 184: #define G2STAT_INT_PEND 0x02 ! 185: #define G2STAT_MBOX_EMPTY 0x04 ! 186: ! 187: #define G2STAT2_HOST_READY 0x01 ! 188: /**/ ! 189: ! 190: struct ahb_dma_seg ! 191: { ! 192: physaddr addr; ! 193: long len; ! 194: }; ! 195: ! 196: struct ahb_ecb_status ! 197: { ! 198: u_short status; ! 199: # define ST_DON 0x0001 ! 200: # define ST_DU 0x0002 ! 201: # define ST_QF 0x0008 ! 202: # define ST_SC 0x0010 ! 203: # define ST_DO 0x0020 ! 204: # define ST_CH 0x0040 ! 205: # define ST_INT 0x0080 ! 206: # define ST_ASA 0x0100 ! 207: # define ST_SNS 0x0200 ! 208: # define ST_INI 0x0800 ! 209: # define ST_ME 0x1000 ! 210: # define ST_ECA 0x4000 ! 211: u_char ha_status; ! 212: # define HS_OK 0x00 ! 213: # define HS_CMD_ABORTED_HOST 0x04 ! 214: # define HS_CMD_ABORTED_ADAPTER 0x05 ! 215: # define HS_TIMED_OUT 0x11 ! 216: # define HS_HARDWARE_ERR 0x20 ! 217: # define HS_SCSI_RESET_ADAPTER 0x22 ! 218: # define HS_SCSI_RESET_INCOMING 0x23 ! 219: u_char targ_status; ! 220: # define TS_OK 0x00 ! 221: # define TS_CHECK_CONDITION 0x02 ! 222: # define TS_BUSY 0x08 ! 223: u_long resid_count; ! 224: u_long resid_addr; ! 225: u_short addit_status; ! 226: u_char sense_len; ! 227: u_char unused[9]; ! 228: u_char cdb[6]; ! 229: }; ! 230: ! 231: /**/ ! 232: ! 233: struct ecb ! 234: { ! 235: u_char opcode; ! 236: # define ECB_SCSI_OP 0x01 ! 237: u_char :4; ! 238: u_char options:3; ! 239: u_char :1; ! 240: short opt1; ! 241: # define ECB_CNE 0x0001 ! 242: # define ECB_DI 0x0080 ! 243: # define ECB_SES 0x0400 ! 244: # define ECB_S_G 0x1000 ! 245: # define ECB_DSB 0x4000 ! 246: # define ECB_ARS 0x8000 ! 247: short opt2; ! 248: # define ECB_LUN 0x0007 ! 249: # define ECB_TAG 0x0008 ! 250: # define ECB_TT 0x0030 ! 251: # define ECB_ND 0x0040 ! 252: # define ECB_DAT 0x0100 ! 253: # define ECB_DIR 0x0200 ! 254: # define ECB_ST 0x0400 ! 255: # define ECB_CHK 0x0800 ! 256: # define ECB_REC 0x4000 ! 257: # define ECB_NRB 0x8000 ! 258: u_short unused1; ! 259: physaddr data; ! 260: u_long datalen; ! 261: physaddr status; ! 262: physaddr chain; ! 263: short unused2; ! 264: short unused3; ! 265: physaddr sense; ! 266: u_char senselen; ! 267: u_char cdblen; ! 268: short cksum; ! 269: u_char cdb[12]; ! 270: /*-----------------end of hardware supported fields----------------*/ ! 271: struct ecb *next; /* in free list */ ! 272: struct scsi_xfer *xs; /* the scsi_xfer for this cmd */ ! 273: long int delta; /* difference from previous*/ ! 274: struct ecb *later,*sooner; ! 275: int flags; ! 276: #define ECB_FREE 0 ! 277: #define ECB_ACTIVE 1 ! 278: #define ECB_ABORTED 2 ! 279: #define ECB_IMMED 4 ! 280: #define ECB_IMMED_FAIL 8 ! 281: struct ahb_dma_seg ahb_dma[AHB_NSEG]; ! 282: struct ahb_ecb_status ecb_status; ! 283: struct scsi_sense_data ecb_sense; ! 284: }; ! 285: ! 286: struct ecb *ahb_soonest = (struct ecb *)0; ! 287: struct ecb *ahb_latest = (struct ecb *)0; ! 288: long int ahb_furtherest = 0; /* longest time in the timeout queue */ ! 289: /**/ ! 290: ! 291: struct ahb_data ! 292: { ! 293: int flags; ! 294: #define AHB_INIT 0x01; ! 295: int baseport; ! 296: struct ecb ecbs[NUM_CONCURRENT]; ! 297: struct ecb *free_ecb; ! 298: int our_id; /* our scsi id */ ! 299: int vect; ! 300: struct ecb *immed_ecb; /* an outstanding immediete command */ ! 301: } ahb_data[NAHB]; ! 302: ! 303: int ahbprobe(); ! 304: int ahb_attach(); ! 305: int ahbintr(); ! 306: int ahb_scsi_cmd(); ! 307: int ahb_timeout(); ! 308: struct ecb *cheat; ! 309: void ahbminphys(); ! 310: long int ahb_adapter_info(); ! 311: ! 312: #ifdef MACH ! 313: struct isa_driver ahbdriver = { ahbprobe, 0, ahb_attach, "ahb", 0, 0, 0}; ! 314: int (*ahbintrs[])() = {ahbintr, 0}; ! 315: #endif MACH ! 316: ! 317: #ifdef __386BSD__ ! 318: struct isa_driver ahbdriver = { ahbprobe, ahb_attach, "ahb"}; ! 319: #endif __386BSD__ ! 320: ! 321: #define MAX_SLOTS 8 ! 322: static ahb_slot = 0; /* slot last board was found in */ ! 323: static ahb_unit = 0; ! 324: int ahb_debug = 0; ! 325: #define AHB_SHOWECBS 0x01 ! 326: #define AHB_SHOWINTS 0x02 ! 327: #define AHB_SHOWCMDS 0x04 ! 328: #define AHB_SHOWMISC 0x08 ! 329: #define FAIL 1 ! 330: #define SUCCESS 0 ! 331: #define PAGESIZ 4096 ! 332: ! 333: struct scsi_switch ahb_switch = ! 334: { ! 335: ahb_scsi_cmd, ! 336: ahbminphys, ! 337: 0, ! 338: 0, ! 339: ahb_adapter_info, ! 340: 0,0,0 ! 341: }; ! 342: ! 343: /**/ ! 344: /***********************************************************************\ ! 345: * Function to send a command out through a mailbox * ! 346: \***********************************************************************/ ! 347: ahb_send_mbox( int unit ! 348: ,int opcode ! 349: ,int target ! 350: ,struct ecb *ecb) ! 351: { ! 352: int port = ahb_data[unit].baseport; ! 353: int spincount = FUDGE(delaycount) * 1; /* 1ms should be enough */ ! 354: int s = splbio(); ! 355: int stport = port + G2STAT; ! 356: ! 357: while( ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY)) ! 358: != (G2STAT_MBOX_EMPTY)) ! 359: && (spincount--)); ! 360: if(spincount == -1) ! 361: { ! 362: printf("ahb%d: board not responding\n",unit); ! 363: Debugger(); ! 364: } ! 365: ! 366: outl(port + MBOXOUT0,KVTOPHYS(ecb)); /* don't know this will work */ ! 367: outb(port + ATTN, opcode|target); ! 368: ! 369: splx(s); ! 370: } ! 371: ! 372: /***********************************************************************\ ! 373: * Function to poll for command completion when in poll mode * ! 374: \***********************************************************************/ ! 375: ahb_poll(int unit ,int wait) /* in msec */ ! 376: { ! 377: int port = ahb_data[unit].baseport; ! 378: int spincount = FUDGE(delaycount) * wait; /* in msec */ ! 379: int stport = port + G2STAT; ! 380: int start = spincount; ! 381: ! 382: retry: ! 383: while( (spincount--) && (!(inb(stport) & G2STAT_INT_PEND))); ! 384: if(spincount == -1) ! 385: { ! 386: printf("ahb%d: board not responding\n",unit); ! 387: return(EIO); ! 388: } ! 389: if ((int)cheat != PHYSTOKV(inl(port + MBOXIN0))) ! 390: { ! 391: printf("discarding %x ",inl(port + MBOXIN0)); ! 392: outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT); ! 393: spinwait(50); ! 394: goto retry; ! 395: }/* don't know this will work */ ! 396: ahbintr(unit); ! 397: return(0); ! 398: } ! 399: /***********************************************************************\ ! 400: * Function to send an immediate type command to the adapter * ! 401: \***********************************************************************/ ! 402: ahb_send_immed( int unit ! 403: ,int target ! 404: ,u_long cmd) ! 405: { ! 406: int port = ahb_data[unit].baseport; ! 407: int spincount = FUDGE(delaycount) * 1; /* 1ms should be enough */ ! 408: int s = splbio(); ! 409: int stport = port + G2STAT; ! 410: ! 411: while( ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY)) ! 412: != (G2STAT_MBOX_EMPTY)) ! 413: && (spincount--)); ! 414: if(spincount == -1) ! 415: { ! 416: printf("ahb%d: board not responding\n",unit); ! 417: Debugger(); ! 418: } ! 419: ! 420: outl(port + MBOXOUT0,cmd); /* don't know this will work */ ! 421: outb(port + G2CNTRL, G2CNTRL_SET_HOST_READY); ! 422: outb(port + ATTN, OP_IMMED | target); ! 423: splx(s); ! 424: } ! 425: ! 426: /**/ ! 427: ! 428: /*******************************************************\ ! 429: * Check the slots looking for a board we recognise * ! 430: * If we find one, note it's address (slot) and call * ! 431: * the actual probe routine to check it out. * ! 432: \*******************************************************/ ! 433: ahbprobe(dev) ! 434: struct isa_dev *dev; ! 435: { ! 436: int port; ! 437: u_char byte1,byte2,byte3; ! 438: ahb_slot++; ! 439: while (ahb_slot<8) ! 440: { ! 441: port = 0x1000 * ahb_slot; ! 442: byte1 = inb(port + HID0); ! 443: byte2 = inb(port + HID1); ! 444: byte3 = inb(port + HID2); ! 445: if(byte1 == 0xff) ! 446: { ! 447: ahb_slot++; ! 448: continue; ! 449: } ! 450: if ((CHAR1(byte1,byte2) == 'A') ! 451: && (CHAR2(byte1,byte2) == 'D') ! 452: && (CHAR3(byte1,byte2) == 'P') ! 453: && ((byte3 == 0 ) || (byte3 == 1))) ! 454: { ! 455: dev->dev_addr = port; ! 456: return(ahbprobe1(dev) ? 0x1000 : 0); ! 457: } ! 458: ahb_slot++; ! 459: } ! 460: return(0); ! 461: } ! 462: /*******************************************************\ ! 463: * Check if the device can be found at the port given * ! 464: * and if so, set it up ready for further work * ! 465: * as an argument, takes the isa_dev structure from * ! 466: * autoconf.c * ! 467: \*******************************************************/ ! 468: ahbprobe1(dev) ! 469: struct isa_dev *dev; ! 470: { ! 471: /***********************************************\ ! 472: * find unit and check we have that many defined * ! 473: \***********************************************/ ! 474: int unit = ahb_unit; ! 475: #if defined(OSF) ! 476: static ihandler_t ahb_handler[NAHB]; ! 477: static ihandler_id_t *ahb_handler_id[NAHB]; ! 478: register ihandler_t *chp = &ahb_handler[unit];; ! 479: #endif /* defined(OSF) */ ! 480: ! 481: dev->dev_unit = unit; ! 482: ahb_data[unit].baseport = dev->dev_addr; ! 483: if(unit >= NAHB) ! 484: { ! 485: printf("ahb: unit number (%d) too high\n",unit); ! 486: return(0); ! 487: } ! 488: /***********************************************\ ! 489: * Try initialise a unit at this location * ! 490: * sets up dma and bus speed, loads ahb_data[unit].vect* ! 491: \***********************************************/ ! 492: if (ahb_init(unit) != 0) ! 493: { ! 494: return(0); ! 495: } ! 496: ! 497: /***********************************************\ ! 498: * If it's there, put in it's interrupt vectors * ! 499: \***********************************************/ ! 500: #ifdef MACH ! 501: #if defined(OSF) /* OSF */ ! 502: chp->ih_level = dev->dev_pic; ! 503: chp->ih_handler = dev->dev_intr[0]; ! 504: chp->ih_resolver = i386_resolver; ! 505: chp->ih_rdev = dev; ! 506: chp->ih_stats.intr_type = INTR_DEVICE; ! 507: chp->ih_stats.intr_cnt = 0; ! 508: chp->ih_hparam[0].intparam = unit; ! 509: if ((ahb_handler_id[unit] = handler_add(chp)) != NULL) ! 510: handler_enable(ahb_handler_id[unit]); ! 511: else ! 512: panic("Unable to add ahb interrupt handler"); ! 513: #else /* CMU */ ! 514: dev->dev_pic = ahb_data[unit].vect; ! 515: take_dev_irq(dev); ! 516: #endif /* !defined(OSF) */ ! 517: printf("port=%x spl=%d\n", dev->dev_addr, dev->dev_spl); ! 518: #endif MACH ! 519: #ifdef __386BSD__ /* 386BSD */ ! 520: dev->id_irq = (1 << ahb_data[unit].vect); ! 521: dev->id_drq = -1; /* use EISA dma */ ! 522: printf("\n **"); ! 523: #endif __386BSD__ ! 524: ! 525: ahb_unit++; ! 526: return(1); ! 527: } ! 528: ! 529: /***********************************************\ ! 530: * Attach all the sub-devices we can find * ! 531: \***********************************************/ ! 532: ahb_attach(dev) ! 533: struct isa_dev *dev; ! 534: { ! 535: int unit = dev->dev_unit; ! 536: ! 537: ! 538: #ifdef __386BSD__ ! 539: printf("ahb%d: probing for scsi devices..\n", unit); ! 540: #endif __386BSD__ ! 541: ! 542: /***********************************************\ ! 543: * ask the adapter what subunits are present * ! 544: \***********************************************/ ! 545: scsi_attachdevs( unit, ahb_data[unit].our_id, &ahb_switch); ! 546: #if defined(OSF) ! 547: ahb_attached[unit]=1; ! 548: #endif /* defined(OSF) */ ! 549: if(!unit) /* only one for all boards */ ! 550: { ! 551: ahb_timeout(0); ! 552: } ! 553: return; ! 554: } ! 555: ! 556: /***********************************************\ ! 557: * Return some information to the caller about * ! 558: * the adapter and it's capabilities * ! 559: \***********************************************/ ! 560: long int ahb_adapter_info(unit) ! 561: int unit; ! 562: { ! 563: return(2); /* 2 outstanding requests at a time per device */ ! 564: } ! 565: ! 566: /***********************************************\ ! 567: * Catch an interrupt from the adaptor * ! 568: \***********************************************/ ! 569: ahbintr(unit) ! 570: { ! 571: struct ecb *ecb; ! 572: unsigned char stat; ! 573: register i; ! 574: u_char ahbstat; ! 575: int target; ! 576: long int mboxval; ! 577: ! 578: int port = ahb_data[unit].baseport; ! 579: ! 580: if(scsi_debug & PRINTROUTINES) ! 581: printf("ahbintr "); ! 582: ! 583: #if defined(OSF) ! 584: if (!ahb_attached[unit]) ! 585: { ! 586: return(1); ! 587: } ! 588: #endif /* defined(OSF) */ ! 589: while(inb(port + G2STAT) & G2STAT_INT_PEND) ! 590: { ! 591: /***********************************************\ ! 592: * First get all the information and then * ! 593: * acknowlege the interrupt * ! 594: \***********************************************/ ! 595: ahbstat = inb(port + G2INTST); ! 596: target = ahbstat & G2INTST_TARGET; ! 597: stat = ahbstat & G2INTST_INT_STAT; ! 598: mboxval = inl(port + MBOXIN0);/* don't know this will work */ ! 599: outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT); ! 600: if(scsi_debug & TRACEINTERRUPTS) ! 601: printf("status = 0x%x ",stat); ! 602: /***********************************************\ ! 603: * Process the completed operation * ! 604: \***********************************************/ ! 605: ! 606: if(stat == AHB_ECB_OK) /* common case is fast */ ! 607: { ! 608: ecb = (struct ecb *)PHYSTOKV(mboxval); ! 609: } ! 610: else ! 611: { ! 612: switch(stat) ! 613: { ! 614: case AHB_IMMED_OK: ! 615: ecb = ahb_data[unit].immed_ecb; ! 616: ahb_data[unit].immed_ecb = 0; ! 617: break; ! 618: case AHB_IMMED_ERR: ! 619: ecb = ahb_data[unit].immed_ecb; ! 620: ecb->flags |= ECB_IMMED_FAIL; ! 621: ahb_data[unit].immed_ecb = 0; ! 622: break; ! 623: case AHB_ASN: /* for target mode */ ! 624: ecb = 0; ! 625: break; ! 626: case AHB_HW_ERR: ! 627: ecb = 0; ! 628: break; ! 629: case AHB_ECB_RECOVERED: ! 630: ecb = (struct ecb *)PHYSTOKV(mboxval); ! 631: break; ! 632: case AHB_ECB_ERR: ! 633: ecb = (struct ecb *)PHYSTOKV(mboxval); ! 634: break; ! 635: default: ! 636: printf(" Unknown return from ahb%d(%x)\n",unit,ahbstat); ! 637: ecb=0; ! 638: } ! 639: } ! 640: if(ecb) ! 641: { ! 642: if(ahb_debug & AHB_SHOWCMDS ) ! 643: { ! 644: ahb_show_scsi_cmd(ecb->xs); ! 645: } ! 646: if((ahb_debug & AHB_SHOWECBS) && ecb) ! 647: printf("<int ecb(%x)>",ecb); ! 648: ahb_remove_timeout(ecb); ! 649: ahb_done(unit,ecb,((stat == AHB_ECB_OK)?SUCCESS:FAIL)); ! 650: } ! 651: } ! 652: return(1); ! 653: } ! 654: ! 655: /***********************************************\ ! 656: * We have a ecb which has been processed by the * ! 657: * adaptor, now we look to see how the operation * ! 658: * went. * ! 659: \***********************************************/ ! 660: ahb_done(unit,ecb,state) ! 661: int unit,state; ! 662: struct ecb *ecb; ! 663: { ! 664: struct ahb_ecb_status *stat = &ecb->ecb_status; ! 665: struct scsi_sense_data *s1,*s2; ! 666: struct scsi_xfer *xs = ecb->xs; ! 667: ! 668: if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS)) ! 669: printf("ahb_done "); ! 670: /***********************************************\ ! 671: * Otherwise, put the results of the operation * ! 672: * into the xfer and call whoever started it * ! 673: \***********************************************/ ! 674: if(ecb->flags & ECB_IMMED) ! 675: { ! 676: if(ecb->flags & ECB_IMMED_FAIL) ! 677: { ! 678: xs->error = XS_DRIVER_STUFFUP; ! 679: } ! 680: goto done; ! 681: } ! 682: if ( (state == SUCCESS) || (xs->flags & SCSI_ERR_OK)) ! 683: { /* All went correctly OR errors expected */ ! 684: xs->resid = 0; ! 685: xs->error = 0; ! 686: } ! 687: else ! 688: { ! 689: ! 690: s1 = &(ecb->ecb_sense); ! 691: s2 = &(xs->sense); ! 692: ! 693: if(stat->ha_status) ! 694: { ! 695: switch(stat->ha_status) ! 696: { ! 697: case HS_SCSI_RESET_ADAPTER: ! 698: break; ! 699: case HS_SCSI_RESET_INCOMING: ! 700: break; ! 701: case HS_CMD_ABORTED_HOST: /* No response */ ! 702: case HS_CMD_ABORTED_ADAPTER: /* No response */ ! 703: break; ! 704: case HS_TIMED_OUT: /* No response */ ! 705: if (ahb_debug & AHB_SHOWMISC) ! 706: { ! 707: printf("timeout reported back\n"); ! 708: } ! 709: xs->error = XS_TIMEOUT; ! 710: break; ! 711: default: /* Other scsi protocol messes */ ! 712: xs->error = XS_DRIVER_STUFFUP; ! 713: if (ahb_debug & AHB_SHOWMISC) ! 714: { ! 715: printf("unexpected ha_status: %x\n", ! 716: stat->ha_status); ! 717: } ! 718: } ! 719: ! 720: } ! 721: else ! 722: { ! 723: switch(stat->targ_status) ! 724: { ! 725: case TS_CHECK_CONDITION: ! 726: /* structure copy!!!!!*/ ! 727: *s2=*s1; ! 728: xs->error = XS_SENSE; ! 729: break; ! 730: case TS_BUSY: ! 731: xs->error = XS_BUSY; ! 732: break; ! 733: default: ! 734: if (ahb_debug & AHB_SHOWMISC) ! 735: { ! 736: printf("unexpected targ_status: %x\n", ! 737: stat->targ_status); ! 738: } ! 739: xs->error = XS_DRIVER_STUFFUP; ! 740: } ! 741: } ! 742: } ! 743: done: xs->flags |= ITSDONE; ! 744: ahb_free_ecb(unit,ecb, xs->flags); ! 745: if(xs->when_done) ! 746: (*(xs->when_done))(xs->done_arg,xs->done_arg2); ! 747: } ! 748: ! 749: /***********************************************\ ! 750: * A ecb (and hence a mbx-out is put onto the * ! 751: * free list. * ! 752: \***********************************************/ ! 753: ahb_free_ecb(unit,ecb, flags) ! 754: struct ecb *ecb; ! 755: { ! 756: unsigned int opri; ! 757: ! 758: if(scsi_debug & PRINTROUTINES) ! 759: printf("ecb%d(0x%x)> ",unit,flags); ! 760: if (!(flags & SCSI_NOMASK)) ! 761: opri = splbio(); ! 762: ! 763: ecb->next = ahb_data[unit].free_ecb; ! 764: ahb_data[unit].free_ecb = ecb; ! 765: ecb->flags = ECB_FREE; ! 766: /***********************************************\ ! 767: * If there were none, wake abybody waiting for * ! 768: * one to come free, starting with queued entries* ! 769: \***********************************************/ ! 770: if (!ecb->next) { ! 771: wakeup(&ahb_data[unit].free_ecb); ! 772: } ! 773: if (!(flags & SCSI_NOMASK)) ! 774: splx(opri); ! 775: } ! 776: ! 777: /***********************************************\ ! 778: * Get a free ecb (and hence mbox-out entry) * ! 779: \***********************************************/ ! 780: struct ecb * ! 781: ahb_get_ecb(unit,flags) ! 782: { ! 783: unsigned opri; ! 784: struct ecb *rc; ! 785: ! 786: if(scsi_debug & PRINTROUTINES) ! 787: printf("<ecb%d(0x%x) ",unit,flags); ! 788: if (!(flags & SCSI_NOMASK)) ! 789: opri = splbio(); ! 790: /***********************************************\ ! 791: * If we can and have to, sleep waiting for one * ! 792: * to come free * ! 793: \***********************************************/ ! 794: while ((!(rc = ahb_data[unit].free_ecb)) && (!(flags & SCSI_NOSLEEP))) ! 795: { ! 796: sleep(&ahb_data[unit].free_ecb, PRIBIO); ! 797: } ! 798: if (rc) ! 799: { ! 800: ahb_data[unit].free_ecb = rc->next; ! 801: rc->flags = ECB_ACTIVE; ! 802: } ! 803: if (!(flags & SCSI_NOMASK)) ! 804: splx(opri); ! 805: return(rc); ! 806: } ! 807: ! 808: ! 809: ! 810: /***********************************************\ ! 811: * Start the board, ready for normal operation * ! 812: \***********************************************/ ! 813: ahb_init(unit) ! 814: int unit; ! 815: { ! 816: int port = ahb_data[unit].baseport; ! 817: int intdef; ! 818: int spincount = FUDGE(delaycount) * 1000; /* 1 sec enough? */ ! 819: int i; ! 820: int stport = port + G2STAT; ! 821: #define NO_NO 1 ! 822: #ifdef NO_NO ! 823: /***********************************************\ ! 824: * reset board, If it doesn't respond, assume * ! 825: * that it's not there.. good for the probe * ! 826: \***********************************************/ ! 827: outb(port + EBCTRL,CDEN); /* enable full card */ ! 828: outb(port + PORTADDR,PORTADDR_ENHANCED); ! 829: ! 830: outb(port + G2CNTRL,G2CNTRL_HARD_RESET); ! 831: spinwait(1); ! 832: outb(port + G2CNTRL,0); ! 833: spinwait(10); ! 834: while( ((inb(stport) & G2STAT_BUSY )) ! 835: && (spincount--)); ! 836: if(spincount == -1) ! 837: { ! 838: if (ahb_debug & AHB_SHOWMISC) ! 839: printf("ahb_init: No answer from bt742a board\n"); ! 840: return(ENXIO); ! 841: } ! 842: i = inb(port + MBOXIN0) & 0xff; ! 843: if(i) ! 844: { ! 845: printf("self test failed, val = 0x%x\n",i); ! 846: return(EIO); ! 847: } ! 848: #endif ! 849: while( inb(stport) & G2STAT_INT_PEND) ! 850: { ! 851: printf("."); ! 852: outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT); ! 853: spinwait(10); ! 854: } ! 855: outb(port + EBCTRL,CDEN); /* enable full card */ ! 856: outb(port + PORTADDR,PORTADDR_ENHANCED); ! 857: /***********************************************\ ! 858: * Assume we have a board at this stage * ! 859: * setup dma channel from jumpers and save int * ! 860: * level * ! 861: \***********************************************/ ! 862: #ifdef __386BSD__ ! 863: printf("ahb%d reading board settings, ",unit); ! 864: #define PRNT(x) ! 865: #else __386BSD__ ! 866: printf("ahb%d:",unit); ! 867: #define PRNT(x) printf(x) ! 868: #endif __386BSD__ ! 869: ! 870: intdef = inb(port + INTDEF); ! 871: switch(intdef & 0x07) ! 872: { ! 873: case INT9: ! 874: ahb_data[unit].vect = 9; ! 875: PRNT("int=9 "); ! 876: break; ! 877: case INT10: ! 878: ahb_data[unit].vect = 10; ! 879: PRNT("int=10 "); ! 880: break; ! 881: case INT11: ! 882: ahb_data[unit].vect = 11; ! 883: PRNT("int=11 "); ! 884: break; ! 885: case INT12: ! 886: ahb_data[unit].vect = 12; ! 887: PRNT("int=12 "); ! 888: break; ! 889: case INT14: ! 890: ahb_data[unit].vect = 14; ! 891: PRNT("int=14 "); ! 892: break; ! 893: case INT15: ! 894: ahb_data[unit].vect = 15; ! 895: PRNT("int=15 "); ! 896: break; ! 897: default: ! 898: printf("illegal int setting\n"); ! 899: return(EIO); ! 900: } ! 901: outb(port + INTDEF ,(intdef | INTEN)); /* make sure we can interrupt */ ! 902: /* who are we on the scsi bus */ ! 903: ahb_data[unit].our_id = (inb(port + SCSIDEF) & HSCSIID); ! 904: ! 905: /***********************************************\ ! 906: * link up all our ECBs into a free list * ! 907: \***********************************************/ ! 908: for (i=0; i < NUM_CONCURRENT; i++) ! 909: { ! 910: ahb_data[unit].ecbs[i].next = ahb_data[unit].free_ecb; ! 911: ahb_data[unit].free_ecb = &ahb_data[unit].ecbs[i]; ! 912: ahb_data[unit].free_ecb->flags = ECB_FREE; ! 913: } ! 914: ! 915: /***********************************************\ ! 916: * Note that we are going and return (to probe) * ! 917: \***********************************************/ ! 918: ahb_data[unit].flags |= AHB_INIT; ! 919: return( 0 ); ! 920: } ! 921: ! 922: ! 923: #ifndef min ! 924: #define min(x,y) (x < y ? x : y) ! 925: #endif min ! 926: ! 927: ! 928: void ahbminphys(bp) ! 929: struct buf *bp; ! 930: { ! 931: #ifdef MACH ! 932: #if !defined(OSF) ! 933: bp->b_flags |= B_NPAGES; /* can support scat/gather */ ! 934: #endif /* defined(OSF) */ ! 935: #endif MACH ! 936: if(bp->b_bcount > ((AHB_NSEG-1) * PAGESIZ)) ! 937: { ! 938: bp->b_bcount = ((AHB_NSEG-1) * PAGESIZ); ! 939: } ! 940: } ! 941: ! 942: /***********************************************\ ! 943: * start a scsi operation given the command and * ! 944: * the data address. Also needs the unit, target * ! 945: * and lu * ! 946: \***********************************************/ ! 947: int ahb_scsi_cmd(xs) ! 948: struct scsi_xfer *xs; ! 949: { ! 950: struct scsi_sense_data *s1,*s2; ! 951: struct ecb *ecb; ! 952: struct ahb_dma_seg *sg; ! 953: int seg; /* scatter gather seg being worked on */ ! 954: int i = 0; ! 955: int rc = 0; ! 956: int thiskv; ! 957: physaddr thisphys,nextphys; ! 958: int unit =xs->adapter; ! 959: int bytes_this_seg,bytes_this_page,datalen,flags; ! 960: struct iovec *iovp; ! 961: int s; ! 962: if(scsi_debug & PRINTROUTINES) ! 963: printf("ahb_scsi_cmd "); ! 964: /***********************************************\ ! 965: * get a ecb (mbox-out) to use. If the transfer * ! 966: * is from a buf (possibly from interrupt time) * ! 967: * then we can't allow it to sleep * ! 968: \***********************************************/ ! 969: flags = xs->flags; ! 970: if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */ ! 971: if(flags & ITSDONE) ! 972: { ! 973: printf("Already done?"); ! 974: xs->flags &= ~ITSDONE; ! 975: } ! 976: if(!(flags & INUSE)) ! 977: { ! 978: printf("Not in use?"); ! 979: xs->flags |= INUSE; ! 980: } ! 981: if (!(ecb = ahb_get_ecb(unit,flags))) ! 982: { ! 983: xs->error = XS_DRIVER_STUFFUP; ! 984: return(TRY_AGAIN_LATER); ! 985: } ! 986: ! 987: cheat = ecb; ! 988: if(ahb_debug & AHB_SHOWECBS) ! 989: printf("<start ecb(%x)>",ecb); ! 990: if(scsi_debug & SHOWCOMMANDS) ! 991: { ! 992: ahb_show_scsi_cmd(xs); ! 993: } ! 994: ecb->xs = xs; ! 995: /***********************************************\ ! 996: * If it's a reset, we need to do an 'immediate' * ! 997: * command, and store it's ccb for later * ! 998: * if there is already an immediate waiting, * ! 999: * then WE must wait * ! 1000: \***********************************************/ ! 1001: if(flags & SCSI_RESET) ! 1002: { ! 1003: ecb->flags |= ECB_IMMED; ! 1004: if(ahb_data[unit].immed_ecb) ! 1005: { ! 1006: return(TRY_AGAIN_LATER); ! 1007: } ! 1008: ahb_data[unit].immed_ecb = ecb; ! 1009: if (!(flags & SCSI_NOMASK)) ! 1010: { ! 1011: s = splbio(); ! 1012: ahb_send_immed(unit,xs->targ,AHB_TARG_RESET); ! 1013: ahb_add_timeout(ecb,xs->timeout); ! 1014: splx(s); ! 1015: return(SUCCESSFULLY_QUEUED); ! 1016: } ! 1017: else ! 1018: { ! 1019: ahb_send_immed(unit,xs->targ,AHB_TARG_RESET); ! 1020: /***********************************************\ ! 1021: * If we can't use interrupts, poll on completion* ! 1022: \***********************************************/ ! 1023: if(scsi_debug & TRACEINTERRUPTS) ! 1024: printf("wait "); ! 1025: if( ahb_poll(unit,xs->timeout)) ! 1026: { ! 1027: ahb_free_ecb(unit,ecb,flags); ! 1028: xs->error = XS_TIMEOUT; ! 1029: return(HAD_ERROR); ! 1030: } ! 1031: return(COMPLETE); ! 1032: } ! 1033: } ! 1034: /***********************************************\ ! 1035: * Put all the arguments for the xfer in the ecb * ! 1036: \***********************************************/ ! 1037: ecb->opcode = ECB_SCSI_OP; ! 1038: ecb->opt1 = ECB_SES|ECB_DSB|ECB_ARS; ! 1039: if(xs->datalen) ! 1040: { ! 1041: ecb->opt1 |= ECB_S_G; ! 1042: } ! 1043: ecb->opt2 = xs->lu | ECB_NRB; ! 1044: ecb->cdblen = xs->cmdlen; ! 1045: ecb->sense = KVTOPHYS(&(ecb->ecb_sense)); ! 1046: ecb->senselen = sizeof(ecb->ecb_sense); ! 1047: ecb->status = KVTOPHYS(&(ecb->ecb_status)); ! 1048: ! 1049: if(xs->datalen) ! 1050: { /* should use S/G only if not zero length */ ! 1051: ecb->data = KVTOPHYS(ecb->ahb_dma); ! 1052: sg = ecb->ahb_dma ; ! 1053: seg = 0; ! 1054: if(flags & SCSI_DATA_UIO) ! 1055: { ! 1056: iovp = ((struct uio *)xs->data)->uio_iov; ! 1057: datalen = ((struct uio *)xs->data)->uio_iovcnt; ! 1058: xs->datalen = 0; ! 1059: while ((datalen) && (seg < AHB_NSEG)) ! 1060: { ! 1061: sg->addr = (physaddr)iovp->iov_base; ! 1062: xs->datalen += sg->len = iovp->iov_len; ! 1063: if(scsi_debug & SHOWSCATGATH) ! 1064: printf("(0x%x@0x%x)" ! 1065: ,iovp->iov_len ! 1066: ,iovp->iov_base); ! 1067: sg++; ! 1068: iovp++; ! 1069: seg++; ! 1070: datalen--; ! 1071: } ! 1072: } ! 1073: else ! 1074: { ! 1075: /***********************************************\ ! 1076: * Set up the scatter gather block * ! 1077: \***********************************************/ ! 1078: ! 1079: if(scsi_debug & SHOWSCATGATH) ! 1080: printf("%d @0x%x:- ",xs->datalen,xs->data); ! 1081: datalen = xs->datalen; ! 1082: thiskv = (int)xs->data; ! 1083: thisphys = KVTOPHYS(thiskv); ! 1084: ! 1085: while ((datalen) && (seg < AHB_NSEG)) ! 1086: { ! 1087: bytes_this_seg = 0; ! 1088: ! 1089: /* put in the base address */ ! 1090: sg->addr = thisphys; ! 1091: ! 1092: if(scsi_debug & SHOWSCATGATH) ! 1093: printf("0x%x",thisphys); ! 1094: ! 1095: /* do it at least once */ ! 1096: nextphys = thisphys; ! 1097: while ((datalen) && (thisphys == nextphys)) ! 1098: /*********************************************\ ! 1099: * This page is contiguous (physically) with * ! 1100: * the the last, just extend the length * ! 1101: \*********************************************/ ! 1102: { ! 1103: /* how far to the end of the page */ ! 1104: nextphys= (thisphys & (~(PAGESIZ - 1))) ! 1105: + PAGESIZ; ! 1106: bytes_this_page = nextphys - thisphys; ! 1107: /**** or the data ****/ ! 1108: bytes_this_page = min(bytes_this_page ! 1109: ,datalen); ! 1110: bytes_this_seg += bytes_this_page; ! 1111: datalen -= bytes_this_page; ! 1112: ! 1113: /* get more ready for the next page */ ! 1114: thiskv = (thiskv & (~(PAGESIZ - 1))) ! 1115: + PAGESIZ; ! 1116: if(datalen) ! 1117: thisphys = KVTOPHYS(thiskv); ! 1118: } ! 1119: /********************************************\ ! 1120: * next page isn't contiguous, finish the seg * ! 1121: \********************************************/ ! 1122: if(scsi_debug & SHOWSCATGATH) ! 1123: printf("(0x%x)",bytes_this_seg); ! 1124: sg->len = bytes_this_seg; ! 1125: sg++; ! 1126: seg++; ! 1127: } ! 1128: } /*end of iov/kv decision */ ! 1129: ecb->datalen = seg * sizeof(struct ahb_dma_seg); ! 1130: if(scsi_debug & SHOWSCATGATH) ! 1131: printf("\n"); ! 1132: if (datalen) ! 1133: { /* there's still data, must have run out of segs! */ ! 1134: printf("ahb_scsi_cmd%d: more than %d DMA segs\n", ! 1135: unit,AHB_NSEG); ! 1136: xs->error = XS_DRIVER_STUFFUP; ! 1137: ahb_free_ecb(unit,ecb,flags); ! 1138: return(HAD_ERROR); ! 1139: } ! 1140: ! 1141: } ! 1142: else ! 1143: { /* No data xfer, use non S/G values */ ! 1144: ecb->data = (physaddr)0; ! 1145: ecb->datalen = 0; ! 1146: } ! 1147: ecb->chain = (physaddr)0; ! 1148: /***********************************************\ ! 1149: * Put the scsi command in the ecb and start it * ! 1150: \***********************************************/ ! 1151: bcopy(xs->cmd, ecb->cdb, xs->cmdlen); ! 1152: /***********************************************\ ! 1153: * Usually return SUCCESSFULLY QUEUED * ! 1154: \***********************************************/ ! 1155: if (!(flags & SCSI_NOMASK)) ! 1156: { ! 1157: s = splbio(); ! 1158: ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb); ! 1159: ahb_add_timeout(ecb,xs->timeout); ! 1160: splx(s); ! 1161: if(scsi_debug & TRACEINTERRUPTS) ! 1162: printf("cmd_sent "); ! 1163: return(SUCCESSFULLY_QUEUED); ! 1164: } ! 1165: /***********************************************\ ! 1166: * If we can't use interrupts, poll on completion* ! 1167: \***********************************************/ ! 1168: ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb); ! 1169: if(scsi_debug & TRACEINTERRUPTS) ! 1170: printf("cmd_wait "); ! 1171: do ! 1172: { ! 1173: if(ahb_poll(unit,xs->timeout)) ! 1174: { ! 1175: if (!(xs->flags & SCSI_SILENT)) printf("cmd fail\n"); ! 1176: ahb_send_mbox(unit,OP_ABORT_ECB,xs->targ,ecb); ! 1177: if(ahb_poll(unit,2000)) ! 1178: { ! 1179: printf("abort failed in wait\n"); ! 1180: ahb_free_ecb(unit,ecb,flags); ! 1181: } ! 1182: xs->error = XS_DRIVER_STUFFUP; ! 1183: splx(s); ! 1184: return(HAD_ERROR); ! 1185: } ! 1186: } while (!(xs->flags & ITSDONE));/* something (?) else finished */ ! 1187: splx(s); ! 1188: scsi_debug = 0;ahb_debug = 0; ! 1189: if(xs->error) ! 1190: { ! 1191: return(HAD_ERROR); ! 1192: } ! 1193: return(COMPLETE); ! 1194: } ! 1195: ! 1196: /* ! 1197: * +----------+ +----------+ +----------+ ! 1198: * ahb_soonest--->| later |--->| later|--->| later|--->0 ! 1199: * | [Delta] | | [Delta] | | [Delta] | ! 1200: * 0<---|sooner |<---|sooner |<---|sooner |<---ahb_latest ! 1201: * +----------+ +----------+ +----------+ ! 1202: * ! 1203: * ahb_furtherest = sum(Delta[1..n]) ! 1204: */ ! 1205: ahb_add_timeout(ecb,time) ! 1206: struct ecb *ecb; ! 1207: int time; ! 1208: { ! 1209: int timeprev; ! 1210: struct ecb *prev; ! 1211: int s = splbio(); ! 1212: ! 1213: if(prev = ahb_latest) /* yes, an assign */ ! 1214: { ! 1215: timeprev = ahb_furtherest; ! 1216: } ! 1217: else ! 1218: { ! 1219: timeprev = 0; ! 1220: } ! 1221: while(prev && (timeprev > time)) ! 1222: { ! 1223: timeprev -= prev->delta; ! 1224: prev = prev->sooner; ! 1225: } ! 1226: if(prev) ! 1227: { ! 1228: ecb->delta = time - timeprev; ! 1229: if( ecb->later = prev->later) /* yes an assign */ ! 1230: { ! 1231: ecb->later->sooner = ecb; ! 1232: ecb->later->delta -= ecb->delta; ! 1233: } ! 1234: else ! 1235: { ! 1236: ahb_furtherest = time; ! 1237: ahb_latest = ecb; ! 1238: } ! 1239: ecb->sooner = prev; ! 1240: prev->later = ecb; ! 1241: } ! 1242: else ! 1243: { ! 1244: if( ecb->later = ahb_soonest) /* yes, an assign*/ ! 1245: { ! 1246: ecb->later->sooner = ecb; ! 1247: ecb->later->delta -= time; ! 1248: } ! 1249: else ! 1250: { ! 1251: ahb_furtherest = time; ! 1252: ahb_latest = ecb; ! 1253: } ! 1254: ecb->delta = time; ! 1255: ecb->sooner = (struct ecb *)0; ! 1256: ahb_soonest = ecb; ! 1257: } ! 1258: splx(s); ! 1259: } ! 1260: ! 1261: ahb_remove_timeout(ecb) ! 1262: struct ecb *ecb; ! 1263: { ! 1264: int s = splbio(); ! 1265: ! 1266: if(ecb->sooner) ! 1267: { ! 1268: ecb->sooner->later = ecb->later; ! 1269: } ! 1270: else ! 1271: { ! 1272: ahb_soonest = ecb->later; ! 1273: } ! 1274: if(ecb->later) ! 1275: { ! 1276: ecb->later->sooner = ecb->sooner; ! 1277: ecb->later->delta += ecb->delta; ! 1278: } ! 1279: else ! 1280: { ! 1281: ahb_latest = ecb->sooner; ! 1282: ahb_furtherest -= ecb->delta; ! 1283: } ! 1284: ecb->sooner = ecb->later = (struct ecb *)0; ! 1285: splx(s); ! 1286: } ! 1287: ! 1288: ! 1289: extern int hz; ! 1290: #define ONETICK 500 /* milliseconds */ ! 1291: #define SLEEPTIME ((hz * 1000) / ONETICK) ! 1292: ahb_timeout(arg) ! 1293: int arg; ! 1294: { ! 1295: struct ecb *ecb; ! 1296: int unit; ! 1297: int s = splbio(); ! 1298: ! 1299: while( ecb = ahb_soonest ) ! 1300: { ! 1301: if(ecb->delta <= ONETICK) ! 1302: /***********************************************\ ! 1303: * It has timed out, we need to do some work * ! 1304: \***********************************************/ ! 1305: { ! 1306: unit = ecb->xs->adapter; ! 1307: printf("ahb%d:%d device timed out\n",unit ! 1308: ,ecb->xs->targ); ! 1309: if(ahb_debug & AHB_SHOWECBS) ! 1310: ahb_print_active_ecb(); ! 1311: ! 1312: /***************************************\ ! 1313: * Unlink it from the queue * ! 1314: \***************************************/ ! 1315: ahb_remove_timeout(ecb); ! 1316: ! 1317: /***************************************\ ! 1318: * If it's immediate, don't try abort it * ! 1319: \***************************************/ ! 1320: if(ecb->flags & ECB_IMMED) ! 1321: { ! 1322: ecb->xs->retries = 0; /* I MEAN IT ! */ ! 1323: ecb->flags |= ECB_IMMED_FAIL; ! 1324: ahb_done(unit,ecb,FAIL); ! 1325: continue; ! 1326: } ! 1327: /***************************************\ ! 1328: * If it has been through before, then * ! 1329: * a previous abort has failed, don't * ! 1330: * try abort again * ! 1331: \***************************************/ ! 1332: if(ecb->flags == ECB_ABORTED) /* abort timed out */ ! 1333: { ! 1334: printf("AGAIN"); ! 1335: ecb->xs->retries = 0; /* I MEAN IT ! */ ! 1336: ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST; ! 1337: ahb_done(unit,ecb,FAIL); ! 1338: } ! 1339: else /* abort the operation that has timed out */ ! 1340: { ! 1341: printf("\n"); ! 1342: ahb_send_mbox(unit,OP_ABORT_ECB,ecb->xs->targ,ecb); ! 1343: /* 2 secs for the abort */ ! 1344: ahb_add_timeout(ecb,2000 + ONETICK); ! 1345: ecb->flags = ECB_ABORTED; ! 1346: } ! 1347: } ! 1348: else ! 1349: /***********************************************\ ! 1350: * It has not timed out, adjust and leave * ! 1351: \***********************************************/ ! 1352: { ! 1353: ecb->delta -= ONETICK; ! 1354: ahb_furtherest -= ONETICK; ! 1355: break; ! 1356: } ! 1357: } ! 1358: splx(s); ! 1359: timeout(ahb_timeout,arg,SLEEPTIME); ! 1360: } ! 1361: ! 1362: ahb_show_scsi_cmd(struct scsi_xfer *xs) ! 1363: { ! 1364: u_char *b = (u_char *)xs->cmd; ! 1365: int i = 0; ! 1366: if(!(xs->flags & SCSI_RESET)) ! 1367: { ! 1368: printf("ahb%d:%d:%d-" ! 1369: ,xs->adapter ! 1370: ,xs->targ ! 1371: ,xs->lu); ! 1372: while(i < xs->cmdlen ) ! 1373: { ! 1374: if(i) printf(","); ! 1375: printf("%x",b[i++]); ! 1376: } ! 1377: printf("-\n"); ! 1378: } ! 1379: else ! 1380: { ! 1381: printf("ahb%d:%d:%d-RESET-\n" ! 1382: ,xs->adapter ! 1383: ,xs->targ ! 1384: ,xs->lu ! 1385: ); ! 1386: } ! 1387: } ! 1388: ahb_print_ecb(ecb) ! 1389: struct ecb *ecb; ! 1390: { ! 1391: printf("ecb:%x op:%x cmdlen:%d senlen:%d\n" ! 1392: ,ecb ! 1393: ,ecb->opcode ! 1394: ,ecb->cdblen ! 1395: ,ecb->senselen); ! 1396: printf(" datlen:%d hstat:%x tstat:%x delta:%d flags:%x\n" ! 1397: ,ecb->datalen ! 1398: ,ecb->ecb_status.ha_status ! 1399: ,ecb->ecb_status.targ_status ! 1400: ,ecb->delta ! 1401: ,ecb->flags); ! 1402: ahb_show_scsi_cmd(ecb->xs); ! 1403: } ! 1404: ! 1405: ahb_print_active_ecb() ! 1406: { ! 1407: struct ecb *ecb; ! 1408: ecb = ahb_soonest; ! 1409: ! 1410: while(ecb) ! 1411: { ! 1412: ahb_print_ecb(ecb); ! 1413: ecb = ecb->later; ! 1414: } ! 1415: printf("Furtherest = %d\n",ahb_furtherest); ! 1416: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.