|
|
1.1 ! root 1: /*********************************************************************** ! 2: * Module: aha154x.c ! 3: * ! 4: * Host Adapter Interface routines for the Adaptec AHA154XX series ! 5: * of host adapters. ! 6: * ! 7: * Much of the information used to create this driver was obtained ! 8: * from the AHA1540B/1542B Technical Reference Manual available from ! 9: * Adaptec by phone or snail mail at: ! 10: * ! 11: * Adaptec - Literature Department ! 12: * 691 South Milpitas Blvd. ! 13: * Milpitas, CA 95035 ! 14: * (408) 945-8600 ! 15: * ! 16: * Copyright (c), 1993 Christopher Sean Hilton, All Rights Reserved. ! 17: * ! 18: * Last Modified: Fri Jun 4 20:03:17 1993 by [chris] ! 19: */ ! 20: ! 21: #define _COH_HA_ /* Host Adaptor Module */ ! 22: ! 23: #include <stddef.h> ! 24: #include <sys/coherent.h> ! 25: #include <sys/con.h> ! 26: #include <sys/types.h> ! 27: ! 28: #include <sys/haiscsi.h> ! 29: ! 30: /*********************************************************************** ! 31: * Constants - Patch for your own circumstances. ! 32: */ ! 33: ! 34: unsigned short AHABASE = 0x330, /* Port Base */ ! 35: AHAINTR = 11, /* Host Adapter Interrupt vector */ ! 36: AHADMACHAN = 0x05; /* DMA Channel */ ! 37: ! 38: #define CTRLREG (AHABASE + 0) /* Control Register (Write) */ ! 39: #define HRST bit(7) /* Hard Reset */ ! 40: #define SRST bit(6) /* Soft Reset */ ! 41: #define IRST bit(5) /* Interrupt Reset */ ! 42: #define SCRST bit(4) /* SCSI Bus Reset */ ! 43: ! 44: #define STSREG (AHABASE + 0) /* Status Register (Read) */ ! 45: #define STST bit(7) /* Self Test in progress */ ! 46: #define DIAGF bit(6) /* Internal Diagnostic Failure */ ! 47: #define INIT bit(5) /* Mailbox Initialization Required */ ! 48: #define IDLE bit(4) /* SCSI Host Adapter Idle */ ! 49: #define CDF bit(3) /* Command/Data Out Port Full */ ! 50: #define DF bit(2) /* Data In Port Full */ ! 51: #define INVDCMD bit(0) /* Invalid HA Command */ ! 52: ! 53: #define CMDDATAOUT (AHABASE + 1) /* Command/Data Out (Write) */ ! 54: #define NOP 0x00 /* No Operation (really?) */ ! 55: #define MBINIT 0x01 /* Mail Box Initialization */ ! 56: #define STARTSCSI 0x02 /* Start a SCSI Command */ ! 57: #define STARTBIOS 0x03 /* Start a BIOS Command */ ! 58: #define HAINQUIRY 0x04 /* HA Inquiry */ ! 59: #define ENBLMBOA 0x05 /* Enable Mailbox Out Available Interrupt */ ! 60: #define STSELTO 0x06 /* Set Selection Timeout */ ! 61: #define SETBUSON 0x07 /* Set Bus on time */ ! 62: #define SETBUSOFF 0x08 /* Set Bus off time */ ! 63: #define SETXFER 0x09 /* Set transfer speed */ ! 64: #define RETINSTDEV 0x0a /* Return Installed Devices */ ! 65: #define RETCFGDATA 0x0b /* Return Configuration Data */ ! 66: #define ENBLTRGTMD 0x0c /* Enable Target Mode */ ! 67: #define RETSUDATA 0x0d /* Return Setup Data */ ! 68: ! 69: #define DATAIN (AHABASE + 1) ! 70: ! 71: #define INTRFLGS (AHABASE + 2) ! 72: #define ANYINTR bit(7) /* Any Interrupt */ ! 73: #define SCRD bit(3) /* SCSI Reset Detected */ ! 74: #define HACC bit(2) /* HA Command Complete */ ! 75: #define MBOA bit(1) /* MBO Empty */ ! 76: #define MBIF bit(0) /* MBI Full */ ! 77: ! 78: #define MBOFREE 0x00 /* Mailbox out is free */ ! 79: #define MBOSTART 0x01 /* Start CCB in this Mailbox */ ! 80: #define MBOABORT 0x02 /* Abort CCB in this Mailbox */ ! 81: ! 82: #define MBIFREE 0x00 /* Mailbox in is free */ ! 83: #define MBISUCCESS 0x01 /* Mailbox's CCB Completed Successfully */ ! 84: #define MBIABORTED 0x02 /* Mailbox's CCB Aborted */ ! 85: #define MBIABRTFLD 0x03 /* CCB to Abort not found */ ! 86: #define MBIERROR 0x04 /* CCB Completed with error */ ! 87: ! 88: #define TIMEOUT -1 /* Timeout from pollxxx() functions. */ ! 89: ! 90: #define ST_HAINIT 0x0001 /* Host Adapter being initialized */ ! 91: #define ST_HAIDLE 0x0002 /* Host Adapter is idle */ ! 92: ! 93: /*********************************************************************** ! 94: * Types ! 95: */ ! 96: ! 97: #pragma align 1 ! 98: ! 99: typedef union addr3_u { /* addr3_u for big/little endian conversions */ ! 100: unsigned long value; ! 101: unsigned char byteval[sizeof(unsigned long)]; ! 102: } addr3_t; ! 103: ! 104: typedef union mbo_u *mbo_p; /* Out Box to host adapter */ ! 105: ! 106: typedef union mbo_u { ! 107: unsigned char cmd; ! 108: paddr_t ccbaddr; ! 109: } mbo_t; ! 110: ! 111: typedef union mbi_u *mbi_p; /* In Box from host adapter */ ! 112: ! 113: typedef union mbi_u { ! 114: unsigned char sts; ! 115: paddr_t ccbaddr; ! 116: } mbi_t; ! 117: ! 118: typedef struct mb_s { /* Host adapter mailbox type */ ! 119: mbo_t o[MAXDEVS]; /* One out box for each device */ ! 120: mbi_t i[MAXDEVS]; /* One in box for each possible reply */ ! 121: } mb_t; ! 122: ! 123: typedef struct haccb_s *haccb_p; /* Host Adapter Command/Control Block */ ! 124: ! 125: typedef struct haccb_s { ! 126: unsigned char opcode; ! 127: unsigned char addrctrl; ! 128: unsigned char cdblen; ! 129: unsigned char senselen; ! 130: unsigned char datalen[3]; ! 131: unsigned char bufaddr[3]; ! 132: unsigned char linkaddr[3]; ! 133: unsigned char linkid; ! 134: unsigned char hoststs; ! 135: unsigned char trgtsts; ! 136: unsigned char pad[2]; ! 137: cdb_t cdb; ! 138: } haccb_t; ! 139: ! 140: typedef struct dsentry_s *dsentry_p; ! 141: ! 142: typedef struct dsentry_s { ! 143: unsigned char size[3]; ! 144: unsigned char addr[3]; ! 145: } dsentry_t; ! 146: ! 147: typedef struct dslist_s *dslist_p; ! 148: ! 149: typedef struct dslist_s { ! 150: dsentry_t entries[16]; ! 151: } dslist_t; ! 152: ! 153: #pragma align ! 154: ! 155: /*********************************************************************** ! 156: * Variables ! 157: */ ! 158: ! 159: static int hastate; /* Host Adapter State */ ! 160: static mb_t mb; ! 161: static haccb_t ccb[MAXDEVS]; ! 162: static paddr_t ccbbase; ! 163: static srb_p actv[MAXDEVS]; ! 164: static dslist_t ds[MAXDEVS]; ! 165: ! 166: void abortscsi(); ! 167: ! 168: /*********************************************************************** ! 169: * Support Functions ! 170: */ ! 171: ! 172: #define min(a, b) (((a) <= (b)) ? (a) : (b)) ! 173: ! 174: /*********************************************************************** ! 175: * pollclr() ! 176: * ! 177: * Wait for bit(s) to clear in a port. ! 178: */ ! 179: ! 180: static int pollclr(port, bits) ! 181: unsigned port; ! 182: unsigned bits; ! 183: ! 184: { ! 185: long countdown = 1000000L; ! 186: unsigned pval; ! 187: ! 188: while (countdown-- > 0L) { ! 189: pval = inb(port) & 0xff; ! 190: if ((pval & bits) == 0) ! 191: return (pval & ~bits); ! 192: } ! 193: printf("pollclr() port 0x%x stuck at 0x%x waiting for 0x%x\n", port, pval, bits); ! 194: return TIMEOUT; ! 195: } /* pollclr() */ ! 196: ! 197: /*********************************************************************** ! 198: * pollset() ! 199: * ! 200: * Wait for bits in port to be set. ! 201: */ ! 202: ! 203: static int pollset(port, bits) ! 204: unsigned port; ! 205: unsigned bits; ! 206: { ! 207: long countdown = 1000000L; ! 208: unsigned pval; ! 209: ! 210: while (countdown-- > 0L) { ! 211: pval = inb(port) & 0xff; ! 212: if ((pval & bits) == bits) ! 213: return pval; ! 214: } ! 215: printf("pollset() port 0x%x stuck at 0x%x waiting for 0x%x\n", port, pval, bits); ! 216: return TIMEOUT; ! 217: } /* pollset() */ ! 218: ! 219: /*********************************************************************** ! 220: * hacc() ! 221: * ! 222: * Host Adapter Command Completed - Returns 1 if last host adapter ! 223: * command completed without error. ! 224: */ ! 225: ! 226: static int hacc() ! 227: ! 228: { ! 229: unsigned stsreg; ! 230: ! 231: if (pollset(INTRFLGS, HACC) == TIMEOUT) { ! 232: printf("Timeout waiting for Host Adapter Command Complete\n"); ! 233: return 0; ! 234: } ! 235: stsreg = inb(STSREG) & (IDLE | INIT | CDF | INVDCMD); ! 236: if (stsreg != IDLE) { ! 237: printf("Host Adapter Stuck - STSREG: 0x%x\n", stsreg); ! 238: return 0; ! 239: } ! 240: return 1; ! 241: } /* hacc() */ ! 242: ! 243: /*********************************************************************** ! 244: * haidle() ! 245: * ! 246: * Returns 1 if the Idle Bit is on in the adapter status register ! 247: */ ! 248: ! 249: #define haidle() (pollset(STSREG, IDLE) != TIMEOUT) ! 250: ! 251: /*********************************************************************** ! 252: * gethabyte() ! 253: * ! 254: * Get a byte from the host adapter Data In register. ! 255: */ ! 256: ! 257: static int gethabyte() ! 258: ! 259: { ! 260: return (pollset(STSREG, DF) == TIMEOUT) ? TIMEOUT : (inb(DATAIN) & 0xff); ! 261: } /* gethabyte() */ ! 262: ! 263: /*********************************************************************** ! 264: * puthabyte() ! 265: * ! 266: * Write a byte to the host adapter Command/Data Out Register. ! 267: */ ! 268: ! 269: static int puthabyte(b) ! 270: unsigned char b; ! 271: ! 272: { ! 273: if (pollclr(STSREG, CDF) == TIMEOUT) ! 274: return 0; ! 275: else { ! 276: outb(CMDDATAOUT, b); ! 277: return 1; ! 278: } ! 279: } /* puthabyte() */ ! 280: ! 281: /*********************************************************************** ! 282: * isaha154x() ! 283: * ! 284: * Returns a string indicating the type and revision of the AHA154x ! 285: * host adapter on the bus if it is out there. Caveat: if something ! 286: * else is out there that can respond to this message I don't know ! 287: * what will happen. ! 288: */ ! 289: ! 290: static char *isaha154x(haport) ! 291: unsigned haport; ! 292: ! 293: { ! 294: /* 0123456789012345678901234 */ ! 295: static char brdid[] = "Adaptec AHA-154x# Rev: ##"; ! 296: char buf[4], *p, *idstr = NULL; ! 297: int ch, oldhaport, s; ! 298: ! 299: oldhaport = AHABASE; ! 300: s = sphi(); ! 301: AHABASE = haport; ! 302: if (haidle() && puthabyte(HAINQUIRY)) { ! 303: for (p = buf; p < buf + sizeof(buf); ++p) { ! 304: ch = gethabyte(); ! 305: if (ch == TIMEOUT) ! 306: break; ! 307: else ! 308: *p = ch; ! 309: } ! 310: if (p >= buf + sizeof(buf)) { ! 311: outb(CTRLREG, IRST); ! 312: idstr = (inb(STSREG) & IDLE != IDLE) ? NULL : brdid; ! 313: brdid[23] = buf[2]; ! 314: brdid[24] = buf[3]; ! 315: switch (buf[0]) { /* Board Type Byte */ ! 316: case 'B': /* AHA-1640 with 64 Head BIOS */ ! 317: brdid[13] = '6'; ! 318: case '\0': /* AHA-1540 with 16 head BIOS */ ! 319: case '0': /* AHA-1540 with 64 head BIOS */ ! 320: brdid[16] = ' '; ! 321: break; ! 322: case 'A': /* AHA-1540B with 64 head BIOS */ ! 323: brdid[16] = 'B'; ! 324: break; ! 325: default: ! 326: idstr = "AHA-154x Conformant Host Adapter"; ! 327: break; ! 328: } ! 329: } ! 330: } ! 331: AHABASE = oldhaport; ! 332: spl(s); ! 333: return idstr; ! 334: } /* isaha154x() */ ! 335: ! 336: /*********************************************************************** ! 337: * hareset() ! 338: * ! 339: * Reset the host adapter and leave it ready for operation. ! 340: */ ! 341: ! 342: static char *hareset() ! 343: ! 344: { ! 345: addr3_t mbaddr; ! 346: int mbinitok, stsreg, i, s; ! 347: char *p; ! 348: ! 349: if (p = isaha154x(AHABASE)) { ! 350: s = sphi(); ! 351: outb(CTRLREG, SRST); ! 352: if ((stsreg = pollclr(STSREG, STST)) == TIMEOUT) ! 353: panic("SCSI: Timeout waiting for Host Adapter Initialization\n"); ! 354: ! 355: if ((stsreg & DIAGF) || (stsreg & (INIT | IDLE)) != (INIT | IDLE)) ! 356: panic("SCSI: Host Adapter Initialization Failed.\n"); ! 357: ! 358: memset(&mb, 0, sizeof(mb)); ! 359: mbaddr. value = vtop(&mb); ! 360: mbinitok = 1; ! 361: mbinitok &= puthabyte(MBINIT); ! 362: mbinitok &= puthabyte(sizeof(mb) / (sizeof(mbo_t) + sizeof(mbi_t))); ! 363: mbinitok &= puthabyte(mbaddr. byteval[2]); ! 364: mbinitok &= puthabyte(mbaddr. byteval[1]); ! 365: mbinitok &= puthabyte(mbaddr. byteval[0]); ! 366: if (mbinitok && hacc()) ! 367: for (i = 0; i < MAXDEVS; ++i) { ! 368: actv[i] = NULL; ! 369: mb. o[i]. ccbaddr = vtop(ccb + i); ! 370: flip(mb. o[i]. ccbaddr); ! 371: mb. o[i]. cmd = MBOFREE; ! 372: } ! 373: else ! 374: panic("SCSI: AHA-154XB Mailbox Initialization Failed.\n"); ! 375: ! 376: ccbbase = vtop(ccb); ! 377: spl(s); ! 378: } ! 379: return p; ! 380: } /* hareset() */ ! 381: ! 382: /*********************************************************************** ! 383: * dmacascade() ! 384: * ! 385: * Set the selected (AHADMACHAN) dma channel to cascade mode. ! 386: */ ! 387: ! 388: static void dmacascade() ! 389: ! 390: { ! 391: int dmaporta, dmaportb, s; ! 392: ! 393: s = sphi(); ! 394: if (AHADMACHAN == 0) { ! 395: dmaporta = 0x0b; ! 396: dmaportb = 0x0a; ! 397: } else { ! 398: dmaporta = 0xd6; ! 399: dmaportb = 0xd4; ! 400: } ! 401: outb(dmaporta, 0xc0 | (AHADMACHAN & 3)); ! 402: outb(dmaportb, (AHADMACHAN & 3)); ! 403: spl(s); ! 404: } /* dmacascade() */ ! 405: ! 406: /*********************************************************************** ! 407: * checkmail() ! 408: * ! 409: * Check the incoming mailboxes for messages. Do this on any Mail ! 410: * Box In Full interrupt and before you fail a command for timeout. ! 411: * The code to determine which target device finished by tid is a ! 412: * bit tricky and relies on the following assumptions: ! 413: * ! 414: * 1) The host adapter is installed in a Intel (big-endian) ! 415: * machine. Believe it or not there is (are) non-Intel CPU ! 416: * ISA bus machines. and the one that I know of is a M68000 ! 417: * machine where this would not work. ! 418: * ! 419: * 2) The kernel's data space is physically contiguous and is ! 420: * never swapped out. ! 421: */ ! 422: ! 423: static int checkmail() ! 424: ! 425: { ! 426: static int startid = 0; ! 427: int msgs = 0; ! 428: int sts; ! 429: int s; ! 430: register int id; ! 431: register srb_p r; ! 432: register int i = startid; ! 433: ! 434: do { ! 435: if (mb. i[i]. sts != MBIFREE) { ! 436: s = sphi(); ! 437: sts = mb. i[i]. sts; ! 438: flip(mb. i[i]. ccbaddr); ! 439: id = (unsigned) ((mb. i[i]. ccbaddr & 0x00ffffffL) - ccbbase) / sizeof(haccb_t); ! 440: if (r = actv[id]) { ! 441: switch (sts) { ! 442: case MBISUCCESS: ! 443: case MBIERROR: ! 444: case MBIABRTFLD: ! 445: r->status = ccb[id]. trgtsts; ! 446: break; ! 447: case MBIABORTED: ! 448: r->status = ST_DRVABRT; ! 449: break; ! 450: default: ! 451: panic("Host Adapter Mailbox In value corrupted\n"); ! 452: } ! 453: actv[id] = NULL; ! 454: if (r->cleanup) ! 455: (*(r->cleanup))(r); ! 456: msgs |= bit(id); ! 457: } ! 458: mb. i[i]. ccbaddr = 0; ! 459: spl(s); ! 460: } ! 461: else if (msgs) ! 462: break; ! 463: i = (i + 1) & 7; ! 464: } while (i != startid); ! 465: startid = i; ! 466: ! 467: return msgs; ! 468: } /* checkmail() */ ! 469: ! 470: /*********************************************************************** ! 471: * Driver Interface Functions ! 472: */ ! 473: ! 474: /*********************************************************************** ! 475: * hatimer() ! 476: * ! 477: * Host adapter Timeout handler. ! 478: */ ! 479: ! 480: void hatimer() ! 481: ! 482: { ! 483: register int id; ! 484: register srb_p r; ! 485: register int active; ! 486: int s; ! 487: ! 488: s = sphi(); ! 489: checkmail(); /* Cleanup any missed interrupts, etc. */ ! 490: active = 0; ! 491: for (id = 0; id < MAXDEVS; ++id) { ! 492: if ((r = actv[id]) != NULL && r->timeout != 0) { ! 493: if (--r->timeout == 0) { ! 494: abortscsi(r); ! 495: r->status = ST_DRVABRT; ! 496: } ! 497: else ! 498: active = 1; ! 499: } ! 500: } ! 501: drvl[SCSIMAJOR]. d_time = active; ! 502: spl(s); ! 503: } /* hatimer() */ ! 504: ! 505: /*********************************************************************** ! 506: * haintr() ! 507: * ! 508: * SCSI interrupt handler for host adapter. ! 509: */ ! 510: ! 511: void haintr() ! 512: ! 513: { ! 514: int intrflgs; ! 515: ! 516: intrflgs = inb(INTRFLGS); ! 517: if (intrflgs & ANYINTR) ! 518: outb(CTRLREG, IRST); ! 519: ! 520: if (hastate == ST_HAINIT) ! 521: return; ! 522: if (intrflgs & MBIF) { ! 523: checkmail(); ! 524: return; ! 525: } ! 526: } /* haintr() */ ! 527: ! 528: /*********************************************************************** ! 529: * hainit() ! 530: * ! 531: * Initialize the host adapter for operation. ! 532: */ ! 533: ! 534: int hainit() ! 535: ! 536: { ! 537: char *p; ! 538: ! 539: hastate = ST_HAINIT; ! 540: printf("Host Adapter Module: AHA-154x v1.0.0 beta\n"); ! 541: setivec(AHAINTR, haintr); ! 542: p = hareset(); ! 543: if (!p) ! 544: panic("AHA154x not found or init failed at port: 0x%x\n", AHABASE); ! 545: else ! 546: printf("Initializing %s at port 0x%x, IRQ 0x%x, DMA 0x%x\n", p, AHABASE, AHAINTR, AHADMACHAN); ! 547: ! 548: dmacascade(); ! 549: hastate = ST_HAIDLE; ! 550: return 1; ! 551: } /* hainit() */ ! 552: ! 553: /*********************************************************************** ! 554: * mkdslist() ! 555: * ! 556: * Make an Adaptec Data Segment list for a Scatter/Gather Request. ! 557: * Input: d - the memory area for the Scatter/Gather List. ! 558: * b - the bufaddr structure for the memory block. ! 559: */ ! 560: ! 561: static int mkdslist(d, b) ! 562: register dsentry_p d; ! 563: bufaddr_p b; ! 564: { ! 565: paddr_t p_start; ! 566: size_t p_size; ! 567: paddr_t p_next; ! 568: int segments = 1; ! 569: register unsigned long start; ! 570: register unsigned long end; ! 571: dsentry_p l = d; ! 572: ! 573: switch (b->space) { ! 574: case KRNL_ADDR: /* Kernal Address */ ! 575: case USER_ADDR: /* User Address (Anything goes) */ ! 576: start = b->addr. vaddr; ! 577: p_start = vtop(start); ! 578: break; ! 579: case SYSGLBL_ADDR: /* System Global address (yeah) */ ! 580: start = b->addr. paddr; ! 581: p_start = P2P(start); ! 582: break; ! 583: case PHYS_ADDR: /* Physical Address - (who knows) */ ! 584: default: ! 585: return 0; ! 586: } ! 587: end = start + b->size; ! 588: p_size = min(NBPC - (p_start & (NBPC - 1)), end - start); ! 589: ! 590: for ( ; ; ) { ! 591: d->size[2] = ((unsigned char *) &p_size)[0]; ! 592: d->size[1] = ((unsigned char *) &p_size)[1]; ! 593: d->size[0] = ((unsigned char *) &p_size)[2]; ! 594: d->addr[2] = ((unsigned char *) &p_start)[0]; ! 595: d->addr[1] = ((unsigned char *) &p_start)[1]; ! 596: d->addr[0] = ((unsigned char *) &p_start)[2]; ! 597: if (start + p_size >= end) ! 598: return segments; ! 599: ! 600: p_next = (b->space == SYSGLBL_ADDR) ? P2P(start + p_size) : ! 601: vtop(start + p_size); ! 602: if (p_next == p_start + p_size) ! 603: /* Continue Last Segment */ ! 604: p_size += min(NBPC, end - start - p_size); ! 605: else { ! 606: /* Start New Segment */ ! 607: p_start = p_next; ! 608: start += p_size; ! 609: p_size = min(NBPC, end - start); ! 610: ++d; ! 611: if (++segments > (sizeof(dslist_t) / sizeof(dsentry_t))) ! 612: return 0; ! 613: } ! 614: } ! 615: } /* mkdslist() */ ! 616: ! 617: /*********************************************************************** ! 618: * startscsi() ! 619: * ! 620: * Send a SCSI CDB to a target device on the bus. ! 621: */ ! 622: ! 623: int startscsi(r) ! 624: register srb_p r; ! 625: { ! 626: register haccb_p c; ! 627: paddr_t bufaddr; ! 628: size_t datalen; ! 629: register int s; ! 630: ! 631: if (r->target >= MAXDEVS || r->lun >= MAXUNITS) { ! 632: printf("Illegal device ID: %d LUN: %d", r->target, r->lun); ! 633: return 0; ! 634: } ! 635: ! 636: ++r->tries; ! 637: if (actv[r->target]) { ! 638: devmsg(r->dev, "Device busy: opcode (0x%x)", r->cdb. g0. opcode); ! 639: return 0; ! 640: } ! 641: ! 642: s = sphi(); ! 643: r->status = ST_PENDING; ! 644: c = ccb + r->target; ! 645: memset(c, 0, sizeof(haccb_t)); ! 646: c->opcode = 0; /* Start SCSI CDB */ ! 647: c->addrctrl = (r->target << 5) | (r->lun & 7); ! 648: if (r->xferdir & DMAREAD) c->addrctrl |= 0x08; ! 649: if (r->xferdir & DMAWRITE) c->addrctrl |= 0x10; ! 650: c->cdblen = cpycdb(&(c->cdb), &(r->cdb)); ! 651: c->senselen = 1; ! 652: ! 653: /*********************************************************************** ! 654: * Set up the CCB's Address here. This turned out to be a bit more ! 655: * complicated than I thought it would be. ! 656: */ ! 657: ! 658: if (r->buf. space == PHYS_ADDR) { ! 659: c->datalen[0] = ((unsigned char *) &(r->buf. size))[2]; ! 660: c->datalen[1] = ((unsigned char *) &(r->buf. size))[1]; ! 661: c->datalen[2] = ((unsigned char *) &(r->buf. size))[0]; ! 662: c->bufaddr[0] = ((unsigned char *) &(r->buf. addr. paddr))[2]; ! 663: c->bufaddr[1] = ((unsigned char *) &(r->buf. addr. paddr))[1]; ! 664: c->bufaddr[2] = ((unsigned char *) &(r->buf. addr. paddr))[0]; ! 665: } ! 666: else { ! 667: datalen = mkdslist(ds[r->target]. entries, &(r->buf)); ! 668: if (datalen == 0) { ! 669: printf("SCSI ID %d - Bad Scatter/Gather list\n", r->target); ! 670: spl(s); ! 671: return 0; ! 672: } ! 673: else if (datalen == 1) ! 674: memcpy(c->datalen, ds[r->target]. entries, 6); ! 675: else { ! 676: c->opcode = 2; ! 677: bufaddr = vtop(ds[r->target]. entries); ! 678: datalen *= 6; ! 679: c->datalen[0] = ((unsigned char *) &datalen)[2]; ! 680: c->datalen[1] = ((unsigned char *) &datalen)[1]; ! 681: c->datalen[2] = ((unsigned char *) &datalen)[0]; ! 682: c->bufaddr[0] = ((unsigned char *) &bufaddr)[2]; ! 683: c->bufaddr[1] = ((unsigned char *) &bufaddr)[1]; ! 684: c->bufaddr[2] = ((unsigned char *) &bufaddr)[0]; ! 685: } ! 686: } ! 687: ! 688: mb. o[r->target]. cmd = MBOSTART; ! 689: if (puthabyte(STARTSCSI) && (inb(STSREG) & INVDCMD) == 0) { ! 690: actv[r->target] = r; ! 691: if (r->timeout) ! 692: drvl[SCSIMAJOR]. d_time = 1; ! 693: } ! 694: else ! 695: panic("startscsi(): AHA-154x Command Start Failure\n"); ! 696: ! 697: spl(s); ! 698: return 1; ! 699: } /* startscsi() */ ! 700: ! 701: /*********************************************************************** ! 702: * abortscsi() ! 703: * ! 704: * Abort the SCSI Command at a target device on the bus. ! 705: */ ! 706: ! 707: void abortscsi(r) ! 708: register srb_p r; ! 709: { ! 710: int s, ! 711: spin; ! 712: ! 713: printf("abortscsi(id: %d opcode: (0x%x)\n", r->target, r->cdb. g0. opcode); ! 714: s = sphi(); ! 715: r->timeout = 0; ! 716: mb. o[r->target]. cmd = MBOABORT; ! 717: if (!puthabyte(STARTSCSI) || (inb(STSREG) & INVDCMD) != 0) ! 718: panic("abortscsi(): AHA-154x Command Start Failure\n"); ! 719: ! 720: spin = 0x200001; ! 721: while (r->status == ST_PENDING && --spin > 0L) ! 722: if ((spin & 0xFFF) == 0) ! 723: checkmail(); ! 724: ! 725: if (r->status == ST_PENDING) { ! 726: if (r->xferdir == DMAREAD && ! 727: r->buf. space != KRNL_ADDR && ! 728: r->buf. size > 0) ! 729: panic("abortscsi failed at id: %d\n", r->target); ! 730: else { ! 731: actv[r->target] = NULL; ! 732: r->status = ST_DRVABRT; ! 733: if (r->cleanup) ! 734: (*r->cleanup)(r); ! 735: } ! 736: } ! 737: spl(s); ! 738: } /* abortscsi() */ ! 739: ! 740: /*********************************************************************** ! 741: * resetdevice() ! 742: * ! 743: * Reset a SCSI target. This is not used yet so it isn't coded but if ! 744: * you need to use it all you need to do is set up a CCB with opcode = ! 745: * 0x81. Then send it to the Host Adapter. It will do the rest. ! 746: */ ! 747: ! 748: int resetdevice(id) ! 749: int id; ! 750: { ! 751: panic("resetdevice() Called for ID: %d\n", id); ! 752: } /* resetdevice() */ ! 753: ! 754: /* End of file */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.