|
|
1.1.1.3 ! root 1: /* $Id: aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $ 1.1 root 2: * linux/kernel/aha1542.c 3: * 1.1.1.3 ! root 4: * Copyright (C) 1992 Tommy Thorn 1.1 root 5: */ 6: 7: #include <linux/config.h> 8: #include <linux/kernel.h> 9: #include <linux/head.h> 1.1.1.3 ! root 10: #include <linux/types.h> 1.1 root 11: #include <linux/string.h> 1.1.1.3 ! root 12: 1.1 root 13: #include <asm/system.h> 14: #include <asm/io.h> 15: #include "scsi.h" 16: #include "hosts.h" 17: 18: #include "aha1542.h" 19: #ifdef DEBUG 20: #define DEB(x) x 21: #else 22: #define DEB(x) 23: #endif 24: 25: /* 1.1.1.3 ! root 26: static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $"; 1.1 root 27: */ 28: 29: #define base 0x330 30: #define intr_chan 11 31: 32: static struct mailbox mb[2]; 33: static struct ccb ccb; 34: 35: long WAITtimeout, WAITnexttimeout = 3000000; 36: 1.1.1.3 ! root 37: void (*do_done)(int, int) = NULL; ! 38: int aha1542_host = 0; 1.1 root 39: extern void aha1542_interrupt(); 40: 41: #define aha1542_intr_reset() outb(IRST, CONTROL) 42: #define aha1542_enable_intr() outb(inb_p(0xA1) & ~8, 0xA1) 43: #define aha1542_disable_intr() outb(inb_p(0xA1) | 8, 0xA1) 44: 45: #define WAIT(port, mask, allof, noneof) \ 46: { register WAITbits; \ 47: register WAITtimeout = WAITnexttimeout; \ 48: while (1) { \ 49: WAITbits = inb(port) & (mask); \ 50: if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ 51: break; \ 52: if (--WAITtimeout == 0) goto fail; \ 53: } \ 54: } 55: 56: static void aha1542_stat(void) 57: { 1.1.1.3 ! root 58: /* int s = inb(STATUS), i = inb(INTRFLAGS); ! 59: printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout); */ 1.1 root 60: } 61: 62: static int aha1542_out(unchar *cmdp, int len) 63: { 64: while (len--) 65: { 66: WAIT(STATUS, CDF, 0, CDF); 67: outb(*cmdp++, DATA); 68: } 69: return 0; 70: fail: 71: printk("aha1542_out failed(%d): ", len+1); aha1542_stat(); 72: return 1; 73: } 74: 75: int makecode(unsigned hosterr, unsigned scsierr) 76: { 77: switch (hosterr) { 78: case 0x0: 79: case 0xa: /* Linked command complete without error and linked normally */ 80: case 0xb: /* Linked command complete without error, interrupt generated */ 81: hosterr = 0; 82: break; 83: 84: case 0x11: /* Selection time out-The initiator selection or target 85: reselection was not complete within the SCSI Time out period */ 86: hosterr = DID_TIME_OUT; 87: break; 88: 89: case 0x12: /* Data overrun/underrun-The target attempted to transfer more data 90: thean was allocated by the Data Length field or the sum of the 91: Scatter / Gather Data Length fields. */ 92: 93: case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */ 94: 95: case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was 96: invalid. This usually indicates a software failure. */ 97: 98: case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid. 99: This usually indicates a software failure. */ 100: 101: case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set 102: of linked CCB's does not specify the same logical unit number as 103: the first. */ 104: case 0x18: /* Invalid Target Direction received from Host-The direction of a 105: Target Mode CCB was invalid. */ 106: 107: case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was 108: received to service data transfer between the same target LUN 109: and initiator SCSI ID in the same direction. */ 110: 111: case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero 112: length segment or invalid segment list boundaries was received. 113: A CCB parameter was invalid. */ 114: hosterr = DID_ERROR; /* Couldn't find any better */ 115: break; 116: 117: case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus 118: phase sequence was requested by the target. The host adapter 119: will generate a SCSI Reset Condition, notifying the host with 120: a SCRD interrupt */ 121: hosterr = DID_RESET; 122: break; 123: default: 124: printk("makecode: unknown hoststatus %x\n", hosterr); 125: break; 126: } 127: return scsierr|(hosterr << 16); 128: } 129: 130: int aha1542_test_port(void) 131: { 132: volatile int debug = 0; 133: 134: /* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */ 135: 136: /* DEB(printk("aha1542_test_port called \n")); */ 137: 138: outb(SRST|IRST/*|SCRST*/, CONTROL); 139: 140: debug = 1; 141: /* Expect INIT and IDLE, any of the others are bad */ 142: WAIT(STATUS, STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF); 143: 144: debug = 2; 145: /* Shouldn't have generated any interrupts during reset */ 146: if (inb(INTRFLAGS)&INTRMASK) goto fail; 147: 148: debug = 3; 149: /* Test the basic ECHO command */ 150: outb(CMD_ECHO, DATA); 151: 152: debug = 4; 153: /* Wait for CDF=0. If any of the others are set, it's bad */ 154: WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF); 155: 156: debug = 5; 157: /* The meaning of life */ 158: outb(42, DATA); 159: 160: debug = 6; 161: /* Expect only DF, that is, data ready */ 162: WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD); 163: 164: debug = 7; 165: /* Is the answer correct? */ 166: if (inb(DATA) != 42) goto fail; 167: 168: debug = 8; 169: /* Reading port should reset DF */ 170: if (inb(STATUS) & DF) goto fail; 171: 172: debug = 9; 173: /* When HACC, command is completed, and we're though testing */ 174: WAIT(INTRFLAGS, HACC, HACC, 0); 175: /* now initialize adapter */ 176: 177: debug = 10; 178: /* Clear interrupts */ 179: outb(IRST, CONTROL); 180: 181: debug = 11; 182: 183: return debug; /* 1 = ok */ 184: fail: 185: return 0; /* 0 = not ok */ 186: } 187: 188: /* What's this little function for? */ 189: char *aha1542_info(void) 190: { 191: static char buffer[] = "Adaptec 1542"; 192: return buffer; 193: } 194: 195: /* A "high" level interrupt handler */ 196: void aha1542_intr_handle(void) 197: { 1.1.1.3 ! root 198: void (*my_done)(int, int) = do_done; 1.1 root 199: int errstatus; 200: 201: do_done = NULL; 202: #ifdef DEBUG 203: printk("aha1542_intr_handle: "); 204: if (!(flag&ANYINTR)) printk("no interrupt?"); 205: if (flag&MBIF) printk("MBIF "); 206: if (flag&MBOA) printk("MBOF "); 207: if (flag&HACC) printk("HACC "); 208: if (flag&SCRD) printk("SCRD "); 209: printk("status %02x\n", inb(STATUS)); 210: if (ccb.tarstat|ccb.hastat) 211: printk("aha1542_command: returning %x (status %d)\n", ccb.tarstat + ((int) ccb.hastat << 16), mb[1].status); 212: #endif 213: aha1542_intr_reset(); 214: if (!my_done) { 215: printk("aha1542_intr_handle: Unexpected interrupt\n"); 216: return; 217: } 218: 219: /* is there mail :-) */ 220: 221: if (!mb[1].status) { 222: DEB(printk("aha1542_intr_handle: strange: mbif but no mail!\n")); 1.1.1.3 ! root 223: my_done(aha1542_host, DID_TIME_OUT << 16); 1.1 root 224: return; 225: } 226: 227: /* more error checking left out here */ 228: if (mb[1].status != 1) 229: /* This is surely wrong, but I don't know what's right */ 230: errstatus = makecode(ccb.hastat, ccb.tarstat); 231: else 232: errstatus = 0; 233: 234: mb[1].status = 0; 235: 236: if (ccb.tarstat == 2) { 237: int i; 238: DEB(printk("aha1542_intr_handle: sense:")); 239: for (i = 0; i < 12; i++) 240: printk("%02x ", ccb.cdb[ccb.cdblen+i]); 241: printk("\n"); 242: /* 243: DEB(printk("aha1542_intr_handle: buf:")); 244: for (i = 0; i < bufflen; i++) 245: printk("%02x ", ((unchar *)buff)[i]); 246: printk("\n"); 247: */ 248: } 249: DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus)); 1.1.1.3 ! root 250: my_done(aha1542_host, errstatus); 1.1 root 251: return; 252: } 253: 1.1.1.3 ! root 254: int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int, int)) 1.1 root 255: { 256: unchar ahacmd = CMD_START_SCSI; 257: unchar *cmd = (unchar *) cmnd; 1.1.1.3 ! root 258: DEB(int i); 1.1 root 259: 1.1.1.3 ! root 260: DEB(if (target > 1) {done(aha1542_host, DID_TIME_OUT << 16); return 0;}); 1.1 root 261: 262: #ifdef DEBUG 263: if (*cmd == READ_10 || *cmd == WRITE_10) 264: i = xscsi2int(cmd+2); 265: else if (*cmd == READ_6 || *cmd == WRITE_6) 266: i = scsi2int(cmd+2); 267: else 268: i = -1; 269: if (done) 270: printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen); 271: else 272: printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen); 273: aha1542_stat(); 274: printk("aha1542_queuecommand: dumping scsi cmd:"); 275: for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]); 276: printk("\n"); 277: if (*cmd == WRITE_10 || *cmd == WRITE_6) 278: return 0; /* we are still testing, so *don't* write */ 279: #endif 280: memset(&ccb, 0, sizeof ccb); 281: 282: ccb.cdblen = (*cmd<=0x1f)?6:10; /* SCSI Command Descriptor Block Length */ 283: 284: memcpy(ccb.cdb, cmd, ccb.cdblen); 285: ccb.op = 0; /* SCSI Initiator Command */ 286: ccb.idlun = (target&7)<<5; /* SCSI Target Id */ 287: ccb.rsalen = 12; 288: any2scsi(ccb.datalen, bufflen); 289: any2scsi(ccb.dataptr, buff); 290: ccb.linkptr[0] = ccb.linkptr[1] = ccb.linkptr[2] = 0; 291: ccb.commlinkid = 0; 292: 293: mb[0].status = 1; 294: mb[1].status = 0; 295: 296: #ifdef DEBUGd 297: printk("aha1542_command: sending.. "); 298: for (i = 0; i < sizeof(ccb)-10; i++) 299: printk("%02x ", ((unchar *)&ccb)[i]); 300: #endif 301: 302: if (done) { 303: DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat()); 304: if (do_done) 305: printk("aha1542_queuecommand: Two concurrent queuecommand?\n"); 306: else 307: do_done = done; 308: aha1542_out(&ahacmd, 1); /* start scsi command */ 309: DEB(aha1542_stat()); 310: aha1542_enable_intr(); 311: } 312: else 313: printk("aha1542_queuecommand: done can't be NULL\n"); 314: 315: return 0; 316: } 317: 318: volatile static int internal_done_flag = 0; 319: volatile static int internal_done_errcode = 0; 1.1.1.3 ! root 320: static void internal_done(int host, int errcode) 1.1 root 321: { 322: internal_done_errcode = errcode; 323: ++internal_done_flag; 324: } 325: 326: int aha1542_command(unchar target, const void *cmnd, void *buff, int bufflen) 327: { 328: DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n")); 329: aha1542_queuecommand(target, cmnd, buff, bufflen, internal_done); 330: 331: while (!internal_done_flag); 332: internal_done_flag = 0; 333: return internal_done_errcode; 334: } 335: 336: /* Initialize mailboxes */ 337: static void setup_mailboxes() 338: { 339: static unchar cmd[5] = {CMD_MBINIT, 1}; 340: 341: mb[0].status = mb[1].status = 0; 342: aha1542_intr_reset(); /* reset interrupts, so they don't block */ 343: any2scsi((cmd+2), mb); 344: any2scsi(mb[0].ccbptr, &ccb); 345: aha1542_out(cmd, 5); 346: WAIT(INTRFLAGS, INTRMASK, HACC, 0); 347: while (0) { 348: fail: 349: printk("aha1542_detect: failed setting up mailboxes\n"); 350: } 351: aha1542_intr_reset(); 352: } 353: 354: /* a hack to avoid a strange compilation error */ 355: 356: void call_buh() 357: { 358: set_intr_gate(0x2b,&aha1542_interrupt); 359: } 360: 361: /* return non-zero on detection */ 1.1.1.3 ! root 362: int aha1542_detect(int hostnum) 1.1 root 363: { 364: int i; 365: 366: DEB(printk("aha1542_detect: \n")); 367: 368: if (!(i = aha1542_test_port())) { 369: return 0; 370: } 371: 372: /* Set the Bus on/off-times as not to ruin floppy performens */ 373: { 374: static unchar oncmd[] = {CMD_BUSON_TIME, 5}; 375: static unchar offcmd[] = {CMD_BUSOFF_TIME, 9}; 376: 377: aha1542_intr_reset(); 378: aha1542_out(oncmd, 2); 379: WAIT(INTRFLAGS, INTRMASK, HACC, 0); 380: aha1542_intr_reset(); 381: aha1542_out(offcmd, 2); 382: WAIT(INTRFLAGS, INTRMASK, HACC, 0); 383: while (0) { 384: fail: 385: printk("aha1542_detect: setting bus on/off-time failed\n"); 386: } 387: aha1542_intr_reset(); 388: } 389: 390: aha1542_stat(); 391: setup_mailboxes(); 392: 393: aha1542_stat(); 394: 395: DEB(printk("aha1542_detect: enable interrupt channel %d\n", intr_chan)); 396: call_buh(); 397: 398: if (intr_chan >= 8) 399: outb(inb_p(0x21)&0xfb,0x21); /* open for slave ?? */ 400: 401: DEB(printk("aha1542_detect: enabling interrupts\n")); 402: aha1542_enable_intr(); 403: 404: #ifdef DEBUG 405: DEB(printk(" *** READ CAPACITY ***\n")); 406: 407: { 408: unchar buf[8]; 409: static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 410: int i; 411: 412: for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87; 413: for (i = 0; i < 2; ++i) 414: if (!aha1542_command(i, cmd, buf, sizeof(buf))) { 415: printk("aha_detect: LU %d sector_size %d device_size %d\n", 416: i, xscsi2int(buf+4), xscsi2int(buf)); 417: } 418: } 419: 420: DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n")); 421: 422: for (i = 0; i < 4; ++i) 423: { 424: unsigned char cmd[10]; 425: static buffer[512]; 426: 427: cmd[0] = READ_10; 428: cmd[1] = 0; 429: xany2scsi(cmd+2, i); 430: cmd[6] = 0; 431: cmd[7] = 0; 432: cmd[8] = 1; 433: cmd[9] = 0; 434: aha1542_command(0, cmd, buffer, 512); 435: } 436: #endif 1.1.1.3 ! root 437: aha1542_host = hostnum; 1.1 root 438: return 1; 439: } 440: 441: int aha1542_abort(int i) 442: { 443: DEB(printk("aha1542_abort\n")); 444: return 0; 445: } 446: 447: int aha1542_reset(void) 448: { 449: DEB(printk("aha1542_reset called\n")); 450: return 0; 451: } 452: 453: __asm__(" 454: _aha1542_interrupt: 455: cld 456: pushl %eax 457: pushl %ecx 458: pushl %edx 459: push %ds 460: push %es 461: push %fs 462: movl $0x10,%eax 463: mov %ax,%ds 464: mov %ax,%es 465: movl $0x17,%eax 466: mov %ax,%fs 467: movb $0x20,%al 468: outb %al,$0xA0 # EOI to interrupt controller #1 469: jmp 1f # give port chance to breathe 470: 1: jmp 1f 471: 1: outb %al,$0x20 472: # Please, someone, change this to use the timer 473: # andl $0xfffeffff,_timer_active 474: movl $_aha1542_intr_handle,%edx 475: call *%edx # ``interesting'' way of handling intr. 476: pop %fs 477: pop %es 478: pop %ds 479: popl %edx 480: popl %ecx 481: popl %eax 482: iret 483: ");
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.