|
|
1.1 ! root 1: /* ! 2: * This is the host adaptor specific portion of the ! 3: * Adaptec AHA154x driver. ! 4: * ! 5: * $Log: aha.c,v $ ! 6: * Revision 1.9 93/04/16 06:57:55 bin ! 7: * Hal: kernel 76 update ! 8: * ! 9: * Revision 1.1 93/03/18 10:31:13 root ! 10: * r74 ! 11: * ! 12: * Revision 1.1 91/04/30 11:01:41 root ! 13: * Shipped with COH 3.1.0 ! 14: * ! 15: */ ! 16: #include <sys/coherent.h> ! 17: #include <sys/buf.h> ! 18: #include <sys/sched.h> ! 19: ! 20: #include <sys/scsiwork.h> ! 21: #include <sys/aha154x.h> ! 22: ! 23: #ifdef _I386 ! 24: extern char *palloc(); ! 25: #endif /* _I386 */ ! 26: ! 27: #ifndef _I386 ! 28: extern saddr_t sds; /* System Data Selector */ ! 29: static paddr_t sds_physical; /* as physical address */ ! 30: #endif /* _I386 */ ! 31: static short aha_i_o_base; ! 32: static char aha_loaded; /* did load() find a host adaptor? */ ! 33: static char dev_bit_map[8]; /* one byte per SCSI-ID; one bit per LUN */ ! 34: char drive_info[MAX_SCSI_ID * MAX_LUN]; /* "per drive" info/flags */ ! 35: ! 36: void aha_intr(); /* interrupt service routine */ ! 37: ! 38: #define MIN_MAILBOX 1 ! 39: int MAX_MAILBOX = { 8 }; /* tunable value */ ! 40: ! 41: static scsi_work_t *scsi_work_queue; ! 42: static mailentry *mailbox_in, *mailbox_out; ! 43: static char *aha_err_msg = { "no message" }; ! 44: ! 45: static long aha_timeout[] = { ! 46: #define TIMEOUT_PRESENT 0 ! 47: 0x30000L, ! 48: #define TIMEOUT_SENDCMD 1 ! 49: 0x10000L, ! 50: #define TIMEOUT_POLL 2 ! 51: 0x100L ! 52: }; ! 53: ! 54: /* ! 55: * NIGEL: The 'ccb_t' structure defined in <sys/aha154x.h> has data for the ! 56: * SCSI controller, at least at the base. Presumably the 'ccb_sw' member is ! 57: * not for the SCSI controller, so data after the 'cmd_status' member is ! 58: * for the driver. The 'buffer' member is not used.... ! 59: * ! 60: * Below I create a wrapper structure that separates driver-private data from ! 61: * the Adaptec 'ccb' like the original author should have written. This allows ! 62: * the 'ccb' to be threaded on a work list, and would obviate the need for the ! 63: * stupid machinery in "i386/mem_cache.c" (although not even that would be ! 64: * needed had page management been done right...) ! 65: * ! 66: * The primary motivation for this is to allow ccb's to be deallocated safely. ! 67: * The 286 version of the driver deallocated the structures in aha_process (), ! 68: * which was deferred from aha_intr (). The 4.0 version can not do that because ! 69: * due to the large size of the buffer cache a defer-table overflow might ! 70: * result. We compromise by creating a deferred work list and threading the ! 71: * ccb's on that and only deferring the 'start work' operation. Since ! 72: * aha_process () does no actual work but merely calls bdone () then frees the ! 73: * data, we create a 'free list' of ccb's and a deferred routine to free them, ! 74: * and leave aha_process () to call bdone () at interrupt level to give maximum ! 75: * throughput. ! 76: * ! 77: * You are now passing the Hack City limits. You are now in the Interdicted ! 78: * Zone. ! 79: */ ! 80: ! 81: #include <stddef.h> /* import offsetof () */ ! 82: ! 83: typedef struct driver_ccb drv_ccb_t; ! 84: ! 85: struct driver_ccb { ! 86: ccb_t aha_ccb; /* the driver CCB */ ! 87: drv_ccb_t * next; /* for threading on work list */ ! 88: }; ! 89: ! 90: static drv_ccb_t * free_list; /* ccb's to free */ ! 91: static int free_active; /* nonzero if cleanup routine active */ ! 92: ! 93: /* ! 94: * There are two low-level allocators in use, one for 3.2 and one for 4.0, ! 95: * and rather than #ifdef the usage we call them via a macro below. ! 96: */ ! 97: ! 98: #ifdef _I386 ! 99: #define AHA_ALLOC(size) palloc (size) ! 100: #define AHA_FREE(size) pfree (size) ! 101: #else ! 102: #define AHA_ALLOC(size) kalloc (size) ! 103: #define AHA_FREE(size) kfree (size) ! 104: #endif ! 105: ! 106: ! 107: /* ! 108: * Cleanup routine for free list, called via defer () from ccb_free (). ! 109: * ! 110: * Many fields of active ccb's are filled in with other dynamically allocated ! 111: * structures; this code has responsibility for freeing all of them. ! 112: */ ! 113: void ! 114: ccb_cleanup () ! 115: { ! 116: drv_ccb_t * work; ! 117: int s; ! 118: ! 119: s = sphi (); ! 120: while ((work = free_list) != NULL) { ! 121: free_list = work->next; ! 122: spl (s); ! 123: ! 124: #ifdef _I386 ! 125: /* ! 126: * The following code is insane; the DSL stuff should be part ! 127: * of this ccb system. This will be fixed when a total revamp ! 128: * of memory management occurs, and the "mem_cache.c" stuff ! 129: * gets spaced. ! 130: * ! 131: * In the original code, the ccb_forget () was done after the ! 132: * ccb was totally freed. I put it here to save conditionals. ! 133: */ ! 134: dsl_free (work->aha_ccb.dataptr); ! 135: ccb_forget (& work->aha_ccb); ! 136: #endif ! 137: ! 138: if (work->aha_ccb.ccb_sw != NULL) ! 139: AHA_FREE (work->aha_ccb.ccb_sw); ! 140: AHA_FREE (work); ! 141: ! 142: s = sphi (); ! 143: } ! 144: ! 145: free_active = 0; /* defer () needed to reschedule */ ! 146: spl (s); ! 147: } ! 148: ! 149: ! 150: /* ! 151: * Allocate a ccb and return a pointer to it. Call from base level only. ! 152: * The scsi_work_t * value passed here is remembered so that when the ccb ! 153: * is deallocated it will be too. In addition, code in aha_process () uses ! 154: * this stored value to map back from a ccb to a buffer-cache entry. ! 155: */ ! 156: ccb_t * ! 157: ccb_alloc (sw) ! 158: scsi_work_t * sw; ! 159: { ! 160: drv_ccb_t * drvccb; ! 161: ! 162: if ((drvccb = (drv_ccb_t *) AHA_ALLOC (sizeof (* drvccb))) == NULL) ! 163: return NULL; ! 164: ! 165: /* ! 166: * Remember the 'sw' value. Note that this really should be put in ! 167: * our wrapper structure, but that is to be fixed later. ! 168: */ ! 169: ! 170: drvccb->aha_ccb.ccb_sw = sw; ! 171: ! 172: /* ! 173: * Return a pointer to the inner adaptec ccb. ! 174: */ ! 175: ! 176: return & drvccb->aha_ccb; ! 177: } ! 178: ! 179: ! 180: /* ! 181: * Return a ccb to the free pool. Callable from base or interrupt level. All ! 182: * the dynamically allocated member data of the ccb should be freed by this ! 183: * routine. ! 184: */ ! 185: void ! 186: ccb_free (ccb) ! 187: ccb_t * ccb; ! 188: { ! 189: int s; ! 190: drv_ccb_t * work; ! 191: ! 192: /* ! 193: * Perform a portable downcast from the aha_ccb to the base structure. ! 194: */ ! 195: ! 196: work = (drv_ccb_t *) ((char *) ccb - offsetof (drv_ccb_t, aha_ccb)); ! 197: ! 198: s = sphi (); ! 199: work->next = free_list; ! 200: free_list = work; ! 201: ! 202: if (free_active == 0) { ! 203: defer (ccb_cleanup, 0); ! 204: free_active = 1; ! 205: } ! 206: spl (s); ! 207: } ! 208: ! 209: ! 210: /* ! 211: * Map from a ccb to the 'scsi_work_t' that was memoized when the ccb was ! 212: * allocated. ! 213: */ ! 214: ! 215: #define ccb_to_scsiwork(ccb) (ccb->ccb_sw) ! 216: ! 217: /* ! 218: * NIGEL: Welcome back to Hack City. Beware of mutant code! ! 219: */ ! 220: ! 221: #if 0 ! 222: static ! 223: OUTB(port, value) ! 224: short port; ! 225: { printf("<O(%x,%x)>", port, value); ! 226: outb(port, value); } ! 227: INB(port) ! 228: short port; ! 229: { register int i = inb(port); ! 230: printf("<I(%x)=%x>", port, i); ! 231: return i; } ! 232: #else ! 233: #define OUTB(port, value) outb(port, value) ! 234: #define INB(port) inb(port) ! 235: #endif ! 236: ! 237: #ifdef TRACER ! 238: #define SETMSG(msg) aha_err_msg = msg ! 239: ! 240: static char * ! 241: aha_last_msg() ! 242: { ! 243: T_PIGGY(0x8000, return aha_err_msg;); ! 244: ! 245: return "error messages not verbose"; ! 246: } ! 247: ! 248: #else /* TRACER */ ! 249: ! 250: #define SETMSG(msg) ! 251: static char * ! 252: aha_last_msg() ! 253: { ! 254: return "error messages not verbose"; ! 255: } ! 256: #endif /* TRACER */ ! 257: ! 258: static ! 259: int ! 260: no_mem() ! 261: { ! 262: printf("aha154x: out of kernel memory\n"); ! 263: } ! 264: ! 265: int ! 266: aha_set_base(base) ! 267: { ! 268: register int i; ! 269: ! 270: i = aha_i_o_base; ! 271: aha_i_o_base = base; ! 272: return i; ! 273: } ! 274: ! 275: int ! 276: aha_get_base() ! 277: { ! 278: return aha_i_o_base; ! 279: } ! 280: ! 281: aha_process(ccb) ! 282: ccb_t *ccb; ! 283: { ! 284: register scsi_work_t *sw; ! 285: register BUF *bp; ! 286: ! 287: if ((sw = ccb_to_scsiwork (ccb)) == NULL) { ! 288: ccb->opcode = AHA_OP_INVALID; ! 289: wakeup(ccb); ! 290: return; ! 291: } ! 292: ! 293: bp = sw->sw_bp; ! 294: ! 295: if((ccb->hoststatus != 0) || (ccb->targetstatus != 0)) { ! 296: if(--sw->sw_retry > 0 ! 297: || (ccb->targetstatus == CHECK_TARGET_STATUS ! 298: && ccb->cmd_status[12] == SENSE_UNIT_ATTENTION)) { ! 299: int s = sphi(); ! 300: if(scsi_work_queue->sw_actf == NULL) { ! 301: scsi_work_queue->sw_actf = sw; ! 302: } else { ! 303: scsi_work_queue->sw_actl->sw_actf = sw; ! 304: } ! 305: scsi_work_queue->sw_actl = sw; ! 306: spl(s); ! 307: aha_start(); ! 308: return; ! 309: } ! 310: bp->b_flag |= BFERR; ! 311: } else { ! 312: bp->b_resid = 0; ! 313: } ! 314: ! 315: bdone(bp); ! 316: ccb_free(ccb); ! 317: } ! 318: ! 319: static ! 320: int aha_1out(value) ! 321: { ! 322: register int i; ! 323: ! 324: while((i = INB(aha_i_o_base + AHA_STATUS) & AHA_CDOPFULL) != 0) ! 325: if((i & AHA_INVDCMD) ! 326: || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE)) ! 327: return -1; ! 328: OUTB(aha_i_o_base + AHA_WRITE, value); ! 329: return 0; ! 330: } ! 331: ! 332: static ! 333: int aha_1in() ! 334: { ! 335: register int i; ! 336: ! 337: while((i = INB(aha_i_o_base + AHA_STATUS) & AHA_DIPFULL) == 0) ! 338: if((i & AHA_INVDCMD) ! 339: || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE)) ! 340: return -1; ! 341: return INB(aha_i_o_base + AHA_READ) & 0xFF; ! 342: } ! 343: ! 344: static ! 345: void aha_cmd_out(value) ! 346: { ! 347: register long l; ! 348: register int i; ! 349: ! 350: for(l = aha_timeout[TIMEOUT_SENDCMD]; --l > 0;) { ! 351: if(((i=INB(aha_i_o_base + AHA_STATUS)) ! 352: & AHA_SCSIIDLE) != 0) { ! 353: aha_1out(value); ! 354: return; ! 355: } ! 356: } ! 357: SETMSG("timeout sending cmd byte"); ! 358: printf("aha154x: timeout sending cmd byte\n"); ! 359: } ! 360: ! 361: static ! 362: int aha_poll() ! 363: { ! 364: register int i; ! 365: register int l = aha_timeout[TIMEOUT_POLL]; ! 366: while((--l > 0) ! 367: && ((i = INB(aha_i_o_base + AHA_INTERRUPT)) & AHA_CMD_DONE) == 0) ! 368: ; ! 369: if(l == 0) ! 370: printf("aha154x: aha_poll timed out\n"); ! 371: ! 372: i = INB(aha_i_o_base + AHA_STATUS); ! 373: OUTB(aha_i_o_base + AHA_CONTROL, AHA_INTRRESET); ! 374: return i; ! 375: } ! 376: ! 377: static ! 378: void aha_get_data(vec, cnt) ! 379: char *vec; ! 380: int cnt; ! 381: { ! 382: while(--cnt >= 0) ! 383: *vec++ = aha_1in(); ! 384: aha_poll(); ! 385: } ! 386: ! 387: static ! 388: int aha_present() ! 389: { ! 390: long l; ! 391: ! 392: if(INB(aha_i_o_base) == 0xFF) { ! 393: SETMSG("no adapter found at io base"); ! 394: return -3; ! 395: } ! 396: for(l = aha_timeout[TIMEOUT_PRESENT]; ! 397: (--l > 0) && (INB(aha_i_o_base + AHA_STATUS) & AHA_SELFTEST);) ! 398: ; ! 399: if(l == 0) { ! 400: SETMSG("selftest not completed"); ! 401: return -1; ! 402: } ! 403: if(INB(aha_i_o_base + AHA_STATUS) & AHA_DIAGFAIL) { ! 404: SETMSG("diagnostics failed"); ! 405: return -2; ! 406: } ! 407: if(INB(aha_i_o_base + AHA_STATUS) & AHA_INITMAIL) { ! 408: SETMSG("mailbox initialization needed"); ! 409: return 1; ! 410: } ! 411: if(INB(aha_i_o_base + AHA_STATUS) & AHA_SCSIIDLE) { ! 412: SETMSG("adaptor okay, idle"); ! 413: return 0; ! 414: } ! 415: SETMSG("unknown status at start"); ! 416: return -4; ! 417: } ! 418: ! 419: void ! 420: aha_l_to_p3(value, vec) ! 421: paddr_t value; ! 422: P3 vec; ! 423: { ! 424: register int i; ! 425: ! 426: for(i = 3; --i >= 0;) { ! 427: vec[i] = value & 0xFF; ! 428: value >>= 8; ! 429: } ! 430: } ! 431: ! 432: long ! 433: aha_p3_to_l(vec) ! 434: P3 vec; ! 435: { ! 436: register int i; ! 437: register long retval; ! 438: ! 439: retval = 0; ! 440: for(i = 0; i < 3; ++i) { ! 441: retval <<= 8; ! 442: retval |= vec[i]; ! 443: } ! 444: ! 445: return(retval); ! 446: } /* aha_p3_to_l() */ ! 447: ! 448: #ifndef _I386 /* All of aha_p3_to_v(). */ ! 449: static char * ! 450: aha_p3_to_v(vec) ! 451: P3 vec; ! 452: { ! 453: paddr_t adr; ! 454: ! 455: adr = vec[0]; ! 456: adr <<= 16; ! 457: adr |= (vec[1]<<8) | vec[2]; ! 458: adr -= sds_physical; ! 459: return (char *)adr; ! 460: } ! 461: #endif /* _I386 */ ! 462: ! 463: aha_device_info() ! 464: { ! 465: register int i; ! 466: static char buf[256]; ! 467: ! 468: aha_cmd_out(AHA_DO_GET_DEVICES); ! 469: aha_get_data(&buf[0], 8); ! 470: for(i = 0; i < 8; ++i) ! 471: if(buf[i] != 0) ! 472: printf("[%d] %x ", i, buf[i]); ! 473: printf("\n"); ! 474: } ! 475: ! 476: int aha_unload(ireq) ! 477: { ! 478: /* ! 479: * we should really verify that everything ! 480: * out there gets flushed. ! 481: */ ! 482: if (!aha_loaded) ! 483: return; ! 484: if(mailbox_out) { ! 485: AHA_FREE (mailbox_out); ! 486: mailbox_out = 0; ! 487: } ! 488: clrivec(ireq); ! 489: } ! 490: ! 491: int aha_load(dma, ireq, base, head) ! 492: scsi_work_t *head; ! 493: { ! 494: register int i; ! 495: unsigned char adr[4]; ! 496: ! 497: aha_set_base(base); ! 498: if(mailbox_out == 0) { ! 499: if ((mailbox_out = ! 500: AHA_ALLOC (2 * MAX_MAILBOX * sizeof(mailentry))) == 0) { ! 501: no_mem(); ! 502: return -1; ! 503: } else { ! 504: mailbox_in = &mailbox_out[MAX_MAILBOX]; ! 505: } ! 506: } ! 507: ! 508: for(i = 0; i < MAX_MAILBOX; ++i) ! 509: mailbox_out[i].cmd = mailbox_in[i].cmd = 0; ! 510: ! 511: #ifdef _I386 ! 512: aha_l_to_p3(vtop(mailbox_out), &adr[1]); ! 513: #else /* _I386 */ ! 514: sds_physical = VTOP2(0, sds); ! 515: aha_l_to_p3(VTOP2(mailbox_out, sds), &adr[1]); ! 516: #endif /* _I386 */ ! 517: ! 518: adr[0] = MAX_MAILBOX; ! 519: ! 520: /* ! 521: * setup HW ! 522: */ ! 523: setivec(ireq, aha_intr); ! 524: ! 525: outb(0xD6, 0xC1); /* DMA is currently hard coded for */ ! 526: outb(0xD4, 0x01); /* DMA channel 5 */ ! 527: ! 528: ! 529: OUTB(aha_i_o_base+AHA_CONTROL, AHA_HARDRESET); ! 530: if (aha_present() < 0) { ! 531: printf("aha154x: initialization error or host adaptor not "); ! 532: printf("found at 0x%x\n", aha_i_o_base); ! 533: return -1; ! 534: } ! 535: aha_cmd_out(AHA_DO_MAILBOX_INIT); ! 536: for(i = 0; i < 4; ++i) ! 537: aha_1out(adr[i]); ! 538: scsi_work_queue = head; ! 539: ++aha_loaded; ! 540: return MAX_MAILBOX; ! 541: } ! 542: ! 543: aha_command(sc) ! 544: register scsi_cmd_t *sc; ! 545: { ! 546: register int i; ! 547: /* register */ ccb_t *ccb; ! 548: ! 549: short count = sc->blklen; ! 550: long block = sc->block; ! 551: ! 552: if ((ccb = ccb_alloc (NULL)) == NULL) { ! 553: no_mem(); ! 554: return -1; ! 555: } ! 556: ! 557: #ifdef _I386 ! 558: ccb->opcode = AHA_OP_SIC_SG; /* SCSI_INITIATOR*/ ! 559: #else /* _I386 */ ! 560: ccb->opcode = AHA_OP_SIC; /* SCSI_INITIATOR*/ ! 561: #endif /* _I386 */ ! 562: ccb->target = (sc->unit & 0x1C) << 3; /* SCSI ID */ ! 563: ccb->target |= sc->unit & 0x3; /* LUN */ ! 564: if((ccb->cmd_status[0] = sc->cmd) == ScmdWRITEXTENDED) { ! 565: ccb->target |= AHA_CCB_DATA_OUT; ! 566: } else { /* READEXT, READCAP, INQUIRY */ ! 567: ccb->target |= AHA_CCB_DATA_IN; ! 568: } ! 569: ccb->cmd_status[1] = 0; ! 570: ccb->cmd_status[2] = block; ! 571: ccb->cmd_status[3] = block >>16; ! 572: ccb->cmd_status[4] = block >> 8; ! 573: ccb->cmd_status[5] = block; ! 574: ccb->cmd_status[6] = 0; ! 575: ccb->cmd_status[7] = count / 512; ! 576: ccb->cmd_status[8] = count; ! 577: ccb->cmd_status[9] = 0; ! 578: ccb->cmdlen = 10; ! 579: ccb->senselen = MAX_SENSEDATA; ! 580: ! 581: #ifdef _I386 ! 582: dsl_gen(ccb->dataptr, ccb->datalen, sc->buffer, (long)sc->buflen); ! 583: aha_l_to_p3(vtop(ccb), mailbox_out[0].adr); ! 584: ccb_remember(ccb, mailbox_out[0].adr); ! 585: #else /* _I386 */ ! 586: aha_l_to_p3((long)sc->buflen, ccb->datalen); ! 587: aha_l_to_p3(sc->buffer, ccb->dataptr); ! 588: aha_l_to_p3(VTOP2(ccb, sds), mailbox_out[0].adr); ! 589: #endif /* _I386 */ ! 590: ! 591: mailbox_out[0].cmd = MBO_TO_START; ! 592: ! 593: /* Start the AHA-154x scanning the mailboxes. */ ! 594: aha_1out(AHA_DO_SCSI_START); ! 595: ! 596: /* Wait for this ccb to finish. */ ! 597: while(ccb->opcode != AHA_OP_INVALID) { ! 598: #ifdef _I386 ! 599: x_sleep(ccb, pridisk, slpriNoSig, "aha:ccb"); ! 600: #else ! 601: v_sleep(ccb, CVBLKIO, IVBLKIO, SVBLKIO, "aha:ccb"); ! 602: #endif ! 603: /* The AHA-154x driver is waiting for a ccb to complete. */ ! 604: } ! 605: ! 606: if((ccb->targetstatus == CHECK_TARGET_STATUS) ! 607: && (ccb->cmd_status[12] != SENSE_UNIT_ATTENTION)) { ! 608: printf("aha: SCSI ID %d LUN %d. SCSI sense =", ! 609: (sc->unit >> 2), sc->unit & 0x3); ! 610: for(i = 0; i < ccb->senselen; ++i) ! 611: printf(" %x", ccb->cmd_status[10+i]); ! 612: printf("\n"); ! 613: } ! 614: i = ccb->hoststatus | ccb->targetstatus; ! 615: ! 616: /* ! 617: * NIGEL: If you are worried that the ccb memory is not getting freed ! 618: * soon enough, add a parameter to ccb_cleanup () to flag whether it ! 619: * should clear the active flag and call it directly here. ! 620: */ ! 621: ccb_free(ccb); ! 622: ! 623: return i; ! 624: } ! 625: ! 626: ccb_t *buildccb(sw) ! 627: register scsi_work_t *sw; ! 628: { ! 629: register ccb_t *ccb; ! 630: ! 631: if ((ccb = ccb_alloc(sw)) == NULL) ! 632: return NULL; ! 633: ! 634: #ifdef _I386 ! 635: ccb->opcode = AHA_OP_SIC_SG; /* SCSI_INITIATOR*/ ! 636: #else /* _I386 */ ! 637: ccb->opcode = AHA_OP_SIC; /* SCSI_INITIATOR*/ ! 638: #endif /* _I386 */ ! 639: ! 640: ccb->target = (sw->sw_drv & 0x1C) << 3; /* SCSI ID */ ! 641: ccb->target |= (sw->sw_drv) & 0x3; /* LUN */ ! 642: if(sw->sw_bp->b_req == BREAD) { ! 643: ccb->target |= AHA_CCB_DATA_IN; ! 644: ccb->cmd_status[0] = ScmdREADEXTENDED; ! 645: } else { ! 646: ccb->target |= AHA_CCB_DATA_OUT; ! 647: ccb->cmd_status[0] = ScmdWRITEXTENDED; ! 648: } ! 649: ccb->cmd_status[2] = 0; ! 650: ccb->cmd_status[3] = sw->sw_bno >>16; ! 651: ccb->cmd_status[4] = sw->sw_bno >> 8; ! 652: ccb->cmd_status[5] = sw->sw_bno; ! 653: ccb->cmd_status[6] = 0; ! 654: ccb->cmd_status[7] = sw->sw_bp->b_count / (512*256L); ! 655: ccb->cmd_status[8] = sw->sw_bp->b_count / 512; ! 656: ccb->cmd_status[9] = 0; ! 657: ccb->cmdlen = 10; ! 658: ccb->senselen = MAX_SENSEDATA; ! 659: ! 660: #ifdef _I386 ! 661: dsl_gen(ccb->dataptr, ccb->datalen, ! 662: sw->sw_bp->b_paddr, (long)sw->sw_bp->b_count); ! 663: #else /* _I386 */ ! 664: aha_l_to_p3((long)sw->sw_bp->b_count, ccb->datalen); ! 665: aha_l_to_p3(vtop(sw->sw_bp->b_faddr), ccb->dataptr); ! 666: #endif /* _I386 */ ! 667: /* ! 668: * The ccb's returned here are going to be freed by aha_process (). ! 669: */ ! 670: return ccb; ! 671: #if 0 ! 672: /* start of ioctl code */ ! 673: if(f == SASI_CMD_IN) ! 674: ccb->target |= AHA_CCB_DATA_IN; ! 675: else if(f == SASI_CMD_OUT) ! 676: ccb->target |= AHA_CCB_DATA_OUT; ! 677: else ! 678: ccb->target |= AHA_CCB_DATA_IN ! 679: |AHA_CCB_DATA_OUT; ! 680: #endif ! 681: } ! 682: ! 683: aha_start() ! 684: { ! 685: register int i, s, n = 0; ! 686: scsi_work_t *sw; ! 687: static char locked; ! 688: ! 689: s = sphi(); ! 690: if(locked) { ! 691: spl(s); ! 692: return; ! 693: } ! 694: ++locked; ! 695: spl(s); ! 696: ! 697: while((sw = scsi_work_queue->sw_actf) != NULL) { ! 698: for(i = MIN_MAILBOX; i < MAX_MAILBOX; ++i) ! 699: if(mailbox_out[i].cmd == MBO_IS_FREE) { ! 700: register ccb_t *ccb; ! 701: int s; ! 702: ! 703: ++n; ! 704: if ((ccb = buildccb (sw)) == NULL) { ! 705: /* ! 706: * NIGEL: Earlier kernels did not ! 707: * diagnose this! ! 708: */ ! 709: goto out_of_mem; ! 710: } ! 711: #ifdef _I386 ! 712: aha_l_to_p3(vtop(ccb), ! 713: mailbox_out[i].adr); ! 714: ccb_remember(ccb, mailbox_out[i].adr); ! 715: #else /* _I386 */ ! 716: aha_l_to_p3(VTOP2(ccb, sds), ! 717: mailbox_out[i].adr); ! 718: #endif /* _I386 */ ! 719: mailbox_out[i].cmd = MBO_TO_START; ! 720: ! 721: aha_1out(AHA_DO_SCSI_START); ! 722: ! 723: s = sphi(); ! 724: sw = scsi_work_queue->sw_actf = sw->sw_actf; ! 725: if(sw == NULL) ! 726: scsi_work_queue->sw_actl = NULL; ! 727: spl(s); ! 728: ! 729: if(sw == NULL) ! 730: break; ! 731: } ! 732: if(i == MAX_MAILBOX) ! 733: break; ! 734: } ! 735: out_of_mem: ! 736: --locked; ! 737: return n; ! 738: } ! 739: ! 740: int ! 741: aha_completed() ! 742: { ! 743: register int i, n; ! 744: ! 745: for(n = 0, i = 0; i < MAX_MAILBOX; ++i) ! 746: if(mailbox_in[i].cmd != MBI_IS_FREE) { ! 747: /* ! 748: * NIGEL: Earlier kernels deferred these, but with the ! 749: * ccb_free ()/ccb_alloc () system that is no longer ! 750: * necessary in either 4.x or 3.x systems. ! 751: */ ! 752: #ifdef _I386 ! 753: aha_process(ccb_recall(mailbox_in[i].adr)); ! 754: #else /* _I386 */ ! 755: aha_process(aha_p3_to_v(mailbox_in[i].adr)); ! 756: #endif /* _I386 */ ! 757: mailbox_in[i].cmd = MBI_IS_FREE; ! 758: ++n; ! 759: } ! 760: return n; ! 761: } ! 762: ! 763: void ! 764: aha_intr() ! 765: { ! 766: register int i; ! 767: ! 768: if(((i = INB(aha_i_o_base+AHA_INTERRUPT)) & AHA_ANY_INTER) == 0) ! 769: printf("aha: spurious interrupt %x\n", i); ! 770: ! 771: switch(i & AHA_ALL_INTERRUPTS) { ! 772: case AHA_RESETED: ! 773: break; ! 774: case AHA_CMD_DONE: ! 775: break; ! 776: case AHA_MBO_EMPTY: ! 777: defer(aha_start, (char *)0); ! 778: break; ! 779: case AHA_MBI_STORED: ! 780: aha_completed(); ! 781: break; ! 782: default: ! 783: printf("aha: multiple interrupts not yet handled\n"); ! 784: } ! 785: outb(aha_i_o_base+AHA_CONTROL, AHA_INTRRESET); ! 786: } ! 787: ! 788: aha_ioctl() ! 789: { ! 790: printf("aha_ioctl: Not implemented\n"); ! 791: } ! 792: ! 793: #ifdef TRACER ! 794: static unsigned char vec[256]; ! 795: ! 796: static aha_ports_are() { ! 797: printf("aha_ports_are: %x %x %x\n", ! 798: INB(aha_i_o_base+0), ! 799: INB(aha_i_o_base+1), ! 800: INB(aha_i_o_base+2)); ! 801: } ! 802: ! 803: static aha_inquiry_is() { ! 804: printf("aha_inquiry:"); ! 805: printf("... aha_present = %d, ", aha_present()); ! 806: printf("%s\n", aha_last_msg()); ! 807: aha_cmd_out(AHA_DO_INQUIRY); ! 808: ! 809: aha_get_data(&vec[0], 4); ! 810: printf(" board id '%c'", vec[0]); ! 811: printf(", options '%c'", vec[1]); ! 812: printf(", HW '%c'", vec[2]); ! 813: printf(", FW '%c'\n", vec[3]); ! 814: } ! 815: ! 816: void aha_setup_is() { ! 817: register int i; ! 818: ! 819: printf("Setup and Data:\n"); ! 820: aha_cmd_out(AHA_DO_GET_SETUP); ! 821: aha_cmd_out(16); ! 822: aha_get_data(&vec[0], 16); ! 823: printf(" Data Xfer %s Sync (J1)\n", (vec[0]&1) ? "is" : "not"); ! 824: printf(" Parity %s Enabled (J1)\n", (vec[0]&2) ? "is" : "not"); ! 825: switch(vec[1]) { ! 826: case AHA_SPEED_5_0_MB: ! 827: printf(" 5.0 Mb/sec.\n"); break; ! 828: case AHA_SPEED_6_7_MB: ! 829: printf(" 6.7 Mb/sec.\n"); break; ! 830: case AHA_SPEED_8_0_MB: ! 831: printf(" 8.0 Mb/sec.\n"); break; ! 832: case AHA_SPEED_10_MB: ! 833: printf(" 10 Mb/sec.\n"); break; ! 834: case AHA_SPEED_5_7_MB: ! 835: printf(" 5.7 Mb/sec.\n"); break; ! 836: default: ! 837: if(vec[1] & 0x80) ! 838: printf(" Pulse Read %d, Write %d, Strobe off %d\n", ! 839: 50*(2+(vec[1]>>4)&0x7), 50*(2+(vec[1]&7)), ! 840: vec[1] & 0x80 ? 150 : 100); ! 841: } ! 842: printf(" Bus Time ON %d, OFF %d\n", vec[2], vec[3]); ! 843: printf(" %d Mailboxes at %x|%x|%x\n", vec[4], ! 844: vec[5], vec[6], vec[7]); ! 845: for(i = 0; i < 8; ++i) ! 846: if(vec[i+8]) ! 847: printf(" Target [%d] = Sync Neg %x\n", i, vec[i+8]); ! 848: } ! 849: ! 850: static aha_mailboxes_are(n, adr) ! 851: mailentry *adr; ! 852: { ! 853: register int i; ! 854: ! 855: printf("addresses for mailbox is %x:%x\n", (long)adr); ! 856: for(i = 0; i < n; ++i, ++adr) ! 857: printf(" mbo[%x] = %x %x|%x|%x\n", ! 858: i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2]); ! 859: for(i = 0; i < n; ++i, ++adr) ! 860: printf(" mbi[%x] = %x %x|%x|%x\n", ! 861: i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2]); ! 862: } ! 863: ! 864: void aha_status() ! 865: { ! 866: aha_ports_are(); ! 867: aha_inquiry_is(); ! 868: /* aha_devices_are(); */ /* This appears to have never existed. */ ! 869: aha_setup_is(); ! 870: aha_mailboxes_are(MAX_MAILBOX, mailbox_out); ! 871: } ! 872: ! 873: aha_ccb_print(ccb) ! 874: ccb_t *ccb; ! 875: { ! 876: register int i; ! 877: register unsigned char *cp; ! 878: ! 879: printf("aha_ccb_print(ccb: %x)", ccb); ! 880: if (0 != ccb) { ! 881: printf(", sw: %x", ccb->ccb_sw); ! 882: if (0 != ccb->ccb_sw) { ! 883: printf(", bp: %x", ccb->ccb_sw->sw_bp); ! 884: if (0 != ccb->ccb_sw->sw_bp) { ! 885: printf(", flag: %x", ! 886: ccb->ccb_sw->sw_bp->b_flag); ! 887: } ! 888: } ! 889: printf(", op %d, ", ccb->opcode); ! 890: printf("target ID=%d, ", (ccb->target>>5) & 0x7); ! 891: printf("LUN=%d, ", (ccb->target & 0x7)); ! 892: printf("dir=%s%s\n", (ccb->target&AHA_CCB_DATA_IN)?"IN":"", ! 893: (ccb->target&AHA_CCB_DATA_OUT)?"OUT":""); ! 894: printf("data len %x|%x|%x, adr %x|%x|%x\n", ! 895: ccb->datalen[0],ccb->datalen[1],ccb->datalen[2], ! 896: ccb->dataptr[0],ccb->dataptr[1],ccb->dataptr[2]); ! 897: printf("status host=%x, target=%x\n", ! 898: ccb->hoststatus, ccb->targetstatus); ! 899: printf("cmddata[%d]:", ccb->cmdlen); ! 900: for(i = 0, cp = ccb->cmd_status; i < ccb->cmdlen; ++i) ! 901: printf(" %x", *cp++); ! 902: printf("\nrequest sense[%d]:", ccb->senselen); ! 903: for(i = 0; i < ccb->senselen; ++i) ! 904: printf(" %x", *cp++); ! 905: if(i = cp[-1]) { ! 906: printf("\n + "); ! 907: while(--i >= 0) ! 908: printf(" %x", *cp++); ! 909: } ! 910: printf("\n"); ! 911: } ! 912: } ! 913: ! 914: #endif /* TRACER */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.