|
|
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:
1.1.1.2 ! root 11: #if defined(CONFIG_SCSI_SEAGATE) || defined(CONFIG_SCSI_FD_88x)
! 12: #include <asm/io.h>
! 13: #include <asm/system.h>
1.1 root 14: #include <linux/sched.h>
15: #include "seagate.h"
16: #include "scsi.h"
17: #include "hosts.h"
18:
1.1.1.2 ! root 19: extern void seagate_intr(void);
! 20: static int internal_command(unsigned char target, const void *cmnd,
! 21: void *buff, int bufflen, int reselect);
! 22: void (*do_seagate)(void) = NULL;
! 23:
1.1 root 24: static int incommand; /*
25: set if arbitration has finished and we are
26: in some command phase.
27: */
28:
29: static void *base_address = NULL; /*
30: Where the card ROM starts,
31: used to calculate memory mapped
32: register location.
33: */
34: static volatile int abort_confirm = 0;
35:
1.1.1.2 ! root 36: static volatile void *st0x_cr_sr; /*
1.1 root 37: control register write,
38: status register read.
39: 256 bytes in length.
40:
41: Read is status of SCSI BUS,
42: as per STAT masks.
43:
44: */
45:
46:
47: static volatile void *st0x_dr; /*
48: data register, read write
49: 256 bytes in length.
50: */
51:
52:
53: static volatile int st0x_aborted=0; /*
54: set when we are aborted, ie by a time out, etc.
55: */
56:
57: /*
58: In theory, we have a nice auto
59: detect routine - but this
60: overides it.
61: */
62:
63:
64: #define retcode(result) (((result) << 16) | (message << 8) | status)
65: #define STATUS (*(unsigned char *) st0x_cr_sr)
66: #define CONTROL STATUS
67: #define DATA (*(unsigned char *) st0x_dr)
68:
69: #ifndef OVERRIDE
70: static const char * seagate_bases[] = {(char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, (char *) 0xce000, (char *) 0xce000,
71: (char *) 0xdc000, (char *) 0xde000};
72: typedef struct
73: {
74: char *signature ;
75: unsigned offset;
76: unsigned length;
77: } Signature;
78:
79: static const Signature signatures[] = {
1.1.1.2 ! root 80: #ifdef CONFIG_SCSI_SEAGATE
1.1 root 81: {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40},
1.1.1.2 ! root 82:
! 83: /*
! 84: The following two lines are NOT mistakes. One detects
! 85: ROM revision 3.0.0, the other 3.2. Since seagate
! 86: has only one type of SCSI adapter, and this is not
! 87: going to change, the "SEAGATE" and "SCSI" together
! 88: are probably "good enough"
! 89: */
! 90:
1.1 root 91: {"SEAGATE SCSI BIOS ",16, 17},
1.1.1.2 ! root 92: {"SEAGATE SCSI BIOS ",17, 17},
! 93: #endif
! 94:
! 95: /*
! 96: This is for the Future Domain 88x series. I've been told that
! 97: the Seagate controllers are just repackages of these, and seeing
! 98: early seagate BIOS bearing the Future Domain copyright,
! 99: I believe it.
! 100: */
! 101:
! 102: #ifdef CONFIG_SCSI_FD_88x
! 103: {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/90", 5, 46},
! 104: #endif
! 105: }
! 106: ;
1.1 root 107: /*
108: Note that the last signature handles BIOS revisions 3.0.0 and
109: 3.2 - the real ID's are
110:
111: SEAGATE SCSI BIOS REVISION 3.0.0
112: SEAGATE SCSI BIOS REVISION 3.2
113:
114: */
115:
116: #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
117: #endif
118:
1.1.1.2 ! root 119: /*
! 120: * hostno stores the hostnumber, as told to us by the init routine.
! 121: */
! 122:
! 123: static int hostno = -1;
! 124:
1.1 root 125: int seagate_st0x_detect (int hostnum)
126: {
1.1.1.2 ! root 127: #ifndef OVERRIDE
! 128: int i,j;
! 129: #endif
1.1 root 130:
1.1.1.2 ! root 131: /*
! 132: * First, we try for the manual override.
! 133: */
! 134: #ifdef DEBUG
! 135: printk("Autodetecting seagate ST0x\n");
! 136: #endif
! 137:
! 138: if (hostno != -1)
! 139: {
! 140: printk ("ERROR : seagate_st0x_detect() called twice.\n");
! 141: return 0;
! 142: }
1.1 root 143:
144: base_address = NULL;
1.1.1.2 ! root 145: #ifdef OVERRIDE
! 146: base_address = (void *) OVERRIDE;
! 147: #ifdef DEBUG
! 148: printk("Base address overridden to %x\n", base_address);
! 149: #endif
! 150: #else
! 151: /*
! 152: * To detect this card, we simply look for the signature
! 153: * from the BIOS version notice in all the possible locations
! 154: * of the ROM's. This has a nice sideeffect of not trashing
! 155: * any register locations that might be used by something else.
! 156: */
1.1 root 157:
158: for (i = 0; i < (sizeof (seagate_bases) / sizeof (char * )); ++i)
159: for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
160: if (!memcmp ((void *) (seagate_bases[i] +
161: signatures[j].offset), (void *) signatures[j].signature,
162: signatures[j].length))
163: base_address = (void *) seagate_bases[i];
1.1.1.2 ! root 164: #endif
1.1 root 165:
166: if (base_address)
167: {
168: st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00);
169: st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00);
1.1.1.2 ! root 170: #ifdef DEBUG
! 171: printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
! 172: #endif
! 173: hostno = hostnum;
! 174:
! 175: /*
! 176: * At all times, we will use IRQ 5.
! 177: */
! 178:
! 179: #if 1
! 180: set_intr_gate (0x25, seagate_intr);
! 181: __asm__("
! 182: inb $0x21, %%al
! 183: andb $0xdf, %%al
! 184: outb %%al, $0x21"::);
! 185: #endif
1.1 root 186: return -1;
187: }
188: else
189: {
1.1.1.2 ! root 190: #ifdef DEBUG
! 191: printk("ST0x not detected.\n");
! 192: #endif
1.1 root 193: return 0;
194: }
195: }
196:
197: char *seagate_st0x_info(void)
198: {
199: static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n"
1.1.1.2 ! root 200: "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/07/24 06:27:38 root Exp root $\n";
1.1 root 201: return buffer;
202: }
203:
1.1.1.2 ! root 204: /*
! 205: * These are our saved pointers for the outstanding command that is
! 206: * waiting for a reconnect
! 207: */
! 208:
! 209: static unsigned char current_target;
! 210: static unsigned char *current_cmnd, *current_data;
! 211: static int current_bufflen;
! 212: static void (*done_fn)(int, int) = NULL;
! 213:
! 214: /*
! 215: * These control weather or not disconnect / reconnect will be attempted,
! 216: * or are being attempted.
! 217: */
! 218:
! 219: #define NO_RECONNECT 0
! 220: #define RECONNECT_NOW 1
! 221: #define CAN_RECONNECT 2
! 222:
! 223: /*
! 224: * This determines if we are expecting to reconnect or not.
! 225: */
! 226:
! 227: static int should_reconnect = 0;
1.1 root 228:
1.1.1.2 ! root 229: void seagate_unexpected_intr (void)
! 230: {
! 231: printk("scsi%d: unexpected interrupt.\n", hostno);
! 232: }
! 233:
! 234: /*
! 235: * The seagate_reconnect_intr routine is called when a target reselects the
! 236: * host adapter. This occurs on the interrupt triggered by the target
! 237: * asserting SEL.
! 238: */
1.1 root 239:
1.1.1.2 ! root 240: void seagate_reconnect_intr (void)
! 241: {
! 242: int temp;
! 243:
! 244: #if (DEBUG & PHASE_RESELECT)
! 245: printk("scsi%d : seagate_reconnect_intr() called\n", hostno);
! 246: #endif
! 247:
! 248: if (!should_reconnect)
! 249: seagate_unexpected_intr();
! 250: else
! 251: {
! 252: should_reconnect = 0;
! 253:
! 254: #if (DEBUG & PHASE_RESELECT)
! 255: printk("scsi%d : internal_command("
! 256: "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno,
! 257: current_target, current_data, current_bufflen);
! 258: #endif
! 259:
! 260: temp = internal_command (current_target,
! 261: current_cmnd, current_data, current_bufflen,
! 262: RECONNECT_NOW);
! 263:
! 264: if (msg_byte(temp) != DISCONNECT)
! 265: {
! 266: if (done_fn)
! 267: {
! 268: #if (DEBUG & PHASE_RESELECT)
! 269: printk("scsi%d : done_fn(%d,%08x)", hostno,
! 270: hostno, temp);
! 271: #endif
! 272: done_fn (hostno, temp);
! 273: }
! 274: else
! 275: printk("done_fn() not defined.\n");
! 276: }
! 277: }
! 278: }
! 279:
! 280: /*
! 281: * The seagate_st0x_queue_command() function provides a queued interface
! 282: * to the seagate SCSI driver. Basically, it just passes control onto the
! 283: * seagate_command() function, after fixing it so that the done_fn()
! 284: * is set to the one passed to the function.
! 285: */
! 286:
! 287: int seagate_st0x_queue_command (unsigned char target, const void *cmnd,
! 288: void *buff, int bufflen, void (*fn)(int,
! 289: int))
! 290: {
! 291: int result;
! 292:
! 293: done_fn = fn;
! 294: current_target = target;
! 295: (const void *) current_cmnd = cmnd;
! 296: current_data = buff;
! 297: current_bufflen = bufflen;
! 298:
! 299: result = internal_command (target, cmnd, buff, bufflen,
! 300: CAN_RECONNECT);
! 301: if (msg_byte(result) == DISCONNECT)
! 302: return 0;
! 303: else
! 304: {
! 305: done_fn (hostno, result);
! 306: return 1;
! 307: }
! 308: }
! 309:
! 310: int seagate_st0x_command (unsigned char target, const void *cmnd,
! 311: void *buff, int bufflen)
! 312: {
! 313: return internal_command (target, cmnd, buff, bufflen,
! 314: (int) NO_RECONNECT);
! 315: }
! 316:
! 317: static int internal_command(unsigned char target, const void *cmnd,
! 318: void *buff, int bufflen, int reselect)
1.1 root 319: {
320: int len;
321: unsigned char *data;
1.1.1.2 ! root 322: int clock;
! 323: int temp;
1.1 root 324:
1.1.1.2 ! root 325:
! 326: #if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))
! 327: int i;
! 328: #endif
! 329:
! 330: #if (DEBUG & PHASE_ETC)
! 331: int phase=0, newphase;
! 332: #endif
1.1 root 333:
334: int done = 0;
335: unsigned char status = 0;
336: unsigned char message = 0;
337: register unsigned char status_read;
338:
1.1.1.2 ! root 339: do_seagate = seagate_unexpected_intr;
1.1 root 340:
341: len=bufflen;
342: data=(unsigned char *) buff;
343:
344: incommand = 0;
345: st0x_aborted = 0;
346:
1.1.1.2 ! root 347: #if (DEBUG & PRINT_COMMAND)
! 348: printk ("scsi%d : target = %d, command = ", hostno, target);
! 349: for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
! 350: printk("%02x ", ((unsigned char *) cmnd)[i]);
! 351: printk("\n");
! 352: #endif
! 353:
! 354: #if (DEBUG & PHASE_RESELECT)
! 355: switch (reselect)
! 356: {
! 357: case RECONNECT_NOW :
! 358: printk("scsi%d : reconnecting\n", hostno);
! 359: break;
! 360: case CAN_RECONNECT :
! 361: printk("scsi%d : allowed to reconnect\n", hostno);
! 362: break;
! 363: default :
! 364: printk("scsi%d : not allowed to reconnect\n", hostno);
! 365: }
! 366: #endif
1.1 root 367:
1.1.1.2 ! root 368:
1.1 root 369: if (target > 6)
1.1.1.2 ! root 370: {
! 371: if (reselect == RECONNECT_NOW)
! 372: eoi();
1.1 root 373: return DID_BAD_TARGET;
1.1.1.2 ! root 374: }
1.1 root 375:
1.1.1.2 ! root 376: /*
! 377: * We work it differently depending on if this is is "the first time,"
! 378: * or a reconnect. If this is a reselct phase, then SEL will
! 379: * be asserted, and we must skip selection / arbitration phases.
! 380: */
1.1 root 381:
1.1.1.2 ! root 382: if (reselect == RECONNECT_NOW)
! 383: {
! 384: #if (DEBUG & PHASE_RESELECT)
! 385: printk("scsi%d : phase RESELECT \n", hostno);
! 386: #endif
1.1 root 387:
1.1.1.2 ! root 388: /*
! 389: * At this point, we should find the logical or of our ID and the original
! 390: * target's ID on the BUS, with BSY, SEL, and I/O signals asserted.
! 391: *
! 392: * After ARBITRATION phase is completed, only SEL, BSY, and the
! 393: * target ID are asserted. A valid initator ID is not on the bus
! 394: * until IO is asserted, so we must wait for that.
! 395: */
! 396:
! 397: for (clock = jiffies + 10, temp = 0; (jiffies < clock) &&
! 398: !(STATUS & STAT_IO););
! 399:
! 400: if (jiffies >= clock)
! 401: {
! 402: #if (DEBUG & PHASE_RESELECT)
! 403: printk("scsi%d : RESELECT timed out while waiting for IO .\n",
! 404: hostno);
! 405: #endif
! 406: eoi();
! 407: return (DID_BAD_INTR << 16);
! 408: }
1.1 root 409:
1.1.1.2 ! root 410: /*
! 411: * After I/O is asserted by the target, we can read our ID and its
! 412: * ID off of the BUS.
! 413: */
! 414:
! 415: if (!((temp = DATA) & 0x80))
! 416: {
! 417: #if (DEBUG & PHASE_RESELECT)
! 418: printk("scsi%d : detected reconnect request to different target.\n"
! 419: "\tData bus = %d\n", hostno, temp);
! 420: #endif
! 421: eoi();
! 422: return (DID_BAD_INTR << 16);
! 423: }
1.1 root 424:
1.1.1.2 ! root 425: if (!(temp & (1 << current_target)))
! 426: {
! 427: printk("scsi%d : Unexpected reselect interrupt. Data bus = %d\n",
! 428: hostno, temp);
! 429: eoi();
! 430: return (DID_BAD_INTR << 16);
! 431: }
! 432: data=current_data; /* WDE add */
! 433: cmnd=current_cmnd; /* WDE add */
! 434: len=current_bufflen; /* WDE add */
1.1 root 435:
1.1.1.2 ! root 436: /*
! 437: * We have determined that we have been selected. At this point,
! 438: * we must respond to the reselection by asserting BSY ourselves
! 439: */
1.1 root 440:
1.1.1.2 ! root 441: CONTROL = (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY);
1.1 root 442:
1.1.1.2 ! root 443: /*
! 444: * The target will drop SEL, and raise BSY, at which time we must drop
! 445: * BSY.
! 446: */
! 447:
! 448: for (clock = jiffies + 10; (jiffies < clock) && (STATUS & STAT_SEL););
! 449:
! 450: if (jiffies >= clock)
! 451: {
! 452: CONTROL = (BASE_CMD | CMD_INTR);
! 453: #if (DEBUG & PHASE_RESELECT)
! 454: printk("scsi%d : RESELECT timed out while waiting for SEL.\n",
! 455: hostno);
! 456: #endif
! 457: eoi();
! 458: return (DID_BAD_INTR << 16);
! 459: }
1.1 root 460:
1.1.1.2 ! root 461: CONTROL = BASE_CMD;
1.1 root 462:
1.1.1.2 ! root 463: /*
! 464: * At this point, we have connected with the target and can get
! 465: * on with our lives.
! 466: */
! 467: eoi();
! 468: }
! 469: else
! 470: {
! 471: #if (DEBUG & PHASE_BUS_FREE)
! 472: printk ("scsi%d : phase = BUS FREE \n", hostno);
! 473: #endif
1.1 root 474:
1.1.1.2 ! root 475: /*
! 476: * BUS FREE PHASE
! 477: *
! 478: * On entry, we make sure that the BUS is in a BUS FREE
! 479: * phase, by insuring that both BSY and SEL are low for
! 480: * at least one bus settle delay. Several reads help
! 481: * eliminate wire glitch.
! 482: */
! 483:
! 484: clock = jiffies + ST0X_BUS_FREE_DELAY;
! 485:
! 486: while (((STATUS | STATUS | STATUS) &
! 487: (STAT_BSY | STAT_SEL)) &&
! 488: (!st0x_aborted) && (jiffies < clock));
! 489:
! 490: if (jiffies > clock)
! 491: return retcode(DID_BUS_BUSY);
! 492: else if (st0x_aborted)
! 493: return retcode(st0x_aborted);
1.1 root 494:
1.1.1.2 ! root 495: /*
! 496: * Bus free has been detected, within BUS settle. I used to
! 497: * support an arbitration phase - however, on the Seagate, this
! 498: * degraded performance by a factor > 10 - so it is no more.
! 499: */
1.1 root 500:
1.1.1.2 ! root 501: /*
! 502: * SELECTION PHASE
! 503: *
! 504: * Now, we select the disk, giving it the SCSI ID at data
! 505: * and a command of PARITY if necessary, and we raise SEL.
! 506: */
1.1 root 507:
1.1.1.2 ! root 508: #if (DEBUG & PHASE_SELECTION)
! 509: printk("scsi%d : phase = SELECTION\n", hostno);
! 510: #endif
! 511:
! 512: clock = jiffies + ST0X_SELECTION_DELAY;
! 513:
! 514: /*
! 515: * If we wish to disconnect, we should request a MESSAGE OUT
! 516: * at this point. Technically, ATTN should be raised before
! 517: * SEL = true and BSY = false (from arbitration), but I think this
! 518: * should do.
! 519: */
! 520: if (reselect)
! 521: CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
! 522: CMD_ATTN;
! 523:
! 524: /*
! 525: * We must assert both our ID and our target's ID on the bus.
! 526: */
! 527: DATA = (unsigned char) ((1 << target) | 0x80);
! 528:
! 529: /*
! 530: * If we are allowing ourselves to reconnect, then I will keep
! 531: * ATTN raised so we get MSG OUT.
! 532: */
! 533: CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL |
! 534: (reselect ? CMD_ATTN : 0);
! 535:
! 536: /*
! 537: * When the SCSI device decides that we're gawking at it, it will
! 538: * respond by asserting BUSY on the bus.
! 539: */
! 540: while (!((status_read = STATUS) & STAT_BSY) &&
! 541: (jiffies < clock) && !st0x_aborted)
1.1 root 542:
543: #if (DEBUG & PHASE_SELECTION)
544: {
545: temp = clock - jiffies;
546:
547: if (!(jiffies % 5))
548: printk("seagate_st0x_timeout : %d \r",temp);
549:
550: }
551: printk("Done. \n\r");
1.1.1.2 ! root 552: printk("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n",
! 553: hostno, status_read, temp, st0x_aborted);
1.1 root 554: #else
555: ;
556: #endif
557:
558:
1.1.1.2 ! root 559: if ((jiffies > clock) || (!st0x_aborted &&
! 560: !(status_read & STAT_BSY)))
1.1 root 561: {
1.1.1.2 ! root 562: #if (DEBUG & PHASE_SELECT)
! 563: printk ("scsi%d : NO CONNECT with target %d, status = %x \n",
! 564: hostno, target, STATUS);
! 565: #endif
! 566: return retcode(DID_NO_CONNECT);
1.1 root 567: }
568:
1.1.1.2 ! root 569: /*
! 570: * If we have been aborted, and we have a command in progress, IE the
! 571: * target still has BSY asserted, then we will reset the bus, and
! 572: * notify the midlevel driver to expect sense.
! 573: */
1.1 root 574:
1.1.1.2 ! root 575: if (st0x_aborted)
! 576: {
! 577: CONTROL = BASE_CMD;
! 578: if (STATUS & STAT_BSY)
! 579: {
! 580: seagate_st0x_reset();
! 581: return retcode(DID_RESET);
! 582: }
! 583: return retcode(st0x_aborted);
! 584: }
! 585: }
1.1 root 586:
1.1.1.2 ! root 587: CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
! 588: ((reselect == CAN_RECONNECT) ? CMD_ATTN : 0) ;
! 589:
! 590: /*
! 591: * INFORMATION TRANSFER PHASE
! 592: *
! 593: * The nasty looking read / write inline assembler loops we use for
! 594: * DATAIN and DATAOUT phases are approximately 4-5 times as fast as
! 595: * the 'C' versions - since we're moving 1024 bytes of data, this
! 596: * really adds up.
! 597: */
! 598:
! 599: #if (DEBUG & PHASE_ETC)
! 600: printk("scsi%d : phase = INFORMATION TRANSFER\n", hostno);
! 601: #endif
1.1 root 602:
603: incommand = 1;
604:
605:
1.1.1.2 ! root 606: /*
! 607: * Now, we poll the device for status information,
! 608: * and handle any requests it makes. Note that since we are unsure of
! 609: * how much data will be flowing across the system, etc and cannot
! 610: * make reasonable timeouts, that we will instead have the midlevel
! 611: * driver handle any timeouts that occur in this phase.
! 612: */
1.1 root 613:
614: while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done)
1.1.1.2 ! root 615: {
! 616: #ifdef PARITY
! 617: if (status_read & STAT_PARITY)
1.1 root 618: {
1.1.1.2 ! root 619: done = 1;
! 620: st0x_aborted = DID_PARITY;
! 621: }
! 622: #endif
1.1 root 623:
1.1.1.2 ! root 624: if (status_read & STAT_REQ)
! 625: {
! 626: #if (DEBUG & PHASE_ETC)
! 627: if ((newphase = (status_read & REQ_MASK)) != phase)
1.1 root 628: {
1.1.1.2 ! root 629: phase = newphase;
! 630: switch (phase)
! 631: {
! 632: case REQ_DATAOUT:
! 633: printk("scsi%d : phase = DATA OUT\n",
! 634: hostno);
! 635: break;
! 636: case REQ_DATAIN :
! 637: printk("scsi%d : phase = DATA IN\n",
! 638: hostno);
! 639: break;
! 640: case REQ_CMDOUT :
! 641: printk("scsi%d : phase = COMMAND OUT\n",
! 642: hostno);
! 643: break;
! 644: case REQ_STATIN :
! 645: printk("scsi%d : phase = STATUS IN\n",
! 646: hostno);
! 647: break;
! 648: case REQ_MSGOUT :
! 649: printk("scsi%d : phase = MESSAGE OUT\n",
! 650: hostno);
! 651: break;
! 652: case REQ_MSGIN :
! 653: printk("scsi%d : phase = MESSAGE IN\n",
! 654: hostno);
! 655: break;
! 656: default :
! 657: printk("scsi%d : phase = UNKNOWN\n",
! 658: hostno);
! 659: st0x_aborted = 1;
! 660: done = 1;
! 661: }
! 662: }
! 663: #endif
1.1 root 664:
1.1.1.2 ! root 665: switch (status_read & REQ_MASK)
! 666: {
! 667: case REQ_DATAOUT :
! 668:
! 669: /*
! 670: * We loop as long as we are in a data out phase, there is data to send,
! 671: * and BSY is still active.
! 672: */
! 673: __asm__ ("
1.1 root 674:
675: /*
676: Local variables :
677: len = ecx
678: data = esi
679: st0x_cr_sr = ebx
680: st0x_dr = edi
681:
682: Test for any data here at all.
683: */
684: movl %0, %%esi /* local value of data */
685: movl %1, %%ecx /* local value of len */
686: orl %%ecx, %%ecx
687: jz 2f
688:
689: cld
690:
691: movl _st0x_cr_sr, %%ebx
692: movl _st0x_dr, %%edi
693:
694: 1: movb (%%ebx), %%al
695: /*
696: Test for BSY
697: */
698:
699: test $1, %%al
700: jz 2f
701:
702: /*
703: Test for data out phase - STATUS & REQ_MASK should be REQ_DATAOUT, which is 0.
704: */
705: test $0xe, %%al
706: jnz 2f
707: /*
708: Test for REQ
709: */
710: test $0x10, %%al
711: jz 1b
712: lodsb
713: movb %%al, (%%edi)
714: loop 1b
715:
716: 2:
717: movl %%esi, %2
718: movl %%ecx, %3
719: ":
720: /* output */
721: "=r" (data), "=r" (len) :
722: /* input */
723: "0" (data), "1" (len) :
724: /* clobbered */
725: "ebx", "ecx", "edi", "esi");
726:
1.1.1.2 ! root 727: break;
1.1 root 728:
1.1.1.2 ! root 729: case REQ_DATAIN :
! 730: /*
! 731: * We loop as long as we are in a data in phase, there is room to read,
! 732: * and BSY is still active
! 733: */
1.1 root 734:
1.1.1.2 ! root 735: __asm__ ("
1.1 root 736: /*
737: Local variables :
738: ecx = len
739: edi = data
740: esi = st0x_cr_sr
741: ebx = st0x_dr
742:
743: Test for room to read
744: */
745:
746: movl %0, %%edi /* data */
747: movl %1, %%ecx /* len */
748: orl %%ecx, %%ecx
749: jz 2f
750:
751: cld
752: movl _st0x_cr_sr, %%esi
753: movl _st0x_dr, %%ebx
754:
755: 1: movb (%%esi), %%al
756: /*
757: Test for BSY
758: */
759:
760: test $1, %%al
761: jz 2f
762:
763: /*
764: Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4.
765: */
766: movb $0xe, %%ah
767: andb %%al, %%ah
768: cmpb $0x04, %%ah
769: jne 2f
770:
771: /*
772: Test for REQ
773: */
774: test $0x10, %%al
775: jz 1b
776:
777: movb (%%ebx), %%al
778: stosb
779: loop 1b
780:
781: 2: movl %%edi, %2 /* data */
782: movl %%ecx, %3 /* len */
783: ":
784: /* output */
785: "=r" (data), "=r" (len) :
786: /* input */
787: "0" (data), "1" (len) :
788: /* clobbered */
789: "ebx", "ecx", "edi", "esi");
1.1.1.2 ! root 790: break;
1.1 root 791:
1.1.1.2 ! root 792: case REQ_CMDOUT :
! 793: while (((status_read = STATUS) & STAT_BSY) &&
! 794: ((status_read & REQ_MASK) == REQ_CMDOUT))
! 795: if (status_read & STAT_REQ)
! 796: DATA = *(unsigned char *) cmnd ++;
! 797: break;
! 798:
! 799: case REQ_STATIN :
! 800: status = DATA;
! 801: break;
! 802:
! 803: case REQ_MSGOUT :
! 804: /*
! 805: * We can only have sent a MSG OUT if we requested to do this
! 806: * by raising ATTN. So, we must drop ATTN.
! 807: */
! 808:
! 809: CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
! 810: /*
! 811: * If we are reconecting, then we must send an IDENTIFY message in
! 812: * response to MSGOUT.
! 813: */
! 814: if (reselect)
! 815: {
! 816: DATA = IDENTIFY(1,0);
! 817: #if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT))
! 818: printk("scsi%d : sent IDENTIFY message.\n", hostno);
! 819: #endif
! 820: }
! 821: else
! 822: {
! 823: DATA = MESSAGE_REJECT;
1.1 root 824:
1.1.1.2 ! root 825: #if (DEBUG & PHASE_MSGOUT)
! 826: printk("scsi%d : sent MESSAGE REJECT message.\n", hostno);
! 827: #endif
! 828: }
! 829: break;
1.1 root 830:
1.1.1.2 ! root 831: case REQ_MSGIN :
! 832: switch (message = DATA)
! 833: {
! 834: case DISCONNECT :
! 835: should_reconnect = 1;
! 836: current_data = data; /* WDE add */
! 837: current_bufflen = len; /* WDE add */
! 838: #if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))
! 839: printk("scsi%d : disconnected.\n", hostno);
! 840: done=1;
! 841: break;
! 842: #endif
! 843: case COMMAND_COMPLETE :
! 844: #if (DEBUG & PHASE_MSGIN)
! 845: printk("scsi%d : command complete.\n", hostno);
! 846: done=1;
! 847: break;
! 848: #endif
! 849: case ABORT :
! 850: #if (DEBUG & PHASE_MSGIN)
! 851: printk("scsi%d : abort message.\n", hostno);
! 852: #endif
! 853: done=1;
! 854: break;
! 855: case SAVE_POINTERS :
! 856: current_data = data; /* WDE mod */
! 857: current_bufflen = len; /* WDE add */
! 858: #if (DEBUG & PHASE_MSGIN)
! 859: printk("scsi%d : pointers saved.\n", hostno);
! 860: #endif
! 861: break;
! 862: case RESTORE_POINTERS:
! 863: data=current_data; /* WDE mod */
! 864: cmnd=current_cmnd;
! 865: #if (DEBUG & PHASE_MSGIN)
! 866: printk("scsi%d : pointers restored.\n", hostno);
! 867: #endif
! 868: break;
! 869: default:
1.1 root 870:
1.1.1.2 ! root 871: /*
! 872: * IDENTIFY distinguishes itself from the other messages by setting the
! 873: * high byte.
! 874: */
! 875:
! 876: if (message & 0x80)
! 877: {
! 878: #if (DEBUG & PHASE_MSGIN)
! 879: printk("scsi%d : IDENTIFY message received from id %d, lun %d.\n",
! 880: hostno, target, message & 7);
! 881: #endif
1.1 root 882: }
1.1.1.2 ! root 883: else
! 884: {
! 885:
! 886: #if (DEBUG & PHASE_MSGIN)
! 887: printk("scsi%d : unknown message %d from target %d.\n",
! 888: hostno, message, target);
! 889: #endif
! 890: }
! 891: }
! 892: break;
1.1 root 893:
1.1.1.2 ! root 894: default :
! 895: printk("scsi%d : unknown phase.\n", hostno);
! 896: st0x_aborted = DID_ERROR;
! 897: }
! 898: } /* while ends */
! 899: } /* if ends */
1.1 root 900:
901: #if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
902: printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len);
903: #endif
904:
905: #if (DEBUG & PHASE_EXIT)
1.1.1.2 ! root 906: printk("Buffer : \n");
! 907: for (i = 0; i < 20; ++i)
! 908: printk ("%02x ", ((unsigned char *) data)[i]); /* WDE mod */
! 909: printk("\n");
! 910: printk("Status = %02x, message = %02x\n", status, message);
1.1 root 911: #endif
912:
913:
1.1.1.2 ! root 914: if (st0x_aborted)
! 915: {
! 916: if (STATUS & STAT_BSY)
1.1 root 917: {
1.1.1.2 ! root 918: seagate_st0x_reset();
! 919: st0x_aborted = DID_RESET;
! 920: }
! 921: abort_confirm = 1;
! 922: }
1.1 root 923:
1.1.1.2 ! root 924: if (should_reconnect)
! 925: {
! 926: #if (DEBUG & PHASE_RESELECT)
! 927: printk("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n",
! 928: hostno);
1.1 root 929: #endif
1.1.1.2 ! root 930: do_seagate = seagate_reconnect_intr;
! 931: CONTROL = BASE_CMD | CMD_INTR ;
! 932: }
! 933: else
! 934: CONTROL = BASE_CMD;
1.1 root 935:
1.1.1.2 ! root 936: return retcode (st0x_aborted);
1.1 root 937: }
938:
939: int seagate_st0x_abort (int code)
940: {
941: if (code)
942: st0x_aborted = code;
943: else
944: st0x_aborted = DID_ABORT;
945:
946: return 0;
947: }
948:
949: /*
950: the seagate_st0x_reset function resets the SCSI bus
951: */
952:
953: int seagate_st0x_reset (void)
954: {
955: unsigned clock;
956: /*
957: No timeouts - this command is going to fail because
958: it was reset.
959: */
960:
961: #ifdef DEBUG
962: printk("In seagate_st0x_reset()\n");
963: #endif
964:
965:
966: /* assert RESET signal on SCSI bus. */
967:
968: CONTROL = BASE_CMD | CMD_RST;
969: clock=jiffies+2;
970:
971:
972: /* Wait. */
973:
974: while (jiffies < clock);
975:
976: CONTROL = BASE_CMD;
977:
978: st0x_aborted = DID_RESET;
979:
980: #ifdef DEBUG
981: printk("SCSI bus reset.\n");
982: #endif
983: return 0;
984: }
1.1.1.2 ! root 985:
1.1 root 986: #endif
1.1.1.2 ! root 987:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.