|
|
1.1 ! root 1: /* ! 2: * seagate.c Copyright (C) 1992 Drew Eckhardt ! 3: * low level scsi driver for ST01/ST02 by ! 4: * Drew Eckhardt ! 5: * ! 6: * <[email protected]> ! 7: */ ! 8: ! 9: #include <linux/config.h> ! 10: ! 11: #ifdef CONFIG_SCSI_SEAGATE ! 12: #include <linux/sched.h> ! 13: ! 14: #include "seagate.h" ! 15: #include "scsi.h" ! 16: #include "hosts.h" ! 17: ! 18: static int incommand; /* ! 19: set if arbitration has finished and we are ! 20: in some command phase. ! 21: */ ! 22: ! 23: static void *base_address = NULL; /* ! 24: Where the card ROM starts, ! 25: used to calculate memory mapped ! 26: register location. ! 27: */ ! 28: static volatile int abort_confirm = 0; ! 29: ! 30: volatile void *st0x_cr_sr; /* ! 31: control register write, ! 32: status register read. ! 33: 256 bytes in length. ! 34: ! 35: Read is status of SCSI BUS, ! 36: as per STAT masks. ! 37: ! 38: */ ! 39: ! 40: ! 41: static volatile void *st0x_dr; /* ! 42: data register, read write ! 43: 256 bytes in length. ! 44: */ ! 45: ! 46: ! 47: static volatile int st0x_aborted=0; /* ! 48: set when we are aborted, ie by a time out, etc. ! 49: */ ! 50: ! 51: /* ! 52: In theory, we have a nice auto ! 53: detect routine - but this ! 54: overides it. ! 55: */ ! 56: ! 57: ! 58: #define retcode(result) (((result) << 16) | (message << 8) | status) ! 59: #define STATUS (*(unsigned char *) st0x_cr_sr) ! 60: #define CONTROL STATUS ! 61: #define DATA (*(unsigned char *) st0x_dr) ! 62: ! 63: #ifndef OVERRIDE ! 64: static const char * seagate_bases[] = {(char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, (char *) 0xce000, (char *) 0xce000, ! 65: (char *) 0xdc000, (char *) 0xde000}; ! 66: typedef struct ! 67: { ! 68: char *signature ; ! 69: unsigned offset; ! 70: unsigned length; ! 71: } Signature; ! 72: ! 73: static const Signature signatures[] = { ! 74: {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40}, ! 75: {"SEAGATE SCSI BIOS ",16, 17}, ! 76: {"SEAGATE SCSI BIOS ",17, 17}}; ! 77: /* ! 78: Note that the last signature handles BIOS revisions 3.0.0 and ! 79: 3.2 - the real ID's are ! 80: ! 81: SEAGATE SCSI BIOS REVISION 3.0.0 ! 82: SEAGATE SCSI BIOS REVISION 3.2 ! 83: ! 84: */ ! 85: ! 86: #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature)) ! 87: #endif ! 88: ! 89: int seagate_st0x_detect (int hostnum) ! 90: { ! 91: #ifndef OVERRIDE ! 92: int i,j; ! 93: #endif ! 94: ! 95: /* ! 96: First, we try for the manual override. ! 97: */ ! 98: #ifdef DEBUG ! 99: printk("Autodetecting seagate ST0x\n"); ! 100: #endif ! 101: ! 102: base_address = NULL; ! 103: #ifdef OVERRIDE ! 104: base_address = (void *) OVERRIDE; ! 105: #ifdef DEBUG ! 106: printk("Base address overridden to %x\n", base_address); ! 107: #endif ! 108: #else ! 109: /* ! 110: To detect this card, we simply look for the SEAGATE SCSI ! 111: from the BIOS version notice in all the possible locations ! 112: of the ROM's. ! 113: */ ! 114: ! 115: for (i = 0; i < (sizeof (seagate_bases) / sizeof (char * )); ++i) ! 116: for (j = 0; !base_address && j < NUM_SIGNATURES; ++j) ! 117: if (!memcmp ((void *) (seagate_bases[i] + ! 118: signatures[j].offset), (void *) signatures[j].signature, ! 119: signatures[j].length)) ! 120: base_address = (void *) seagate_bases[i]; ! 121: #endif ! 122: ! 123: if (base_address) ! 124: { ! 125: st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00); ! 126: st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00); ! 127: #ifdef DEBUG ! 128: printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr); ! 129: #endif ! 130: return -1; ! 131: } ! 132: else ! 133: { ! 134: #ifdef DEBUG ! 135: printk("ST0x not detected.\n"); ! 136: #endif ! 137: return 0; ! 138: } ! 139: } ! 140: ! 141: ! 142: ! 143: char *seagate_st0x_info(void) ! 144: { ! 145: static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n" ! 146: "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/04/24 18:01:50 root Exp root $\n"; ! 147: return buffer; ! 148: } ! 149: ! 150: ! 151: ! 152: int seagate_st0x_command(unsigned char target, const void *cmnd, ! 153: void *buff, int bufflen) ! 154: { ! 155: int len; ! 156: unsigned char *data; ! 157: ! 158: int clock; /* ! 159: We use clock for timeouts, etc. This replaces the ! 160: seagate_st0x_timeout that we had been using. ! 161: */ ! 162: #if (DEBUG & PHASE_SELECTION) ! 163: int temp; ! 164: #endif ! 165: ! 166: #if (DEBUG & PHASE_EXIT) ! 167: void *retaddr, *realretaddr; ! 168: #endif ! 169: ! 170: #if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT)) ! 171: int i; ! 172: #endif ! 173: ! 174: #if (DEBUG & PHASE_ETC) ! 175: int phase=0, newphase; ! 176: #endif ! 177: ! 178: int done = 0; ! 179: unsigned char status = 0; ! 180: unsigned char message = 0; ! 181: register unsigned char status_read; ! 182: ! 183: #if (DEBUG & PHASE_EXIT) ! 184: __asm__(" ! 185: movl 4(%%ebp), %%eax ! 186: ":"=a" (realretaddr):); ! 187: printk("return address = %08x\n", realretaddr); ! 188: #endif ! 189: ! 190: ! 191: len=bufflen; ! 192: data=(unsigned char *) buff; ! 193: ! 194: incommand = 0; ! 195: st0x_aborted = 0; ! 196: ! 197: #if (DEBUG & PRINT_COMMAND) ! 198: printk ("seagate_st0x_command, target = %d, command = ", target); ! 199: for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i) ! 200: printk("%02x ", ((unsigned char *) cmnd)[i]); ! 201: printk("\n"); ! 202: #endif ! 203: ! 204: if (target > 6) ! 205: return DID_BAD_TARGET; ! 206: ! 207: ! 208: #if (DEBUG & PHASE_BUS_FREE) ! 209: printk ("SCSI PHASE = BUS FREE \n"); ! 210: #endif ! 211: ! 212: /* ! 213: ! 214: BUS FREE PHASE ! 215: ! 216: On entry, we make sure that the BUS is in a BUS FREE ! 217: phase, by insuring that both BSY and SEL are low for ! 218: at least one bus settle delay. The standard requires a ! 219: minimum of 400 ns, which is 16 clock cycles on a ! 220: 386-40 . ! 221: ! 222: This doesn't give us much time - so we'll do two several ! 223: reads to be sure be sure. ! 224: */ ! 225: ! 226: clock = jiffies + ST0X_BUS_FREE_DELAY; ! 227: ! 228: while (((STATUS | STATUS | STATUS) & ! 229: (STAT_BSY | STAT_SEL)) && ! 230: (!st0x_aborted) && (jiffies < clock)); ! 231: ! 232: if (jiffies > clock) ! 233: return retcode(DID_BUS_BUSY); ! 234: else if (st0x_aborted) ! 235: return retcode(st0x_aborted); ! 236: ! 237: /* ! 238: Bus free has been detected, within BUS settle. I used to support an arbitration ! 239: phase - however, on the seagate, this degraded performance by a factor > 10 - so ! 240: it is no more. ! 241: */ ! 242: ! 243: /* ! 244: SELECTION PHASE ! 245: ! 246: Now, we select the disk, giving it the SCSI ID at data ! 247: and a command of PARITY if necessary, plus driver enable, ! 248: plus raise select signal. ! 249: */ ! 250: ! 251: #if (DEBUG & PHASE_SELECTION) ! 252: printk("SCSI PHASE = SELECTION\n"); ! 253: #endif ! 254: ! 255: clock = jiffies + ST0X_SELECTION_DELAY; ! 256: DATA = (unsigned char) (1 << target); ! 257: ! 258: CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL; ! 259: ! 260: /* ! 261: When the SCSI device decides that we're gawking at it, it will respond by asserting BUSY on the bus. ! 262: */ ! 263: while (!((status_read = STATUS) & STAT_BSY) && (jiffies < clock) && !st0x_aborted) ! 264: ! 265: #if (DEBUG & PHASE_SELECTION) ! 266: { ! 267: temp = clock - jiffies; ! 268: ! 269: if (!(jiffies % 5)) ! 270: printk("seagate_st0x_timeout : %d \r",temp); ! 271: ! 272: } ! 273: printk("Done. \n\r"); ! 274: printk("Status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n", status_read, temp, ! 275: st0x_aborted); ! 276: #else ! 277: ; ! 278: #endif ! 279: ! 280: ! 281: if ((jiffies > clock) || (!st0x_aborted & !(status_read & STAT_BSY))) ! 282: { ! 283: #if (DEBUG & PHASE_SELECT) ! 284: printk ("NO CONNECT with target %d, status = %x \n", target, STATUS); ! 285: #endif ! 286: return retcode(DID_NO_CONNECT); ! 287: } ! 288: ! 289: /* ! 290: If we have been aborted, and we have a command in progress, IE the target still has ! 291: BSY asserted, then we will reset the bus, and notify the midlevel driver to ! 292: expect sense. ! 293: */ ! 294: ! 295: if (st0x_aborted) ! 296: { ! 297: CONTROL = BASE_CMD; ! 298: if (STATUS & STAT_BSY) ! 299: { ! 300: seagate_st0x_reset(); ! 301: return retcode(DID_RESET); ! 302: } ! 303: ! 304: return retcode(st0x_aborted); ! 305: } ! 306: ! 307: /* ! 308: COMMAND PHASE ! 309: The device has responded with a BSY, so we may now enter ! 310: the information transfer phase, where we will send / recieve ! 311: data and command as directed by the target. ! 312: ! 313: ! 314: The nasty looking read / write inline assembler loops we use for ! 315: DATAIN and DATAOUT phases are approximately 4-5 times as fast as ! 316: the 'C' versions - since we're moving 1024 bytes of data, this ! 317: really adds up. ! 318: */ ! 319: ! 320: #if (DEBUG & PHASE_ETC) ! 321: printk("PHASE = information transfer\n"); ! 322: #endif ! 323: ! 324: incommand = 1; ! 325: ! 326: /* ! 327: Enable command ! 328: */ ! 329: ! 330: CONTROL = BASE_CMD | CMD_DRVR_ENABLE; ! 331: ! 332: /* ! 333: Now, we poll the device for status information, ! 334: and handle any requests it makes. Note that since we are unsure of ! 335: how much data will be flowing across the system, etc and cannot ! 336: make reasonable timeouts, that we will instead have the midlevel ! 337: driver handle any timeouts that occur in this phase. ! 338: */ ! 339: ! 340: while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done) ! 341: { ! 342: #ifdef PARITY ! 343: if (status_read & STAT_PARITY) ! 344: { ! 345: done = 1; ! 346: st0x_aborted = DID_PARITY; ! 347: } ! 348: #endif ! 349: ! 350: if (status_read & STAT_REQ) ! 351: { ! 352: #if (DEBUG & PHASE_ETC) ! 353: if ((newphase = (status_read & REQ_MASK)) != phase) ! 354: { ! 355: phase = newphase; ! 356: switch (phase) ! 357: { ! 358: case REQ_DATAOUT : printk("SCSI PHASE = DATA OUT\n"); break; ! 359: case REQ_DATAIN : printk("SCSI PHASE = DATA IN\n"); break; ! 360: case REQ_CMDOUT : printk("SCSI PHASE = COMMAND OUT\n"); break; ! 361: case REQ_STATIN : printk("SCSI PHASE = STATUS IN\n"); break; ! 362: case REQ_MSGOUT : printk("SCSI PHASE = MESSAGE OUT\n"); break; ! 363: case REQ_MSGIN : printk("SCSI PHASE = MESSAGE IN\n"); break; ! 364: default : printk("UNKNOWN PHASE"); st0x_aborted = 1; done = 1; ! 365: } ! 366: } ! 367: #endif ! 368: ! 369: switch (status_read & REQ_MASK) ! 370: { ! 371: case REQ_DATAOUT : ! 372: ! 373: /* ! 374: We loop as long as we are in a data out phase, there is data to send, and BSY is still ! 375: active ! 376: */ ! 377: __asm__ (" ! 378: ! 379: /* ! 380: Local variables : ! 381: len = ecx ! 382: data = esi ! 383: st0x_cr_sr = ebx ! 384: st0x_dr = edi ! 385: ! 386: Test for any data here at all. ! 387: */ ! 388: movl %0, %%esi /* local value of data */ ! 389: movl %1, %%ecx /* local value of len */ ! 390: orl %%ecx, %%ecx ! 391: jz 2f ! 392: ! 393: cld ! 394: ! 395: movl _st0x_cr_sr, %%ebx ! 396: movl _st0x_dr, %%edi ! 397: ! 398: 1: movb (%%ebx), %%al ! 399: /* ! 400: Test for BSY ! 401: */ ! 402: ! 403: test $1, %%al ! 404: jz 2f ! 405: ! 406: /* ! 407: Test for data out phase - STATUS & REQ_MASK should be REQ_DATAOUT, which is 0. ! 408: */ ! 409: test $0xe, %%al ! 410: jnz 2f ! 411: /* ! 412: Test for REQ ! 413: */ ! 414: test $0x10, %%al ! 415: jz 1b ! 416: lodsb ! 417: movb %%al, (%%edi) ! 418: loop 1b ! 419: ! 420: 2: ! 421: movl %%esi, %2 ! 422: movl %%ecx, %3 ! 423: ": ! 424: /* output */ ! 425: "=r" (data), "=r" (len) : ! 426: /* input */ ! 427: "0" (data), "1" (len) : ! 428: /* clobbered */ ! 429: "ebx", "ecx", "edi", "esi"); ! 430: ! 431: break; ! 432: ! 433: case REQ_DATAIN : ! 434: /* ! 435: We loop as long as we are in a data out phase, there is room to read, and BSY is still ! 436: active ! 437: */ ! 438: ! 439: __asm__ (" ! 440: /* ! 441: Local variables : ! 442: ecx = len ! 443: edi = data ! 444: esi = st0x_cr_sr ! 445: ebx = st0x_dr ! 446: ! 447: Test for room to read ! 448: */ ! 449: ! 450: movl %0, %%edi /* data */ ! 451: movl %1, %%ecx /* len */ ! 452: orl %%ecx, %%ecx ! 453: jz 2f ! 454: ! 455: cld ! 456: movl _st0x_cr_sr, %%esi ! 457: movl _st0x_dr, %%ebx ! 458: ! 459: 1: movb (%%esi), %%al ! 460: /* ! 461: Test for BSY ! 462: */ ! 463: ! 464: test $1, %%al ! 465: jz 2f ! 466: ! 467: /* ! 468: Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4. ! 469: */ ! 470: movb $0xe, %%ah ! 471: andb %%al, %%ah ! 472: cmpb $0x04, %%ah ! 473: jne 2f ! 474: ! 475: /* ! 476: Test for REQ ! 477: */ ! 478: test $0x10, %%al ! 479: jz 1b ! 480: ! 481: movb (%%ebx), %%al ! 482: stosb ! 483: loop 1b ! 484: ! 485: 2: movl %%edi, %2 /* data */ ! 486: movl %%ecx, %3 /* len */ ! 487: ": ! 488: /* output */ ! 489: "=r" (data), "=r" (len) : ! 490: /* input */ ! 491: "0" (data), "1" (len) : ! 492: /* clobbered */ ! 493: "ebx", "ecx", "edi", "esi"); ! 494: break; ! 495: ! 496: case REQ_CMDOUT : ! 497: while (((status_read = STATUS) & STAT_BSY) && ((status_read & REQ_MASK) == ! 498: REQ_CMDOUT)) ! 499: DATA = *(unsigned char *) cmnd ++; ! 500: break; ! 501: ! 502: case REQ_STATIN : ! 503: status = DATA; ! 504: break; ! 505: ! 506: case REQ_MSGOUT : ! 507: DATA = MESSAGE_REJECT; ! 508: break; ! 509: ! 510: case REQ_MSGIN : ! 511: if ((message = DATA) == COMMAND_COMPLETE) ! 512: done=1; ! 513: ! 514: break; ! 515: ! 516: default : printk("UNKNOWN PHASE"); st0x_aborted = DID_ERROR; ! 517: } ! 518: } ! 519: ! 520: } ! 521: ! 522: #if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT)) ! 523: printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len); ! 524: #endif ! 525: ! 526: #if (DEBUG & PHASE_EXIT) ! 527: printk("Buffer : \n"); ! 528: for (i = 0; i < 20; ++i) ! 529: printk ("%02x ", ((unsigned char *) buff)[i]); ! 530: printk("\n"); ! 531: printk("Status = %02x, message = %02x\n", status, message); ! 532: #endif ! 533: ! 534: ! 535: if (st0x_aborted) ! 536: { ! 537: if (STATUS & STAT_BSY) ! 538: { ! 539: seagate_st0x_reset(); ! 540: st0x_aborted = DID_RESET; ! 541: } ! 542: abort_confirm = 1; ! 543: } ! 544: ! 545: CONTROL = BASE_CMD; ! 546: ! 547: #if (DEBUG & PHASE_EXIT) ! 548: __asm__(" ! 549: mov 4(%%ebp), %%eax ! 550: ":"=a" (retaddr):); ! 551: ! 552: printk("Exiting seagate_st0x_command() - return address is %08x \n", retaddr); ! 553: if (retaddr != realretaddr) ! 554: panic ("Corrupted stack : return address on entry != return address on exit.\n"); ! 555: ! 556: #endif ! 557: ! 558: return retcode (st0x_aborted); ! 559: } ! 560: ! 561: int seagate_st0x_abort (int code) ! 562: { ! 563: if (code) ! 564: st0x_aborted = code; ! 565: else ! 566: st0x_aborted = DID_ABORT; ! 567: ! 568: return 0; ! 569: } ! 570: ! 571: /* ! 572: the seagate_st0x_reset function resets the SCSI bus ! 573: */ ! 574: ! 575: int seagate_st0x_reset (void) ! 576: { ! 577: unsigned clock; ! 578: /* ! 579: No timeouts - this command is going to fail because ! 580: it was reset. ! 581: */ ! 582: ! 583: #ifdef DEBUG ! 584: printk("In seagate_st0x_reset()\n"); ! 585: #endif ! 586: ! 587: ! 588: /* assert RESET signal on SCSI bus. */ ! 589: ! 590: CONTROL = BASE_CMD | CMD_RST; ! 591: clock=jiffies+2; ! 592: ! 593: ! 594: /* Wait. */ ! 595: ! 596: while (jiffies < clock); ! 597: ! 598: CONTROL = BASE_CMD; ! 599: ! 600: st0x_aborted = DID_RESET; ! 601: ! 602: #ifdef DEBUG ! 603: printk("SCSI bus reset.\n"); ! 604: #endif ! 605: return 0; ! 606: } ! 607: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.