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