|
|
1.1 ! root 1: /* ! 2: * Device driver for Seagate ST01/ST02 scsi host adapters. ! 3: * ! 4: * To do: ! 5: * nonzero LUN's ! 6: * start new command during disconnect ! 7: * rewrite as single state machine, instead of 7 of them ! 8: * separate SCSI layer from host-dependent stuff ! 9: * ! 10: * $Log: ss.c,v $ ! 11: * Revision 2.17 91/11/12 07:49:26 bin ! 12: * 3204 kernel source for use with piggy's tboot code ! 13: * ! 14: * Revision 3.5 91/11/11 12:31:26 hal ! 15: * Translation-mode parameters from tboot. ! 16: * ! 17: * Revision 3.4 91/11/05 16:02:25 hal ! 18: * Allow access to WHOLE_DRIVE even if no partition table. ! 19: * Delete lbolt test code. ! 20: * ! 21: * Revision 3.3 91/06/21 10:46:27 hal ! 22: * Now talks to TMC-881 + ST4350N. ! 23: * ! 24: * Revision 3.2 91/06/20 17:10:32 hal ! 25: * First version for TMC-881. ! 26: * ! 27: * Revision 3.1 91/06/17 07:43:25 hal ! 28: * Add TMC-840 code. ! 29: * ! 30: * Revision 1.1 91/06/17 07:42:27 hal ! 31: * Add TMC-840 code. ! 32: * ! 33: * ! 34: */ ! 35: ! 36: /* ! 37: * Debug levels. ! 38: * DEBUG = 0 No debug output. ! 39: * DEBUG = 1 Debug output on error only. ! 40: * DEBUG = 2 Debug output on error and at other selected places. ! 41: * DEBUG = 3 Print state machine trace. ! 42: * DEBUG = 4 Print info xfer phases and msg_in values. ! 43: */ ! 44: #if (DEBUG >= 1) ! 45: static int s_id; ! 46: #define PR1(str) printf("%s%d ", str, s_id) ! 47: #else ! 48: #define PR1(str) ! 49: #endif ! 50: #if (DEBUG >= 2) ! 51: #define PR2(str) printf(str) ! 52: #else ! 53: #define PR2(str) ! 54: #endif ! 55: #if (DEBUG >= 3) ! 56: #define PR3(str) printf("%s%d ", str, s_id) ! 57: #else ! 58: #define PR3(str) ! 59: #endif ! 60: #if (DEBUG >= 4) ! 61: #define PR4(str) printf("%s%d ", str, s_id) ! 62: #else ! 63: #define PR4(str) ! 64: #endif ! 65: ! 66: /* ! 67: * Includes. ! 68: */ ! 69: #include <sys/coherent.h> ! 70: #include <sys/io.h> ! 71: #include <sys/sched.h> ! 72: #include <sys/uproc.h> ! 73: #include <sys/proc.h> ! 74: #include <sys/con.h> ! 75: #include <sys/stat.h> ! 76: #include <sys/devices.h> /* SCSI_MAJOR */ ! 77: #include <errno.h> ! 78: #include <sys/fdisk.h> ! 79: #include <sys/hdioctl.h> ! 80: #include <sys/buf.h> ! 81: #include <sys/scsiwork.h> ! 82: #include <sys/typed.h> ! 83: ! 84: /* ! 85: * Definitions. ! 86: * Constants. ! 87: * Macros with argument lists. ! 88: * Typedefs. ! 89: * Enums. ! 90: */ ! 91: #define SS_RAM 0x1800 /* Offset of parameter RAM */ ! 92: ! 93: /* Future Domain */ ! 94: #define FD_CSR 0x1C00 /* Offset of control/status register */ ! 95: #define FD_DAT 0x1E00 /* Offset of data port */ ! 96: ! 97: /* Seagate */ ! 98: #define SS_CSR 0x1A00 /* Offset of control/status register */ ! 99: #define SS_DAT 0x1C00 /* Offset of data port */ ! 100: ! 101: #define SS_RAM_LEN 128 /* ST0x has 128 bytes of RAM */ ! 102: #define SS_DAT_LEN 0x400 /* Byte range mapped to data port */ ! 103: #define SS_SEL_LEN 0x2000 /* Total size of memory-mapped area */ ! 104: ! 105: #define WC_ENABLE_SCSI 0x80 /* Write Control (WC) register bits */ ! 106: #define WC_ENABLE_IRPT 0x40 ! 107: #define WC_ENABLE_PRTY 0x20 ! 108: #define WC_ARBITRATE 0x10 ! 109: #define WC_ATTENTION 0x08 ! 110: #define WC_BUSY 0x04 ! 111: #define WC_SELECT 0x02 ! 112: #define WC_SCSI_RESET 0x01 ! 113: ! 114: #define RS_ARBIT_COMPL 0x80 /* Read STATUS (RS) register bits */ ! 115: #define RS_PRTY_ERROR 0x40 ! 116: #define RS_SELECT 0x20 ! 117: #define RS_REQUEST 0x10 ! 118: #define RS_CTRL_DATA 0x08 ! 119: #define RS_I_O 0x04 ! 120: #define RS_MESSAGE 0x02 ! 121: #define RS_BUSY 0x01 ! 122: ! 123: #define DEV_SCSI_ID(dev) ((dev >> 4) & 0x0007) ! 124: #define DEV_LUN(dev) ((dev >> 2) & 0x0003) ! 125: #define DEV_DRIVE(dev) ((dev >> 2) & 0x001F) ! 126: #define DEV_PARTN(dev) (dev & 0x0003) ! 127: #define DEV_SPECIAL(dev) (dev & 0x0080) ! 128: ! 129: #define HIPRI_RETRIES 5000 /* # of times to retry while hogging CPU */ ! 130: #define LOPRI_RETRIES 5 /* # of retries with sleep between tries */ ! 131: #define WHOLE_DRIVE NPARTN ! 132: #define RESET_TICKS 50 /* # of clock ticks for reset settling */ ! 133: #define LOAD_DELAY 30000 /* Loop counter during ssload() only */ ! 134: ! 135: #define BUS_FREE ((ffbyte(ss_csr) & (RS_BUSY | RS_SELECT)) == 0) ! 136: #define TGT_RSEL \ ! 137: ( (ffbyte(ss_csr) & (RS_SELECT | RS_I_O )) \ ! 138: && (ffbyte(ss_dat) & (host_id | (1<<s_id) )) ) ! 139: ! 140: #define DELAY_ARB 10 /* delays units are 10 msec (clock ticks) */ ! 141: #define DELAY_BDR 30 ! 142: #define DELAY_BSY 20 ! 143: #define DELAY_RES 50 ! 144: #define DELAY_RST 40 ! 145: ! 146: #define MAX_AVL_COUNT 100 ! 147: #define MAX_BDR_COUNT 3 ! 148: #define MAX_BSY_COUNT 3 ! 149: #define MAX_TRY_COUNT 10 ! 150: #define INL_MAX_REQ_POLL 800000L ! 151: #define WKG_MAX_REQ_POLL 20000L ! 152: ! 153: typedef unsigned char uchar; ! 154: typedef unsigned int uint; ! 155: typedef unsigned long ulong; ! 156: ! 157: typedef enum { /* values for current driver state */ ! 158: SST_DEQUEUE =0, ! 159: SST_BUS_DEV_RESET, ! 160: SST_HIPRI_RESET, ! 161: SST_LOPRI_RESET, ! 162: SST_POLL_ARBITN, ! 163: SST_POLL_BEGIN_IO, ! 164: SST_POLL_RESELECT, ! 165: SST_REQ_SENSE, ! 166: SST_RESET_OFF ! 167: } SST_TYPE; ! 168: ! 169: typedef enum { /* values for input to recovery routine */ ! 170: RV_A_TIMEOUT, ! 171: RV_P_TIMEOUT, ! 172: RV_R_TIMEOUT, ! 173: RV_BF_TIMEOUT, ! 174: RV_CS_BUSY, ! 175: RV_CS_CHECK ! 176: } RV_TYPE; ! 177: ! 178: typedef struct ss { ! 179: ulong capacity; ! 180: ulong blocklen; ! 181: ulong bno; ! 182: int msg_in; ! 183: int dr_watch; ! 184: uchar cmdbuf[G1CMDLEN]; ! 185: int cmdlen; ! 186: int cmd_bytes_out; ! 187: int cmdstat; ! 188: BUF *bp; /* current I/O request node, or NULL */ ! 189: struct fdisk_s parmp[NPARTN+1]; ! 190: SST_TYPE state; ! 191: TIM tim; /* for target-specific timers */ ! 192: uchar avl_count; ! 193: uchar bdr_count; ! 194: uchar bsy_count; ! 195: uchar try_count; ! 196: uint busy:1; /* 1 if command uses local buffer */ ! 197: uint expired:1; /* 1 if target's timer has expired */ ! 198: uint ptab_read:1; /* 1 if partition table has been read */ ! 199: uint waiting:1; /* 1 if target timer is running */ ! 200: } ss_type; ! 201: ! 202: typedef struct { ! 203: uint ncyl; ! 204: uchar nhead; ! 205: uchar nspt; ! 206: } drv_parm_type; ! 207: ! 208: /* ! 209: * Functions. ! 210: * Import Functions. ! 211: * Export Functions. ! 212: * Local Functions. ! 213: */ ! 214: ! 215: /* functions from bufq.c */ ! 216: extern int bufq_init(); ! 217: extern void bufq_rlse(); ! 218: extern void bufq_wr_tail(); ! 219: extern BUF * bufq_rd_head(); ! 220: extern BUF * bufq_rm_head(); ! 221: ! 222: /* functions from ssas.s */ ! 223: extern void ss_get(); ! 224: extern int ss_put(); ! 225: extern int nulldev(); ! 226: extern int nonedev(); ! 227: extern unsigned char ffbyte(); ! 228: ! 229: static void ssopen(); /* CON functions */ ! 230: static void ssclose(); ! 231: static void ssblock(); ! 232: static void ssread(); ! 233: static void sswrite(); ! 234: static int ssioctl(); ! 235: static void sswatch(); ! 236: static void ssload(); ! 237: static void ssunload(); ! 238: ! 239: static int bus_dev_reset(); /* additional support functions */ ! 240: static int chk_reconn(); ! 241: static void do_connect(); ! 242: static void dummy_reconn(); ! 243: static int far_info_xfer(); ! 244: static int host_ident(); ! 245: static int init_call(); ! 246: static void init_pointers(); ! 247: static int inquiry(); ! 248: static int local_info_xfer(); ! 249: static int mode_sense(); ! 250: static void next_req(); ! 251: static void nonpolled(); ! 252: static int read_cap(); ! 253: static void recover(); ! 254: static int req_sense(); ! 255: static int rsel_handshake(); ! 256: static void ssdelay(); ! 257: static void ss_finished(); ! 258: static void ss_mach(); ! 259: static void set_timeout(); ! 260: static int ssinit(); ! 261: static void ssintr(); ! 262: static int start_arb(); ! 263: static void stop_timeout(); ! 264: static void tbparms(); ! 265: static uchar xpmod(); ! 266: ! 267: /* ! 268: * Global Data. ! 269: * Import Variables. ! 270: * Export Variables. ! 271: * Local Variables. ! 272: */ ! 273: extern short n_atdr; /* set by atcount() before any load routines run */ ! 274: ! 275: CON sscon = { ! 276: DFBLK|DFCHR, /* Flags */ ! 277: SCSI_MAJOR, /* Major index */ ! 278: ssopen, /* Open */ ! 279: ssclose, /* Close */ ! 280: ssblock, /* Block */ ! 281: ssread, /* Read */ ! 282: sswrite, /* Write */ ! 283: ssioctl, /* Ioctl */ ! 284: nulldev, /* Powerfail */ ! 285: sswatch, /* Timeout */ ! 286: ssload, /* Load */ ! 287: ssunload, /* Unload */ ! 288: nulldev /* Poll */ ! 289: }; ! 290: ! 291: /* Patch these Export Variables to configure the driver. */ ! 292: /* ! 293: * In the low byte of NSDRIVE, bit n is 1 if SCSI ID n is an installed target. ! 294: * The high byte indicates which type of host adapter: ! 295: * 00 - ST01/ST02 ! 296: * 80 - TMC-845/850/860/875/885 ! 297: * 40 - TMC-840/841/880/881 ! 298: */ ! 299: uint NSDRIVE = 0x0000; ! 300: uint SS_INT = 5; /* ST0[12] use either IRQ3 or IRQ5 */ ! 301: uint SS_BASE = 0xCA00; /* Segment addr of ST0x communication area */ ! 302: ! 303: /* ncyl, nhead, nspt */ ! 304: drv_parm_type drv_parm[MAX_SCSI_ID] = { ! 305: { 0, 0, 0}, ! 306: { 0, 0, 0}, ! 307: { 0, 0, 0}, ! 308: { 0, 0, 0}, ! 309: { 0, 0, 0}, ! 310: { 0, 0, 0}, ! 311: { 0, 0, 0} ! 312: }; ! 313: ! 314: static BUF dbuf; /* For raw I/O */ ! 315: static paddr_t ss_base; /* physical address of ST0x comm area */ ! 316: static faddr_t ss_fp; /* (far *) to ST0x comm area */ ! 317: ! 318: static faddr_t ss_ram; /* (far *) to parameter RAM */ ! 319: static faddr_t ss_csr; /* (far *) to control/status */ ! 320: static faddr_t ss_dat; /* (far *) to data port */ ! 321: ! 322: static TIM delay_tim; /* needed for calls to ssdelay() */ ! 323: static int do_sst_op; /* 1 when state machine iteration continues */ ! 324: static int ss_expired; /* 1 after local timeout */ ! 325: ! 326: static uint max_req_poll; /* this changes after initialization */ ! 327: ! 328: static uchar host_id; /* Host is SCSI ID #7 for Seagate, 6 for FD */ ! 329: static uchar swap_status_bits; ! 330: ! 331: static ss_type *ss_tbl; /* points to block of "ss" structs */ ! 332: static ss_type *ss[MAX_SCSI_ID]; ! 333: ! 334: /* ! 335: * host_claimed is -1 if host is available, else it's the SCSI id of the ! 336: * target that claims the host. ! 337: * ! 338: * host is claimed at start of any of the follwoing: ! 339: * SCSI bus reset ! 340: * arbitration for block i/o request ! 341: * reselect ! 342: * ! 343: * host is released at: ! 344: * end of SCSI bus reset ! 345: * completion (successful or not) of block i/o request (ss_finished) ! 346: * disconnect <-- temporarily disabled ! 347: */ ! 348: static int host_claimed; ! 349: ! 350: /* ! 351: * ssload() - load routine. ! 352: * ! 353: * Action: The controller is reset and the interrupt vector is grabbed. ! 354: * The drive characteristics are set up at this time. ! 355: */ ! 356: static void ssload() ! 357: { ! 358: int erf = 0; /* 1 if error occurs */ ! 359: int i; ! 360: int max_id = -1; ! 361: int num_drives = 0; ! 362: int tbnum; ! 363: ! 364: /* ! 365: * Allocate a selector to map into ST0x memory-mapped comm area. ! 366: */ ! 367: ss_base = (paddr_t)((long)(unsigned)SS_BASE << 4); ! 368: ss_fp = ptov(ss_base, (fsize_t)SS_SEL_LEN); ! 369: ! 370: ss_ram = ss_fp + SS_RAM; ! 371: ! 372: /* ! 373: * Primitive test of ST0x RAM. ! 374: */ ! 375: sfword(ss_ram, 0xA55A); ! 376: sfword(ss_ram + 2, 0x3CC3); ! 377: sfword(ss_ram + SS_RAM_LEN - 4, 0xA55A); ! 378: sfword(ss_ram + SS_RAM_LEN - 2, 0x3CC3); ! 379: if (ffword(ss_ram) != 0xA55A /* fetch a "far" word */ ! 380: || ffword(ss_ram + 2) != 0x3CC3 ! 381: || ffword(ss_ram + SS_RAM_LEN - 4) != 0xA55A ! 382: || ffword(ss_ram + SS_RAM_LEN - 2) != 0x3CC3) { ! 383: printf("Error - host failed memory test\n"); ! 384: erf = 1; ! 385: } ! 386: ! 387: /* ! 388: * Set host-dependent constants. ! 389: */ ! 390: switch(NSDRIVE >> 8) { ! 391: case 0x00: /* ST01/ST02 */ ! 392: ss_csr = ss_fp + SS_CSR; ! 393: ss_dat = ss_fp + SS_DAT; ! 394: host_id = 0x80; /* host is id #7 */ ! 395: break; ! 396: case 0x80: /* TMC-845/850/860/875/885 */ ! 397: ss_csr = ss_fp + FD_CSR; ! 398: ss_dat = ss_fp + FD_DAT; ! 399: host_id = 0x40; /* host is id #6 */ ! 400: break; ! 401: case 0x40: /* TMC-840/841/880/881 */ ! 402: ss_csr = ss_fp + SS_CSR; ! 403: ss_dat = ss_fp + SS_DAT; ! 404: host_id = 0x40; /* host is id #6 */ ! 405: swap_status_bits = 1; ! 406: break; ! 407: } ! 408: NSDRIVE &= ~(uint)host_id; ! 409: ! 410: /* ! 411: * Allocate drive structs. ! 412: * ! 413: * Do a single call to kalloc() then put allocated pieces into ! 414: * array ss. ! 415: * ! 416: * First allocate and clear storage. Then hook up the pointers. ! 417: */ ! 418: if (!erf) { ! 419: for (i = 0; i < MAX_SCSI_ID; i++) ! 420: if ((NSDRIVE >> i) & 1) { ! 421: max_id = i; ! 422: num_drives++; ! 423: } ! 424: if (num_drives == 0) { ! 425: printf("Error - ss has no valid target id's\n"); ! 426: erf = 1; ! 427: } else if ((ss_tbl = kalloc(num_drives*sizeof(ss_type))) ! 428: == NULL) { ! 429: printf("Error - ss can't allocate structs\n"); ! 430: erf = 1; ! 431: } else ! 432: kclear(ss_tbl, num_drives * sizeof(ss_type)); ! 433: } ! 434: if (!erf) { ! 435: ss_type *foo = ss_tbl; ! 436: ! 437: for (i = 0; i < MAX_SCSI_ID; i++) ! 438: if ((NSDRIVE >> i) & 1) ! 439: ss[i] = foo++; ! 440: } ! 441: ! 442: /* ! 443: * Claim IRQ vector. ! 444: */ ! 445: setivec(SS_INT, ssintr); ! 446: ! 447: /* ! 448: * Initialize drives we know about (i.e. in NSDRIVE bitmap). ! 449: * ! 450: * Part of this is getting parameters from tboot, if any. ! 451: * The drive number in tboot's data block must be matched with ! 452: * the SCSI id in question. Drive numbering in tboot is assumed ! 453: * to start with any "at" drives (n_atdr counts these) ! 454: * then proceed with SCSI drives in increasing id number order. ! 455: */ ! 456: tbnum = n_atdr; /* tboot drive number for first SCSI drive */ ! 457: host_claimed = -1; ! 458: bufq_init(max_id + 1); ! 459: max_req_poll = INL_MAX_REQ_POLL; ! 460: if (!erf) { ! 461: for (i = 0; i < MAX_SCSI_ID; i++) ! 462: if ((NSDRIVE >> i) & 1) { ! 463: tbparms(tbnum, i); /* get tboot parms */ ! 464: ssinit(i); ! 465: tbnum++; ! 466: } ! 467: } ! 468: max_req_poll = WKG_MAX_REQ_POLL; ! 469: } ! 470: ! 471: /* ! 472: * ssunload() - unload routine. ! 473: */ ! 474: static void ssunload() ! 475: { ! 476: /* ! 477: * Deallocate driver heap space. ! 478: */ ! 479: if (ss_tbl) ! 480: kfree(ss_tbl); ! 481: bufq_rlse(); ! 482: ! 483: /* ! 484: * Free the ST0x selector. ! 485: */ ! 486: vrelse(ss_fp); ! 487: ! 488: /* ! 489: * Release IRQ vector. ! 490: */ ! 491: clrivec(SS_INT); ! 492: } ! 493: ! 494: /* ! 495: * ssopen() ! 496: * ! 497: * Input: dev = disk device to be opened. ! 498: * mode = access mode [IPR,IPW, IPR+IPW]. ! 499: * ! 500: * Action: Validate the minor device. ! 501: * Update the paritition table if necessary. ! 502: */ ! 503: static void ssopen(dev, mode) ! 504: register dev_t dev; ! 505: { ! 506: int drive, partn; ! 507: struct fdisk_s *fdp; ! 508: ss_type * ssp; ! 509: int s_id; ! 510: uchar * msg; ! 511: ! 512: /* ! 513: * Set up local variables. ! 514: */ ! 515: drive = DEV_SCSI_ID(dev); ! 516: partn = DEV_PARTN(dev); ! 517: s_id = DEV_SCSI_ID(dev); ! 518: ssp = ss[s_id]; ! 519: fdp = ssp->parmp; ! 520: ! 521: #if (DEBUG >= 3) ! 522: devmsg(dev, "ssopen"); ! 523: #endif ! 524: ! 525: /* ! 526: * LUN must be zero. ! 527: * SCSI id must have corresponding 1 in NSDRIVE bitmapped variable. ! 528: */ ! 529: if (DEV_LUN(dev) != 0 || ((1 << drive) & NSDRIVE) == 0) { ! 530: msg = "bad LUN or SCSI id"; ! 531: u.u_error = ENXIO; ! 532: goto bad_open; ! 533: } ! 534: ! 535: /* ! 536: * If "special" bit is set, partition field must be zero. ! 537: */ ! 538: if (DEV_SPECIAL(dev) && partn != 0) { ! 539: msg = "bad special partition"; ! 540: u.u_error = ENXIO; ! 541: goto bad_open; ! 542: } ! 543: ! 544: /* ! 545: * Subscripting gimmick for partition table. ! 546: */ ! 547: if (dev & SDEV) ! 548: partn = WHOLE_DRIVE; ! 549: ! 550: /* ! 551: * If not accessing whole drive and the partition table has not ! 552: * been read yet, try to read it now. ! 553: * Do this by calling fdisk() with partition table device on the drive ! 554: * that is being accessed. ! 555: */ ! 556: if (partn != WHOLE_DRIVE && !(ssp->ptab_read)) { ! 557: int fdisk_dev; ! 558: ! 559: fdisk_dev = (dev | SDEV) & 0xfff0; ! 560: ! 561: #if (DEBUG >=3) ! 562: devmsg(fdisk_dev, "calling fdisk"); ! 563: if (fdisk(fdisk_dev, fdp)) { ! 564: int p; ! 565: ! 566: fdp[WHOLE_DRIVE].p_size = ssp->capacity; ! 567: fdp[WHOLE_DRIVE].p_base = 0; ! 568: printf("fdisk() succeeded\n"); ! 569: for (p=0; p<=WHOLE_DRIVE; p++) ! 570: printf("p=%d base=%ld size=%ld\n", p, fdp[p].p_base, fdp[p].p_size); ! 571: ssp->ptab_read = 1; ! 572: } else { ! 573: printf("fdisk() failed\n"); ! 574: u.u_error = ENXIO; ! 575: goto bad_open; ! 576: } ! 577: #else ! 578: if (fdisk(fdisk_dev, fdp)) { ! 579: fdp[WHOLE_DRIVE].p_size = ssp->capacity; ! 580: fdp[WHOLE_DRIVE].p_base = 0; ! 581: ssp->ptab_read = 1; ! 582: } else { ! 583: msg = "bad partition table"; ! 584: u.u_error = ENXIO; ! 585: goto bad_open; ! 586: } ! 587: #endif ! 588: ! 589: } ! 590: ! 591: /* ! 592: * Ensure partition lies within drive boundaries and is non-zero size. ! 593: */ ! 594: if (partn != WHOLE_DRIVE ! 595: && (fdp[partn].p_base+fdp[partn].p_size) > fdp[WHOLE_DRIVE].p_size) { ! 596: msg = "partition exceeds drive capacity"; ! 597: u.u_error = EBADFMT; ! 598: goto bad_open; ! 599: } ! 600: ! 601: if (partn != WHOLE_DRIVE && fdp[partn].p_size == 0) { ! 602: msg = "partition not found"; ! 603: u.u_error = ENODEV; ! 604: goto bad_open; ! 605: } ! 606: ! 607: /* ! 608: * OK to open the device. ! 609: * Start watchdog timer (if not already started) for the host adapter. ! 610: */ ! 611: ++drvl[SCSI_MAJOR].d_time; ! 612: ++ssp->dr_watch; ! 613: goto end_open; ! 614: ! 615: bad_open: ! 616: devmsg(dev, msg); ! 617: end_open: ! 618: return; ! 619: } ! 620: ! 621: /* ! 622: * ssclose() ! 623: */ ! 624: static void ssclose(dev) ! 625: dev_t dev; ! 626: { ! 627: ss_type * ssp; ! 628: int s_id; ! 629: ! 630: s_id = DEV_SCSI_ID(dev); ! 631: ssp = ss[s_id]; ! 632: ! 633: /* ! 634: * Decrement the number of watchdog timer requests open for host ! 635: * adapter and for target. ! 636: */ ! 637: --drvl[SCSI_MAJOR].d_time; ! 638: --ssp->dr_watch; ! 639: ! 640: #if (DEBUG >= 3) ! 641: devmsg(dev, "ssclose"); ! 642: #endif ! 643: ! 644: } ! 645: ! 646: /* ! 647: * ssread() - read a block from the raw disk ! 648: * ! 649: * Input: dev = disk device to be written to. ! 650: * iop = pointer to source I/O structure. ! 651: * ! 652: * Action: Invoke the common raw I/O processing code. ! 653: */ ! 654: static void ssread(dev, iop) ! 655: dev_t dev; ! 656: IO *iop; ! 657: { ! 658: ioreq( &dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC ); ! 659: } ! 660: ! 661: /* ! 662: * sswrite() - write a block to the raw disk ! 663: * ! 664: * Input: dev = disk device to be written to. ! 665: * iop = pointer to source I/O structure. ! 666: * ! 667: * Action: Invoke the common raw I/O processing code. ! 668: */ ! 669: static void sswrite(dev, iop) ! 670: dev_t dev; ! 671: IO *iop; ! 672: { ! 673: ioreq( &dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC ); ! 674: } ! 675: ! 676: /* ! 677: * ssioctl() ! 678: * ! 679: * Input: dev = disk device to be operated on. ! 680: * cmd = input/output request to be performed. ! 681: * vec = (pointer to) optional argument. ! 682: */ ! 683: static int ssioctl(dev, cmd, vec) ! 684: register dev_t dev; ! 685: int cmd; ! 686: char * vec; ! 687: { ! 688: int ret = 0; ! 689: hdparm_t hdparm; ! 690: struct fdisk_s *fdp; ! 691: int s_id; ! 692: ss_type * ssp; ! 693: ! 694: s_id = DEV_SCSI_ID(dev); ! 695: ssp = ss[s_id]; ! 696: fdp = ssp->parmp; ! 697: ! 698: switch(cmd) { ! 699: case HDGETA: ! 700: /* ! 701: * Get hard disk attributes. ! 702: */ ! 703: PR3("HDGETA"); ! 704: fdp = ssp->parmp; ! 705: *(short *)&hdparm.landc[0] = ! 706: *(short *)&hdparm.ncyl[0] = drv_parm[s_id].ncyl; ! 707: hdparm.nhead = drv_parm[s_id].nhead; ! 708: hdparm.nspt = drv_parm[s_id].nspt; ! 709: #if (DEBUG >= 3) ! 710: printf("ncyl=%d nhead=%d nspt=%d\n", ! 711: hdparm.ncyl[0]+((int)hdparm.ncyl[1]<<8), (int)hdparm.nhead, (int)hdparm.nspt); ! 712: #endif ! 713: kucopy(&hdparm, vec, sizeof hdparm); ! 714: ret = 0; ! 715: break; ! 716: case HDSETA: ! 717: /* ! 718: * Set hard disk attributes. ! 719: */ ! 720: PR3("HDSETA"); ! 721: fdp = ssp->parmp; ! 722: ukcopy(vec, &hdparm, sizeof hdparm); ! 723: drv_parm[s_id].ncyl = *(short *)&hdparm.ncyl[0]; ! 724: drv_parm[s_id].nhead = hdparm.nhead; ! 725: drv_parm[s_id].nspt = hdparm.nspt; ! 726: #if (DEBUG >= 3) ! 727: printf("ncyl=%d nhead=%d nspt=%d\n", ! 728: hdparm.ncyl[0]+((int)hdparm.ncyl[1]<<8), (int)hdparm.nhead, (int)hdparm.nspt); ! 729: #endif ! 730: ret = 0; ! 731: break; ! 732: default: ! 733: u.u_error = EINVAL; ! 734: ret = -1; ! 735: } ! 736: ! 737: return ret; ! 738: } ! 739: ! 740: /* ! 741: * ssblock() - queue a block to the disk ! 742: * ! 743: * Input: bp = pointer to block to be queued. ! 744: * ! 745: * Action: Queue a block to the disk. ! 746: * Make sure that the transfer is within the disk partition. ! 747: */ ! 748: static void ssblock(bp) ! 749: register BUF *bp; ! 750: { ! 751: struct fdisk_s *fdp; ! 752: int partition, drive, s_id; ! 753: dev_t dev; ! 754: ss_type * ssp; ! 755: uchar * msg = NULL; ! 756: ! 757: /* ! 758: * Set up local variables. ! 759: */ ! 760: dev = bp->b_dev; ! 761: partition = DEV_PARTN(dev); ! 762: drive = DEV_DRIVE(dev); ! 763: s_id = DEV_SCSI_ID(dev); ! 764: ssp = ss[s_id]; ! 765: if (dev & SDEV) ! 766: partition = WHOLE_DRIVE; ! 767: fdp = ssp->parmp; ! 768: ! 769: bp->b_resid = bp->b_count; ! 770: #if (DEBUG >= 2) ! 771: if (bp->b_count != BSIZE) ! 772: printf("b_count=%d ", bp->b_count); ! 773: #endif ! 774: ! 775: /* ! 776: * Range check disk region. ! 777: */ ! 778: if (!(ssp->ptab_read)) { ! 779: if ( partition == WHOLE_DRIVE ) { ! 780: #if 0 ! 781: /* Why did we only allow people to access the first block of WHOLE_DRIVE? ! 782: in cases where there was not a valid partition table? */ ! 783: if ((bp->b_bno != 0) || (bp->b_count != BSIZE)) { ! 784: msg = "invalid request"; ! 785: bp->b_flag |= BFERR; ! 786: goto bad_blk; ! 787: } ! 788: #endif ! 789: } else { ! 790: msg = "no partition table"; ! 791: bp->b_flag |= BFERR; ! 792: goto bad_blk; ! 793: } ! 794: } ! 795: ! 796: /* ! 797: * Check for read at end of partition. ! 798: * (Need to return with b_resid = BSIZE to signal end of volume.) ! 799: */ ! 800: else if ((bp->b_req == BREAD) && (bp->b_bno == fdp[partition].p_size)) { ! 801: goto bad_blk; ! 802: } ! 803: ! 804: /* ! 805: * Check for read past end of partition. ! 806: */ ! 807: else if ( (bp->b_bno + (bp->b_count/BSIZE)) ! 808: > fdp[partition].p_size ) { ! 809: msg = "partition overrun"; ! 810: bp->b_flag |= BFERR; ! 811: goto bad_blk; ! 812: } ! 813: ! 814: /* ! 815: * Fail if request is for zero bytes or is not even # of blocks. ! 816: */ ! 817: if ((bp->b_count % BSIZE) || bp->b_count == 0) { ! 818: msg = "invalid byte count"; ! 819: bp->b_flag |= BFERR; ! 820: goto bad_blk; ! 821: } ! 822: ! 823: /* ! 824: * Operation appears valid. ! 825: * Fill fields in the node and queue the request. ! 826: */ ! 827: bufq_wr_tail(s_id, bp); ! 828: ss_mach(s_id); ! 829: goto end_blk; ! 830: ! 831: /* ! 832: * Operation cannot be done. Release the kernel buffer structure. ! 833: * Value of "bp->b_flag" tells caller if error occurred. ! 834: */ ! 835: bad_blk: ! 836: if (msg) ! 837: devmsg(dev, msg); ! 838: bdone(bp); ! 839: ! 840: end_blk: ! 841: return; ! 842: } ! 843: ! 844: /* ! 845: * ssintr() - Interrupt routine. ! 846: * ! 847: * If we have been reselected by a recognized target device ! 848: * let kernel get out of interrupt mode (defer) and do SCSI ! 849: * reconnect stuff. ! 850: */ ! 851: static void ssintr() ! 852: { ! 853: int s_id; ! 854: ! 855: s_id = chk_reconn(); ! 856: if (s_id != -1) { ! 857: if (ss[s_id]->state == SST_POLL_RESELECT) ! 858: defer(ss_mach, s_id); ! 859: else ! 860: defer(dummy_reconn, s_id); ! 861: PR3("!"); ! 862: } ! 863: } ! 864: ! 865: /* ! 866: * dummy_reconn() ! 867: * ! 868: * Somehow we are in a state where the driver software does not expect ! 869: * a reconnect but a device is trying one anyway. Go thru the motions ! 870: * of reconnect because not servicing a hanging reselect seems to leave ! 871: * the target hung - in such a way that it fails to respond to reset ! 872: * messages and to reset on the SCSI bus. ! 873: */ ! 874: static void dummy_reconn(s_id) ! 875: int s_id; ! 876: { ! 877: int bus_timeout; ! 878: uchar phase_type; ! 879: int s; ! 880: int msg_in; ! 881: int cmdstat; ! 882: int xfer_good = 1; ! 883: PR1("DUM"); ! 884: if (ss[s_id]->state == SST_POLL_RESELECT) { ! 885: defer(ss_mach, s_id); ! 886: goto dum_done; ! 887: } ! 888: if (!rsel_handshake()) ! 889: goto dum_done; ! 890: ! 891: s = sphi(); ! 892: while (req_wait(&bus_timeout) && xfer_good) { ! 893: phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA); ! 894: switch (xpmod(phase_type)) { ! 895: case XP_MSG_IN: ! 896: msg_in = ffbyte(ss_dat); ! 897: switch(msg_in){ ! 898: case MSG_CMD_CMPLT: ! 899: case MSG_DISCONNECT: ! 900: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT); ! 901: break; ! 902: } ! 903: break; ! 904: case XP_MSG_OUT: ! 905: sfbyte(ss_dat, MSG_NOP); ! 906: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI); ! 907: break; ! 908: case XP_STAT_IN: ! 909: cmdstat = ffbyte(ss_dat); ! 910: break; ! 911: case XP_CMD_OUT: ! 912: case XP_DATA_OUT: ! 913: xfer_good = 0; ! 914: break; ! 915: case XP_DATA_IN: ! 916: ffbyte(ss_dat); ! 917: break; ! 918: default: ! 919: break; ! 920: } /* endswitch */ ! 921: } /* endwhile */ ! 922: spl(s); ! 923: ! 924: dum_done: ! 925: return; ! 926: } ! 927: ! 928: /* ! 929: * sswatch() ! 930: * ! 931: * Invoked once per second if any devices going through this driver are open. ! 932: * Poll for any reselect, in case interrupt got lost. ! 933: */ ! 934: static void sswatch() ! 935: { ! 936: int s_id; ! 937: ss_type * ssp; ! 938: ! 939: for (s_id = 0; s_id < MAX_SCSI_ID; s_id++) { ! 940: ssp = ss[s_id]; ! 941: if (ssp && ssp->dr_watch) ! 942: defer(ss_mach, s_id); ! 943: } /* endfor */ ! 944: } ! 945: ! 946: /* ! 947: * bus_wait() ! 948: * ! 949: * Wait for specified bit values to appear in Status Register. ! 950: * This uses a tight loop and does not expect to be interrupted. ! 951: * ! 952: * Argument "flags" is a double-byte value; the high byte is ANDed with ! 953: * status register contents, and the result is tested for equality with ! 954: * the low byte. ! 955: * ! 956: * Return 1 if values wanted appeared, 0 if timeout occurred. ! 957: */ ! 958: static int bus_wait(flags) ! 959: unsigned short flags; ! 960: { ! 961: int found, i; ! 962: unsigned char status; ! 963: ! 964: found = 0; ! 965: for ( i = 0; i < HIPRI_RETRIES; i++) { ! 966: status = ffbyte(ss_csr); ! 967: if ((status & (flags >> 8)) == (flags & 0xff)) { ! 968: found = 1; ! 969: break; ! 970: } ! 971: } ! 972: ! 973: #if (DEBUG >= 1) ! 974: if (!found) ! 975: printf("TO:f=%x s=%x ", flags, status); ! 976: #endif ! 977: ! 978: return found; ! 979: } ! 980: ! 981: /* ! 982: * ssinit() ! 983: * ! 984: * Attempt to initialize the (unique) drive with a given SCSI id. ! 985: * Assume only one drive per SCSI id, having LUN = 0. ! 986: * ! 987: * Return 1 if success, 0 if failure. ! 988: */ ! 989: static int ssinit(s_id) ! 990: int s_id; ! 991: { ! 992: int retval = 1; ! 993: uchar query_buf[MODESENSELEN]; ! 994: ss_type * ssp = ss[s_id]; ! 995: int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4)); ! 996: ! 997: printf("SCSI ID %d LUN 0\n", s_id); ! 998: if (retval) ! 999: if (init_call(inquiry, s_id, query_buf)) { ! 1000: query_buf[INQUIRYLEN] = 0; ! 1001: #if (debug >= 2) ! 1002: devmsg(dev, query_buf + 8); ! 1003: #endif ! 1004: if (query_buf[0] == 0) { ! 1005: retval = 1; ! 1006: } else ! 1007: devmsg(dev, "Not Direct Access Device"); ! 1008: } else ! 1009: devmsg(dev, "Inquiry Failed"); ! 1010: ! 1011: if (retval) ! 1012: if (init_call(read_cap, s_id, query_buf)) { ! 1013: retval = 1; ! 1014: ssp->capacity = query_buf[3] | (query_buf[2] << 8) ! 1015: | (((long)(query_buf[1])) << 16) ! 1016: | (((long)(query_buf[0])) << 24); ! 1017: ssp->blocklen = query_buf[7] | (query_buf[6] << 8) ! 1018: | (((long)(query_buf[5])) << 16) ! 1019: | (((long)(query_buf[4])) << 24); ! 1020: ! 1021: printf("Capacity=%ld blocks Block length=%ld\n", ! 1022: ssp->capacity, ssp->blocklen); ! 1023: } else ! 1024: devmsg(dev, "Read Capacity Failed"); ! 1025: ! 1026: if (retval) ! 1027: if (init_call(mode_sense, s_id, query_buf)) { ! 1028: /* ! 1029: * Display physical drive parameters. ! 1030: */ ! 1031: #define FMT_PG (4+8+8+12) ! 1032: #define DDG_PG (4+8+8+12+24) ! 1033: uchar heads; ! 1034: unsigned short spt; ! 1035: ulong cyls; ! 1036: ! 1037: spt=((int)query_buf[FMT_PG+10]<<8) ! 1038: + query_buf[FMT_PG+11]; ! 1039: cyls=((int)query_buf[DDG_PG+2]<<16) ! 1040: + ((int)query_buf[DDG_PG+3]<<8) ! 1041: + query_buf[DDG_PG+4]; ! 1042: heads=query_buf[DDG_PG+5]; ! 1043: ! 1044: printf("Physical: cylinders=%ld ", cyls); ! 1045: printf("heads=%d ", heads); ! 1046: printf("spt=%d\n", spt); ! 1047: ! 1048: if (drv_parm[s_id].ncyl == 0) { ! 1049: drv_parm[s_id].ncyl = cyls; ! 1050: drv_parm[s_id].nhead = heads; ! 1051: drv_parm[s_id].nspt = spt; ! 1052: } else { ! 1053: printf("Logical: cylinders=%d ", ! 1054: drv_parm[s_id].ncyl); ! 1055: printf("heads=%d ", drv_parm[s_id].nhead); ! 1056: printf("spt=%d\n", drv_parm[s_id].nspt); ! 1057: } ! 1058: } else ! 1059: devmsg(dev, "Mode Sense Failed"); ! 1060: ! 1061: return retval; ! 1062: } ! 1063: ! 1064: /* ! 1065: * far_info_xfer() ! 1066: * ! 1067: * Do bus cycle information transfer phases. ! 1068: * This includes message in/out, command in/out, and data in/out. ! 1069: * ! 1070: * If cmdlen is nonzero, cmdbuf is an array of bytes of that length, ! 1071: * to be sent to the target. ! 1072: * ! 1073: * Return 1 if bus timeout did not occur, else 0. ! 1074: * ! 1075: * pseudocode: ! 1076: * ! 1077: * while (wait for REQ true or BUSY false on SCSI bus) ! 1078: * if (BUSY false) ! 1079: * break from while loop ! 1080: * else ! 1081: * switch (xfer phase = RS_CTRL_DATA|RS_I_O|RS_MESSAGE) ! 1082: * case XP_MSG_IN/XP_MSG_OUT/... ! 1083: * handle the indicated information transfer phase ! 1084: * endswitch ! 1085: * endif ! 1086: * endwhile ! 1087: */ ! 1088: static int far_info_xfer(s_id) ! 1089: int s_id; ! 1090: { ! 1091: int bus_timeout; ! 1092: uchar phase_type; ! 1093: uchar msg_in; ! 1094: int s; ! 1095: int bytes_to_send; ! 1096: ss_type * ssp = ss[s_id]; ! 1097: BUF * bp = ssp->bp; ! 1098: int xfer_good = 1; ! 1099: int xfer_count = bp->b_count - bp->b_resid; ! 1100: int irpts_masked; ! 1101: int block_done=0; ! 1102: ! 1103: ssp->cmd_bytes_out = 0; ! 1104: ssp->msg_in = -1; ! 1105: ! 1106: irpts_masked = 0; ! 1107: while (req_wait(&bus_timeout) && xfer_good) { ! 1108: phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA); ! 1109: if (!irpts_masked) { ! 1110: s = sphi(); ! 1111: irpts_masked = 1; ! 1112: } ! 1113: switch (xpmod(phase_type)) { ! 1114: case XP_MSG_IN: ! 1115: msg_in = ffbyte(ss_dat); ! 1116: switch(msg_in){ ! 1117: case MSG_CMD_CMPLT: ! 1118: PR4("Mcc"); ! 1119: ssp->msg_in = msg_in; ! 1120: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT); ! 1121: break; ! 1122: case MSG_DISCONNECT: ! 1123: PR4("Mdc"); ! 1124: ssp->msg_in = msg_in; ! 1125: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT); ! 1126: break; ! 1127: case MSG_SAVE_DPTR: ! 1128: PR4("Msd"); ! 1129: break; ! 1130: case MSG_RSTOR_DPTR: ! 1131: PR4("Mrd"); ! 1132: break; ! 1133: case MSG_ABORT: ! 1134: PR4("Mab"); ! 1135: break; ! 1136: case MSG_DEV_RESET: ! 1137: PR4("Mdr"); ! 1138: break; ! 1139: case MSG_IDENTIFY: ! 1140: PR4("Mmi"); ! 1141: break; ! 1142: case MSG_IDENT_DC: ! 1143: PR4("Mmd"); ! 1144: break; ! 1145: } ! 1146: break; ! 1147: case XP_MSG_OUT: ! 1148: PR4("MO"); ! 1149: /* ! 1150: * This case shouldn't happen. We weren't ! 1151: * asserting ATTENTION. Abort the bus cycle. ! 1152: */ ! 1153: sfbyte(ss_dat, MSG_NOP); ! 1154: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI); ! 1155: break; ! 1156: case XP_STAT_IN: ! 1157: PR4("SI"); ! 1158: ssp->cmdstat = ffbyte(ss_dat); ! 1159: break; ! 1160: case XP_CMD_OUT: ! 1161: /* ! 1162: * Ship out command bytes. ! 1163: * Reset SCSI bus if too many command bytes are wanted. ! 1164: */ ! 1165: bytes_to_send = ssp->cmdlen - ssp->cmd_bytes_out; ! 1166: if(bytes_to_send > 0) { ! 1167: sfbyte(ss_dat, ssp->cmdbuf[ssp->cmd_bytes_out++]); ! 1168: /* ! 1169: * If just sent last byte, allow interrupts. ! 1170: */ ! 1171: if (bytes_to_send == 1) { ! 1172: PR4("CO"); ! 1173: if (bp->b_req == BREAD) { ! 1174: if (irpts_masked) { ! 1175: spl(s); ! 1176: irpts_masked = 0; ! 1177: } ! 1178: } ! 1179: } ! 1180: } else { /* This case should not happen. */ ! 1181: xfer_good = 0; ! 1182: } ! 1183: break; ! 1184: case XP_DATA_IN: ! 1185: /* ! 1186: * If caller's buffer has room, keep incoming ! 1187: * data byte. ! 1188: */ ! 1189: if (block_done) { ! 1190: xfer_good = 0; ! 1191: PR1("Data in overrun"); ! 1192: } else if (bp->b_req != BREAD) { ! 1193: xfer_good = 0; ! 1194: } else { ! 1195: #if 0 ! 1196: int getbval; ! 1197: ! 1198: block_done=1; ! 1199: PR4("DI"); ! 1200: if(getbval = ss_getb(ss_dat, ! 1201: bp->b_faddr + xfer_count)) { ! 1202: xfer_good = 0; ! 1203: #if (DEBUG >= 1) ! 1204: printf("getb=%d ", getbval); ! 1205: #endif ! 1206: } ! 1207: #else ! 1208: block_done=1; ! 1209: ffcopy(ss_dat, bp->b_faddr + xfer_count, BSIZE); ! 1210: #endif ! 1211: } ! 1212: break; ! 1213: case XP_DATA_OUT: ! 1214: /* ! 1215: * Copy output buffer bytes to data register. ! 1216: */ ! 1217: if (block_done) { ! 1218: xfer_good = 0; ! 1219: PR1("Data out overrun"); ! 1220: } else if (bp->b_req != BWRITE) { ! 1221: xfer_good = 0; ! 1222: } else { ! 1223: #if 0 ! 1224: int putbval; ! 1225: block_done=1; ! 1226: PR4("DO"); ! 1227: if (putbval = ss_putb(ss_dat, ! 1228: bp->b_faddr + xfer_count)) { ! 1229: xfer_good = 0; ! 1230: #if (DEBUG >= 1) ! 1231: printf("putb=%d ", putbval); ! 1232: #endif ! 1233: } ! 1234: #else ! 1235: block_done=1; ! 1236: ffcopy(bp->b_faddr + xfer_count, ss_dat, BSIZE); ! 1237: #endif ! 1238: if (irpts_masked) { ! 1239: spl(s); ! 1240: irpts_masked = 0; ! 1241: } ! 1242: } ! 1243: break; ! 1244: default: ! 1245: break; ! 1246: } /* endswitch */ ! 1247: } ! 1248: if (irpts_masked) ! 1249: spl(s); ! 1250: ! 1251: #if (DEBUG >= 1) ! 1252: switch(ssp->cmdstat) { ! 1253: case -1: ! 1254: if (msg_in != MSG_DISCONNECT) ! 1255: printf("CS-",ssp->cmdstat); ! 1256: break; ! 1257: case CS_GOOD: ! 1258: break; ! 1259: case CS_CHECK: ! 1260: printf("CSK",ssp->cmdstat); ! 1261: break; ! 1262: case CS_BUSY: ! 1263: printf("CSY",ssp->cmdstat); ! 1264: break; ! 1265: case CS_RESERVED: ! 1266: default: ! 1267: printf("CS%x",ssp->cmdstat); ! 1268: } ! 1269: #endif ! 1270: ! 1271: return (bus_timeout) ? 0 : 1 ; ! 1272: } ! 1273: ! 1274: /* ! 1275: * req_wait() ! 1276: * ! 1277: * This routine is called at the start of each information transfer ! 1278: * phase and after the last such phase. ! 1279: * ! 1280: * It returns 1 if REQ is asserted on the SCSI bus, meaning another phase ! 1281: * may begin, and 0 otherwise. A REQ signal will not be seen if the function ! 1282: * times out or if BUSY drops. A value of 1 is written to the pointer argument ! 1283: * if timeout occurred, else 0 is written. ! 1284: */ ! 1285: static int req_wait(to_ptr) ! 1286: int *to_ptr; ! 1287: { ! 1288: int req_found; ! 1289: unsigned char status; ! 1290: ulong poll_ct; ! 1291: int s; ! 1292: ! 1293: s = splo(); ! 1294: *to_ptr = 1; ! 1295: req_found = 0; ! 1296: for (poll_ct = 0L; poll_ct < max_req_poll; poll_ct++) { ! 1297: status = ffbyte(ss_csr); ! 1298: if (status & RS_REQUEST) { ! 1299: req_found = 1; ! 1300: *to_ptr = 0; ! 1301: break; ! 1302: } else if ((status & RS_BUSY) == 0) { ! 1303: *to_ptr = 0; ! 1304: break; ! 1305: } ! 1306: } ! 1307: ! 1308: #if (DEBUG >= 1) ! 1309: if (*to_ptr) { ! 1310: printf("TX: s=%x ", status); ! 1311: } ! 1312: #endif ! 1313: ! 1314: spl(s); ! 1315: return req_found; ! 1316: } ! 1317: ! 1318: /* ! 1319: * req_sense() ! 1320: * ! 1321: * Request Sense for a device. The main reason for doing this is to ! 1322: * clear a standing Command Status of Device Check. ! 1323: * ! 1324: * Full results are discarded. Return 1 if Device returns No Sense or ! 1325: * or Unit Attention. Else return 0. ! 1326: * ! 1327: */ ! 1328: static int req_sense(s_id) ! 1329: int s_id; ! 1330: { ! 1331: uchar sense_buf[SENSELEN]; ! 1332: uchar cmdbuf[G0CMDLEN]; ! 1333: int ret = 0; ! 1334: ! 1335: cmdbuf[0] = ScmdREQUESTSENSE; ! 1336: cmdbuf[1] = 0; ! 1337: cmdbuf[2] = 0; ! 1338: cmdbuf[3] = 0; ! 1339: cmdbuf[4] = SENSELEN; ! 1340: cmdbuf[5] = 0; ! 1341: ! 1342: #if (DEBUG >= 2) ! 1343: {int i; for (i=0; i<SENSELEN; i++) sense_buf[i]=0;} ! 1344: #endif ! 1345: ! 1346: PR2("rqs:"); ! 1347: if (!start_arb()) { ! 1348: PR2("NO arb"); ! 1349: #if (DEBUG >= 2) ! 1350: printf("status=%x ", ffbyte(ss_csr)); ! 1351: #endif ! 1352: goto rqs_done; ! 1353: } ! 1354: ! 1355: if (!host_ident(s_id, 0)) { ! 1356: PR2("NO host ident"); ! 1357: #if (DEBUG >= 2) ! 1358: printf("status=%x ", ffbyte(ss_csr)); ! 1359: #endif ! 1360: goto rqs_done; ! 1361: } ! 1362: ! 1363: if(!local_info_xfer(cmdbuf, G0CMDLEN, sense_buf, SENSELEN, NULL, 0)) { ! 1364: PR2("NO local xfer"); ! 1365: goto rqs_done; ! 1366: } else { ! 1367: /* ! 1368: * Return 1 if drive responded with any of these sense keys: ! 1369: * 0x00 No Sense ! 1370: * 0x06 Unit Attention ! 1371: * 0x0B Aborted Command ! 1372: * In any of the above cases, a retry will likely succeed ! 1373: * without Buse Device Reset or SCSI Bus Reset. ! 1374: */ ! 1375: switch (sense_buf[2]) { ! 1376: case 0x00: ! 1377: case 0x06: ! 1378: case 0x0B: ! 1379: ret = 1; ! 1380: break; ! 1381: } /* endswitch */ ! 1382: } ! 1383: ! 1384: rqs_done: ! 1385: #if (DEBUG >= 2) ! 1386: { ! 1387: int i; ! 1388: ! 1389: for (i=0; i<SENSELEN;i++) ! 1390: printf("%x ", sense_buf[i]); ! 1391: printf("\n"); ! 1392: } ! 1393: #endif ! 1394: return ret; ! 1395: } ! 1396: ! 1397: /* ! 1398: * inquiry() ! 1399: * ! 1400: * Inquiry command for a device. ! 1401: * Find out if device is direct access, removable, etc. ! 1402: * ! 1403: * Put result of inquiry into supplied buffer. ! 1404: * Return 1 if command succeeds, else 0. ! 1405: */ ! 1406: static int inquiry(s_id, buf) ! 1407: int s_id; ! 1408: uchar * buf; ! 1409: { ! 1410: int ret = 0; ! 1411: uchar cmdbuf[G0CMDLEN]; ! 1412: ! 1413: cmdbuf[0] = ScmdINQUIRY; ! 1414: cmdbuf[1] = 0; ! 1415: cmdbuf[2] = 0; ! 1416: cmdbuf[3] = 0; ! 1417: cmdbuf[4] = INQUIRYLEN; ! 1418: cmdbuf[5] = 0; ! 1419: ! 1420: if (start_arb() && host_ident(s_id, 0) && ! 1421: local_info_xfer(cmdbuf, G0CMDLEN, buf, INQUIRYLEN, NULL, 0)) ! 1422: ret = 1; ! 1423: ! 1424: return ret; ! 1425: } ! 1426: ! 1427: /* ! 1428: * mode_sense() ! 1429: * ! 1430: * Mode Sense command for a device. ! 1431: * Use this to get disk parameters: ! 1432: * number of cylinders ! 1433: * number of heads ! 1434: * number of sectors per track. ! 1435: * ! 1436: * Put result of mode sense into supplied buffer. ! 1437: * Return 1 if command succeeds, else 0. ! 1438: */ ! 1439: static int mode_sense(s_id, buf) ! 1440: int s_id; ! 1441: uchar * buf; ! 1442: { ! 1443: int ret = 0; ! 1444: uchar cmdbuf[G0CMDLEN]; ! 1445: ! 1446: cmdbuf[0] = ScmdMODESENSE; ! 1447: cmdbuf[1] = 0; ! 1448: cmdbuf[2] = 0x3F; ! 1449: cmdbuf[3] = 0; ! 1450: cmdbuf[4] = MODESENSELEN; ! 1451: cmdbuf[5] = 0; ! 1452: ! 1453: if (start_arb() && host_ident(s_id, 0) && ! 1454: local_info_xfer(cmdbuf, G0CMDLEN, buf, MODESENSELEN, NULL, 0)) ! 1455: ret = 1; ! 1456: ! 1457: return ret; ! 1458: } ! 1459: ! 1460: /* ! 1461: * read_cap() ! 1462: * ! 1463: * Read Capacity command for a device. ! 1464: * ! 1465: * Return 1 if command succeeds, else 0. ! 1466: */ ! 1467: static int read_cap(s_id, buf) ! 1468: int s_id; ! 1469: uchar * buf; ! 1470: { ! 1471: int ret = 0; ! 1472: uchar cmdbuf[G1CMDLEN]; ! 1473: ! 1474: cmdbuf[0] = ScmdREADCAPACITY; ! 1475: cmdbuf[1] = 0; ! 1476: cmdbuf[2] = 0; ! 1477: cmdbuf[3] = 0; ! 1478: cmdbuf[4] = 0; ! 1479: cmdbuf[5] = 0; ! 1480: cmdbuf[6] = 0; ! 1481: cmdbuf[7] = 0; ! 1482: cmdbuf[8] = 0; ! 1483: cmdbuf[9] = 0; ! 1484: ! 1485: if (start_arb() && host_ident(s_id, 0) && ! 1486: local_info_xfer(cmdbuf, G1CMDLEN, buf, READCAPLEN, NULL, 0)) ! 1487: ret = 1; ! 1488: ! 1489: return ret; ! 1490: } ! 1491: ! 1492: /* ! 1493: * bus_dev_reset() ! 1494: * ! 1495: * Send Bus Device Reset message to the given SCSI id. ! 1496: * Return 1 if host adapter was not busy and no obvious timeouts occurred, ! 1497: * else 0. ! 1498: */ ! 1499: static int bus_dev_reset(s_id) ! 1500: { ! 1501: int bdr_ok = 1; ! 1502: int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4)); ! 1503: ! 1504: PR1("BDR"); ! 1505: if (bdr_ok) { ! 1506: /* ! 1507: * Do ST0x arbitration. ! 1508: * ! 1509: * De-assert SCSI enable bit. ! 1510: * Write my SCSI id to port. ! 1511: * Start arbitration. ! 1512: */ ! 1513: sfbyte(ss_csr, WC_ENABLE_PRTY); ! 1514: sfbyte(ss_dat, host_id); ! 1515: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ARBITRATE); ! 1516: ! 1517: /* ! 1518: * SCSI spec says there is "no maximum" to the wait for ! 1519: * arbitration complete. ! 1520: */ ! 1521: if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) { ! 1522: bdr_ok = 0; ! 1523: } ! 1524: } ! 1525: ! 1526: /* ! 1527: * Arbitration complete. Now select, with ATN to allow messages. ! 1528: */ ! 1529: if (bdr_ok) { ! 1530: sfbyte(ss_dat, host_id | (1 << s_id)); /* Write both SCSI id's */ ! 1531: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT); ! 1532: ! 1533: if (!bus_wait(RS_BUSY << 8 | RS_BUSY)) ! 1534: bdr_ok = 0; ! 1535: } ! 1536: ! 1537: if (bdr_ok) { ! 1538: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION); ! 1539: ! 1540: if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) ! 1541: | (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE))) ! 1542: bdr_ok = 0; ! 1543: } ! 1544: ! 1545: if (bdr_ok) { ! 1546: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI); ! 1547: sfbyte(ss_dat, MSG_DEV_RESET); ! 1548: if (!bus_wait((0xFF << 8) | 0)) ! 1549: bdr_ok = 0; ! 1550: } ! 1551: ! 1552: return bdr_ok; ! 1553: } ! 1554: ! 1555: /* ! 1556: * chk_reconn() ! 1557: * ! 1558: * Check SELECT to see if any SCSI device has tried to reconnect to the host ! 1559: * adapter. Called if there is an interrupt, and by the timer in case ! 1560: * we somehow lose an interrupt. ! 1561: * ! 1562: * Return -1 if no reselect detected, or the SCSI ID of the reselecting ! 1563: * target if there is one. ! 1564: */ ! 1565: static int chk_reconn() ! 1566: { ! 1567: uchar csr, dat; ! 1568: int s_id = -1; ! 1569: ! 1570: csr = ffbyte(ss_csr); ! 1571: if (csr & (RS_SELECT | RS_I_O)) { ! 1572: dat = ffbyte(ss_dat); ! 1573: if ((dat & host_id) && (dat & NSDRIVE)) { ! 1574: dat &= ~host_id; ! 1575: s_id = 0; ! 1576: while (dat >>=1) ! 1577: s_id++; ! 1578: } ! 1579: } ! 1580: ! 1581: return s_id; ! 1582: } ! 1583: ! 1584: /* ! 1585: * ss_mach() ! 1586: * ! 1587: * Gives a distinct state machine for each target device. ! 1588: */ ! 1589: void ss_mach(s_id) ! 1590: int s_id; ! 1591: { ! 1592: ss_type * ssp = ss[s_id]; ! 1593: BUF * bp; ! 1594: ! 1595: do_sst_op = 1; /* plan to run this routine again in most cases */ ! 1596: while (do_sst_op) { ! 1597: bp = ssp->bp; /* nonpolled() below can change ssp->bp */ ! 1598: switch (ssp->state) { ! 1599: /* ! 1600: * Polling states execute whether ssp->waiting or not. ! 1601: */ ! 1602: case SST_POLL_ARBITN: ! 1603: PR3("XPAR"); ! 1604: if (ffbyte(ss_csr) & RS_ARBIT_COMPL) { ! 1605: ssp->waiting = 0; ! 1606: if (host_ident(s_id, 1)) ! 1607: do_connect(s_id); ! 1608: else ! 1609: recover(s_id, RV_P_TIMEOUT); ! 1610: } else { ! 1611: if (ssp->expired) { ! 1612: ssp->expired = 0; ! 1613: recover(s_id, RV_A_TIMEOUT); ! 1614: } else ! 1615: do_sst_op = 0; ! 1616: } ! 1617: break; ! 1618: case SST_POLL_RESELECT: ! 1619: PR3("XPRS"); ! 1620: if (TGT_RSEL) { ! 1621: ssp->waiting = 0; ! 1622: if (host_claimed == -1) ! 1623: host_claimed = s_id; ! 1624: else if (host_claimed != s_id) { ! 1625: #if (DEBUG >= 1) ! 1626: printf("%d->%d ", host_claimed, s_id); ! 1627: #endif ! 1628: } ! 1629: if (rsel_handshake()) { ! 1630: do_connect(s_id); ! 1631: } else { ! 1632: recover(s_id, RV_P_TIMEOUT); ! 1633: } ! 1634: } else { /* Reselect poll is negative */ ! 1635: if (ssp->expired) { ! 1636: ssp->expired = 0; ! 1637: recover(s_id, RV_R_TIMEOUT); ! 1638: } else ! 1639: do_sst_op = 0; ! 1640: } ! 1641: break; ! 1642: case SST_POLL_BEGIN_IO: ! 1643: PR3("XPBI"); ! 1644: if (bp == NULL) ! 1645: ssp->state = SST_DEQUEUE; ! 1646: else { ! 1647: /* ! 1648: * At this point a SCSI command is about to ! 1649: * be initiated. It may be a retry. ! 1650: */ ! 1651: if (host_claimed == -1 && BUS_FREE && BUS_FREE) { ! 1652: ssp->waiting = 0; ! 1653: init_pointers(s_id); ! 1654: if (start_arb()) { ! 1655: host_claimed = s_id; ! 1656: if (host_ident(s_id, 1)) { ! 1657: do_connect(s_id); ! 1658: } else { ! 1659: recover(s_id, RV_P_TIMEOUT); ! 1660: } ! 1661: } else { ! 1662: /* ! 1663: * If arbitration does not succeed right away, it is usually ! 1664: * because another drive is trying to reselect the host. ! 1665: */ ! 1666: set_timeout(s_id, DELAY_ARB); ! 1667: } ! 1668: } else { /* host busy or bus not free */ ! 1669: int o_id; ! 1670: ! 1671: if ((o_id = chk_reconn()) != -1) ! 1672: defer(dummy_reconn, s_id); ! 1673: ++ssp->avl_count; ! 1674: if (ssp->avl_count >= MAX_AVL_COUNT) ! 1675: recover(s_id, RV_BF_TIMEOUT); ! 1676: else ! 1677: set_timeout(s_id, DELAY_BSY); ! 1678: } ! 1679: } ! 1680: break; ! 1681: default: ! 1682: if (ssp->waiting) ! 1683: do_sst_op = 0; ! 1684: else { ! 1685: /* ! 1686: * Nonpolling states execute only if no ! 1687: * target timer is running. ! 1688: */ ! 1689: nonpolled(s_id); ! 1690: } ! 1691: } /* endswitch */ ! 1692: } /* endwhile */ ! 1693: } ! 1694: ! 1695: /* ! 1696: * nonpolled() ! 1697: * ! 1698: * Part of ss_mach() - handling of nonpolling states is taken out simply ! 1699: * for readability. ! 1700: */ ! 1701: static void nonpolled(s_id) ! 1702: int s_id; ! 1703: { ! 1704: ss_type * ssp = ss[s_id]; ! 1705: BUF * bp = ssp->bp; ! 1706: struct fdisk_s *fdp; ! 1707: int partition; ! 1708: dev_t dev; ! 1709: ! 1710: switch (ssp->state) { ! 1711: case SST_BUS_DEV_RESET: ! 1712: PR3("XBDR"); ! 1713: if (bus_dev_reset(s_id)) { ! 1714: do_sst_op = 0; ! 1715: set_timeout(s_id, DELAY_BDR); ! 1716: ssp->state = SST_REQ_SENSE; ! 1717: } else ! 1718: recover(s_id, RV_P_TIMEOUT); ! 1719: break; ! 1720: case SST_DEQUEUE: ! 1721: if(bufq_rd_head(s_id) != NULL && !ssp->busy) { ! 1722: PR3("XDQU"); ! 1723: ssp->busy = 1; ! 1724: bp = bufq_rm_head(s_id); ! 1725: ssp->bp = bp; ! 1726: dev = bp->b_dev; ! 1727: partition = DEV_PARTN(dev); ! 1728: if (dev & SDEV) ! 1729: partition = WHOLE_DRIVE; ! 1730: fdp = ssp->parmp; ! 1731: if (partition != WHOLE_DRIVE) ! 1732: ssp->bno = fdp[partition].p_base + bp->b_bno; ! 1733: else ! 1734: ssp->bno = bp->b_bno; ! 1735: if (bp->b_req == BREAD) ! 1736: ssp->cmdbuf[0] = ScmdREADEXTENDED; ! 1737: else ! 1738: ssp->cmdbuf[0] = ScmdWRITEXTENDED; ! 1739: ssp->cmdbuf[1] = 0; ! 1740: ssp->cmdbuf[2] = ssp->bno >> 24; ! 1741: ssp->cmdbuf[3] = ssp->bno >> 16; ! 1742: ssp->cmdbuf[4] = ssp->bno >> 8; ! 1743: ssp->cmdbuf[5] = ssp->bno; ! 1744: ssp->cmdbuf[6] = 0; ! 1745: ssp->cmdbuf[7] = 0; ! 1746: ssp->cmdbuf[8] = 1; ! 1747: ssp->cmdbuf[9] = 0; ! 1748: ssp->cmdlen = G1CMDLEN; ! 1749: init_pointers(s_id); ! 1750: ssp->bdr_count = 0; ! 1751: ssp->bsy_count = 0; ! 1752: ssp->try_count = 0; ! 1753: ssp->state = SST_POLL_BEGIN_IO; ! 1754: } else /* queue is empty or ssp->busy */ ! 1755: do_sst_op = 0; ! 1756: break; ! 1757: case SST_HIPRI_RESET: ! 1758: case SST_LOPRI_RESET: ! 1759: PR1("XRST"); ! 1760: /* ! 1761: * SST_LOPRI_RESET is same as SST_HIPRI_RESET for now. ! 1762: * Later, can implement a delay to allow other targets to ! 1763: * finish pending operations. ! 1764: */ ! 1765: if (host_claimed == s_id || host_claimed == -1) { ! 1766: host_claimed = s_id; ! 1767: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_SCSI_RESET); /* reset ON */ ! 1768: ssp->state = SST_RESET_OFF; ! 1769: set_timeout(s_id, DELAY_RST); ! 1770: PR1("+"); ! 1771: } else ! 1772: set_timeout(s_id, DELAY_RST); ! 1773: break; ! 1774: case SST_REQ_SENSE: ! 1775: PR1("XRQS"); ! 1776: /* ! 1777: * Come here at end of SCSI Bus reset (and at other times). ! 1778: * If we have host claimed, release it. ! 1779: */ ! 1780: if (host_claimed == s_id) ! 1781: host_claimed = -1; ! 1782: if (req_sense(s_id)) ! 1783: ssp->state = SST_POLL_BEGIN_IO; ! 1784: else ! 1785: recover(s_id, RV_P_TIMEOUT); ! 1786: break; ! 1787: case SST_RESET_OFF: ! 1788: PR3("XRFF"); ! 1789: sfbyte(ss_csr, WC_ENABLE_PRTY); /* reset OFF */ ! 1790: ssp->state = SST_REQ_SENSE; ! 1791: set_timeout(s_id, DELAY_RST); ! 1792: } /* endswitch */ ! 1793: } ! 1794: ! 1795: /* ! 1796: * start_arb() ! 1797: * ! 1798: * return 1 if host adapter returned Arbitration Complete within allotted ! 1799: * number of tries, else 0 ! 1800: */ ! 1801: static int start_arb() ! 1802: { ! 1803: int ret = 0; ! 1804: int poll_ct; ! 1805: ! 1806: sfbyte(ss_csr, WC_ENABLE_PRTY); ! 1807: sfbyte(ss_dat, host_id); ! 1808: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ARBITRATE); ! 1809: ! 1810: /* ! 1811: * SCSI spec says there is "no maximum" to the wait for arbitration ! 1812: * complete. ! 1813: */ ! 1814: for (poll_ct = 0; poll_ct < HIPRI_RETRIES; poll_ct++) { ! 1815: if (ffbyte(ss_csr) & RS_ARBIT_COMPL) { ! 1816: ret = 1; ! 1817: break; ! 1818: } else if (chk_reconn() != -1) { ! 1819: sfbyte(ss_csr, WC_ENABLE_PRTY); ! 1820: break; ! 1821: } ! 1822: } ! 1823: #if (DEBUG >= 1) ! 1824: if (!ret) ! 1825: PR1("oSA"); ! 1826: #endif ! 1827: return ret; ! 1828: } ! 1829: ! 1830: /* ! 1831: * host_ident() ! 1832: * ! 1833: * This routine is the bridge in a SCSI bus cycle between Abitration ! 1834: * Complete and the Information Transfer phases. ! 1835: * ! 1836: * return 1 if everything went ok, 0 in case of timeout ! 1837: */ ! 1838: static int host_ident(s_id, disconnect) ! 1839: int s_id; ! 1840: int disconnect; ! 1841: { ! 1842: int ret = 0; ! 1843: ! 1844: /* ! 1845: * Arbitration complete. Now select, with ATN to allow messages. ! 1846: */ ! 1847: sfbyte(ss_dat, host_id | (1 << s_id)); /* Write both SCSI id's */ ! 1848: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT); ! 1849: ! 1850: if (bus_wait(RS_BUSY << 8 | RS_BUSY)) { ! 1851: /* ! 1852: * Assert ATTN so target expects incoming message byte. ! 1853: */ ! 1854: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION); ! 1855: ! 1856: if (bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) ! 1857: | (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE))) { ! 1858: if (disconnect) ! 1859: sfbyte(ss_dat, MSG_IDENT_DC); ! 1860: else ! 1861: sfbyte(ss_dat, MSG_IDENTIFY); ! 1862: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ENABLE_IRPT); ! 1863: ret = 1; ! 1864: } else { ! 1865: PR1("oHI2"); ! 1866: } ! 1867: } else { ! 1868: PR1("oHI1"); ! 1869: } ! 1870: return ret; ! 1871: } ! 1872: ! 1873: /* ! 1874: * rsel_handshake() ! 1875: * ! 1876: * After Reselect is detected, a couple steps are needed before entering ! 1877: * Information Transfer phases. This routine does those steps. ! 1878: * ! 1879: * return 1 if ok, 0 in case of timeout. ! 1880: */ ! 1881: static int rsel_handshake() ! 1882: { ! 1883: int ret = 0; ! 1884: ! 1885: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_BUSY); ! 1886: if (bus_wait(RS_SELECT << 8 | 0)) { ! 1887: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI); ! 1888: ret = 1; ! 1889: } ! 1890: return ret; ! 1891: } ! 1892: ! 1893: /* ! 1894: * set_timeout() ! 1895: * ! 1896: * Start a timer so as not to wait forever in case something goes wrong while ! 1897: * waiting for an event. Available delays are: ! 1898: * ! 1899: * DELAY_ARB - wait for arbitration complete ! 1900: * DELAY_BDR - allow settling time after Bus Device Reset ! 1901: * DELAY_BSY - wait for not HOST_BUSY and bus free ! 1902: * DELAY_RES - wait for reselect by target ! 1903: * DELAY_RST - allow settling times when doing SCSI Bus Reset ! 1904: * ! 1905: * Second argument is number of clock ticks to wait until timer expiration. ! 1906: */ ! 1907: static void set_timeout(s_id, delay) ! 1908: int s_id, delay; ! 1909: { ! 1910: ss_type * ssp = ss[s_id]; ! 1911: ! 1912: ssp->expired = 0; ! 1913: ssp->waiting = 1; ! 1914: do_sst_op = 0; ! 1915: timeout(&(ssp->tim), delay, stop_timeout, s_id); ! 1916: } ! 1917: ! 1918: /* ! 1919: * stop_timeout() ! 1920: * ! 1921: * Called on expiration of the timer for a given target. ! 1922: * Don't expire a timer if it's no longer active. ! 1923: */ ! 1924: static void stop_timeout(s_id) ! 1925: int s_id; ! 1926: { ! 1927: ss_type * ssp = ss[s_id]; ! 1928: ! 1929: if (ssp->waiting) { ! 1930: ssp->expired = 1; ! 1931: ssp->waiting = 0; ! 1932: } ! 1933: ss_mach(s_id); ! 1934: } ! 1935: ! 1936: /* ! 1937: * init_pointers() ! 1938: * ! 1939: * Initialize command and data pointers when starting (or restarting) ! 1940: * a block i/o command. ! 1941: */ ! 1942: static void init_pointers(s_id) ! 1943: int s_id; ! 1944: { ! 1945: ss_type * ssp = ss[s_id]; ! 1946: BUF * bp = ssp->bp; ! 1947: ! 1948: ssp->cmdstat = -1; ! 1949: ssp->cmd_bytes_out = 0; ! 1950: ssp->avl_count = 0; ! 1951: } ! 1952: ! 1953: /* ! 1954: * recover() ! 1955: * ! 1956: * This routine is called directly or indirectly from ss_mach(). It ! 1957: * determines what to do when the interface fails to behave as desired. ! 1958: * ! 1959: * Arguments are the SCSI id of the target HDC and an error type. ! 1960: * Error types are: ! 1961: * ! 1962: * RV_A_TIMEOUT (arbitration timeout) ! 1963: * Host adapter takes too long to respond with arbitration complete. ! 1964: * ! 1965: * RV_P_TIMEOUT (protocol timeout) ! 1966: * Timeout waiting for desired SCSI bus status while connected to a target. ! 1967: * ! 1968: * RV_R_TIMEOUT (reconnect timeout) ! 1969: * Timeout after target disconnects, waiting for reconnect. ! 1970: * ! 1971: * RV_BF_TIMEOUT (bus free timeout) ! 1972: * Waited too long for host not busy and BUS_FREE. ! 1973: * ! 1974: * RV_CS_BUSY (target device busy) ! 1975: * Command status returned was Busy. ! 1976: * ! 1977: * RV_CS_CHECK (target device check) ! 1978: * Command status returned was CHECK. ! 1979: * ! 1980: * Whenever an error occurs, one of the above inputs, together with the SCSI id ! 1981: * of the target, is sent to the recovery process. The recovery process in turn ! 1982: * programs the next state for the machine. ! 1983: */ ! 1984: static void recover(s_id, errtype) ! 1985: int s_id; ! 1986: RV_TYPE errtype; ! 1987: { ! 1988: ss_type * ssp = ss[s_id]; ! 1989: BUF * bp = ssp->bp; ! 1990: ! 1991: #if (DEBUG >= 1) ! 1992: int foo; ! 1993: if ((foo=chk_reconn()) != -1) ! 1994: printf("HONK%d ", foo); ! 1995: #endif ! 1996: ! 1997: ++ssp->try_count; ! 1998: if (ssp->try_count < MAX_TRY_COUNT) { ! 1999: ! 2000: switch (errtype) { ! 2001: ! 2002: case RV_CS_BUSY: ! 2003: ++ssp->bsy_count; ! 2004: if (ssp->bsy_count < MAX_BSY_COUNT) { ! 2005: ssp->state = SST_POLL_BEGIN_IO; ! 2006: set_timeout(s_id, DELAY_BSY); ! 2007: } else ! 2008: ssp->state = SST_BUS_DEV_RESET; ! 2009: break; ! 2010: ! 2011: case RV_CS_CHECK: ! 2012: ssp->state = SST_REQ_SENSE; ! 2013: break; ! 2014: ! 2015: case RV_P_TIMEOUT: ! 2016: /* fall thru */ ! 2017: case RV_R_TIMEOUT: ! 2018: ++ssp->bdr_count; ! 2019: if (ssp->bdr_count < MAX_BDR_COUNT) ! 2020: ssp->state = SST_BUS_DEV_RESET; ! 2021: else ! 2022: ssp->state = SST_LOPRI_RESET; ! 2023: break; ! 2024: ! 2025: case RV_BF_TIMEOUT: ! 2026: /* fall thru */ ! 2027: case RV_A_TIMEOUT: ! 2028: ssp->state = SST_HIPRI_RESET; ! 2029: } ! 2030: } else { /* try_count >= MAX_TRY_COUNT */ ! 2031: if (bp) { ! 2032: bp->b_flag |= BFERR; ! 2033: printf("(%d,%d): ", major(bp->b_dev), minor(bp->b_dev)); ! 2034: printf("%s error bno=%ld\n", ! 2035: (bp->b_req == BREAD) ? "read" : "write", ! 2036: bp->b_bno); ! 2037: } ! 2038: ss_finished(s_id); ! 2039: } ! 2040: } ! 2041: ! 2042: /* ! 2043: * ss_finished ! 2044: * ! 2045: * Release current i/o buffer to the O/S. ! 2046: */ ! 2047: static void ss_finished(s_id) ! 2048: int s_id; ! 2049: { ! 2050: ss_type * ssp = ss[s_id]; ! 2051: BUF * bp = ssp->bp; ! 2052: int go_again = 1; ! 2053: ! 2054: if (host_claimed == s_id) ! 2055: host_claimed = -1; ! 2056: ssp->busy = 0; ! 2057: if (bp) { ! 2058: if (!(bp->b_flag & BFERR)) ! 2059: bp->b_resid -= BSIZE; ! 2060: if ((bp->b_flag & BFERR) || bp->b_resid == 0) { ! 2061: ssp->bp = NULL; ! 2062: bdone(bp); ! 2063: go_again = 0; ! 2064: } ! 2065: } ! 2066: if (go_again) { ! 2067: ssp->state = SST_POLL_BEGIN_IO; ! 2068: ssp->bdr_count = 0; ! 2069: ssp->bsy_count = 0; ! 2070: ssp->try_count = 0; ! 2071: ! 2072: ssp->bno++; ! 2073: ssp->cmdbuf[2] = ssp->bno >> 24; ! 2074: ssp->cmdbuf[3] = ssp->bno >> 16; ! 2075: ssp->cmdbuf[4] = ssp->bno >> 8; ! 2076: ssp->cmdbuf[5] = ssp->bno; ! 2077: } else { ! 2078: /* ! 2079: * After processing a kernel i/o request, stop the ! 2080: * state machine for the current id. Then start ! 2081: * this or some other machine which has a request ! 2082: * pending. ! 2083: */ ! 2084: do_sst_op = 0; ! 2085: ssp->state = SST_DEQUEUE; ! 2086: next_req(s_id); ! 2087: } ! 2088: } ! 2089: ! 2090: /* ! 2091: * next_req() ! 2092: * ! 2093: * Given the SCSI id where an i/o request just completed, start handling ! 2094: * another i/o request - which may be for the same or other SCSI id. ! 2095: * For now, use round-robin scheduling. ! 2096: */ ! 2097: static void next_req(s_id) ! 2098: int s_id; ! 2099: { ! 2100: int next_id = s_id; ! 2101: ! 2102: while (1) { ! 2103: next_id++; ! 2104: if (next_id >= MAX_SCSI_ID) ! 2105: next_id = 0; ! 2106: if (ss[next_id] ! 2107: && (ss[next_id]->state != SST_DEQUEUE || bufq_rd_head(next_id))) { ! 2108: defer(ss_mach, next_id); ! 2109: break; ! 2110: } ! 2111: if (next_id == s_id) ! 2112: break; ! 2113: } ! 2114: } ! 2115: ! 2116: /* ! 2117: * do_connect() ! 2118: * ! 2119: * This function is called when the host is successfully connected to ! 2120: * the target. It invokes information transfer protocol and then sets ! 2121: * up some sort of recovery unless the command completed successfully ! 2122: * or there was a normal disconnect. ! 2123: */ ! 2124: static void do_connect(s_id) ! 2125: int s_id; ! 2126: { ! 2127: int result; ! 2128: ss_type * ssp = ss[s_id]; ! 2129: ! 2130: result = far_info_xfer(s_id); ! 2131: if (!result) ! 2132: recover(s_id, RV_P_TIMEOUT); ! 2133: else if (ssp->msg_in == MSG_DISCONNECT) { ! 2134: ssp->state = SST_POLL_RESELECT; ! 2135: set_timeout(s_id, DELAY_RES); ! 2136: #if 0 ! 2137: if (host_claimed == s_id) ! 2138: host_claimed = -1; ! 2139: #endif ! 2140: } else if (ssp->msg_in == MSG_CMD_CMPLT && ssp->cmdstat == CS_GOOD) ! 2141: ss_finished(s_id); ! 2142: else if (ssp->cmdstat == CS_BUSY) ! 2143: recover(s_id, RV_CS_BUSY); ! 2144: else if (ssp->cmdstat == CS_CHECK) ! 2145: recover(s_id, RV_CS_CHECK); ! 2146: else /* something else went wrong */ ! 2147: recover(s_id, RV_P_TIMEOUT); ! 2148: } ! 2149: ! 2150: /* ! 2151: * local_info_xfer() ! 2152: * ! 2153: * Do bus cycle information transfer phases. ! 2154: * Transfer is for a command which will produce local results in the driver. ! 2155: * Other ...info_xfer routine handles kernel block i/o commands. ! 2156: * ! 2157: * Return 1 if transfer succeeded, else 0. ! 2158: * ! 2159: */ ! 2160: static int local_info_xfer(cmdbuf, cmdlen, inbuf, inlen, outbuf, outlen) ! 2161: uchar * cmdbuf, * inbuf, * outbuf; ! 2162: uint cmdlen, inlen, outlen; ! 2163: { ! 2164: int bus_timeout; ! 2165: uchar phase_type; ! 2166: int s; ! 2167: int cmd_bytes_out = 0; ! 2168: int data_bytes_in = 0; ! 2169: int data_bytes_out = 0; ! 2170: int ret = 0; ! 2171: int xfer_good = 1; ! 2172: int cmdstat = -1; ! 2173: int msg_in = -1; ! 2174: #if (DEBUG >= 1) ! 2175: int x, xct=0; ! 2176: uchar xch[100]; ! 2177: #endif ! 2178: ! 2179: s = sphi(); ! 2180: while (req_wait(&bus_timeout) && xfer_good) { ! 2181: phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA); ! 2182: #if (DEBUG >= 1) ! 2183: if (xct < 100) ! 2184: xch[xct++]=phase_type; ! 2185: #endif ! 2186: switch (xpmod(phase_type)) { ! 2187: case XP_MSG_IN: ! 2188: msg_in = ffbyte(ss_dat); ! 2189: switch(msg_in){ ! 2190: case MSG_CMD_CMPLT: ! 2191: case MSG_DISCONNECT: ! 2192: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT); ! 2193: break; ! 2194: } ! 2195: break; ! 2196: case XP_MSG_OUT: ! 2197: /* ! 2198: * This case shouldn't happen. We weren't ! 2199: * asserting ATTENTION. ! 2200: */ ! 2201: sfbyte(ss_dat, MSG_NOP); ! 2202: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI); ! 2203: break; ! 2204: case XP_STAT_IN: ! 2205: cmdstat = ffbyte(ss_dat); ! 2206: break; ! 2207: case XP_CMD_OUT: ! 2208: /* ! 2209: * Ship out command bytes. ! 2210: */ ! 2211: if (cmd_bytes_out < cmdlen) { ! 2212: sfbyte(ss_dat, cmdbuf[cmd_bytes_out++]); ! 2213: #if 1 ! 2214: /* ! 2215: * If just sent last byte, allow interrupts. ! 2216: */ ! 2217: if (cmd_bytes_out == cmdlen) { ! 2218: spl(s); ! 2219: s = sphi(); ! 2220: } ! 2221: #endif ! 2222: } else { /* This case should not happen. */ ! 2223: xfer_good = 0; ! 2224: } ! 2225: break; ! 2226: case XP_DATA_IN: ! 2227: /* ! 2228: * If caller's buffer has room, keep incoming ! 2229: * data byte. Else toss it. ! 2230: */ ! 2231: if (data_bytes_in < inlen) { ! 2232: #if 0 ! 2233: do { ! 2234: inbuf[data_bytes_in++] = ffbyte(ss_dat); ! 2235: } while (data_bytes_in < inlen); ! 2236: #else ! 2237: inbuf[data_bytes_in++] = ffbyte(ss_dat); ! 2238: #endif ! 2239: } else ! 2240: xfer_good = 0; ! 2241: break; ! 2242: case XP_DATA_OUT: ! 2243: /* ! 2244: * Copy output buffer bytes to data register. ! 2245: */ ! 2246: if (data_bytes_out < outlen) { ! 2247: sfbyte(outbuf[data_bytes_out++], ss_dat); ! 2248: } else { /* This case should not happen. */ ! 2249: xfer_good = 0; ! 2250: } ! 2251: break; ! 2252: default: ! 2253: break; ! 2254: } /* endswitch */ ! 2255: } ! 2256: spl(s); ! 2257: ! 2258: if (bus_timeout) { ! 2259: PR1("oLX1"); ! 2260: } else if (!xfer_good) { ! 2261: PR1("oLX2"); ! 2262: } else if (cmdstat != CS_GOOD) { ! 2263: PR1("oLX3"); ! 2264: #if (DEBUG >= 1) ! 2265: printf("cmdstat=%x ", cmdstat); ! 2266: #endif ! 2267: } else ! 2268: ret = 1; ! 2269: #if (DEBUG >= 1) ! 2270: if (!ret) { ! 2271: printf("csr=%x ", ffbyte(ss_csr)); ! 2272: printf("xct=%d ", xct); ! 2273: for (x=0; x < xct; x++) ! 2274: printf("%x ", xch[x]); ! 2275: } ! 2276: #endif ! 2277: ! 2278: return ret; ! 2279: } ! 2280: ! 2281: /* ! 2282: * scsireset() ! 2283: * ! 2284: * Reset the SCSI bus. ! 2285: * Allow settling time when turning reset on/off. ! 2286: * Settling times were determined empirically. ! 2287: * Each tick is 10 msec. ! 2288: */ ! 2289: static void scsireset() ! 2290: { ! 2291: int s; ! 2292: ! 2293: #if (DEBUG >= 1) ! 2294: printf("scsireset "); ! 2295: #endif ! 2296: s = splo(); ! 2297: sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_SCSI_RESET); ! 2298: ssdelay(RESET_TICKS); ! 2299: sfbyte(ss_csr, WC_ENABLE_PRTY); ! 2300: ssdelay(RESET_TICKS); ! 2301: spl(s); ! 2302: } ! 2303: ! 2304: /* ! 2305: * ssdelay() ! 2306: * ! 2307: * Delay for some number of arbitrary ticks. ! 2308: * ! 2309: * Using sleep() causes a panic if this driver is linked to the kernel, ! 2310: * even though this routine is called only via ssload(). ! 2311: */ ! 2312: static void ssdelay(ticks) ! 2313: int ticks; ! 2314: { ! 2315: #if 0 ! 2316: timeout(&delay_tim, ticks, wakeup, (int)&delay_tim); ! 2317: sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE); ! 2318: #else ! 2319: int i, j; ! 2320: ! 2321: for (i = 0; i < ticks; i++) ! 2322: for (j = 0; j < LOAD_DELAY; j++); ! 2323: #endif ! 2324: } ! 2325: ! 2326: /* ! 2327: * init_call() ! 2328: * ! 2329: * Call SCSI command function during initialization, with error recovery. ! 2330: * If the simple command fails, try a Bus Device Reset, then SCSI Bus reset. ! 2331: */ ! 2332: static int init_call(fn, s_id, buf) ! 2333: int (*fn)(); ! 2334: int s_id; ! 2335: uchar * buf; ! 2336: { ! 2337: int ret = 1; ! 2338: int i; ! 2339: int o_id; ! 2340: int s; ! 2341: s=sphi(); ! 2342: for (i = 0; i < 2; i++) { ! 2343: o_id = chk_reconn(); ! 2344: if (o_id != -1) ! 2345: dummy_reconn(s_id); ! 2346: if ((*fn)(s_id, buf)) ! 2347: goto init_call_done; ! 2348: ! 2349: req_sense(s_id); ! 2350: if ((*fn)(s_id, buf)) ! 2351: goto init_call_done; ! 2352: ! 2353: if (bus_dev_reset(s_id)) { ! 2354: ssdelay(RESET_TICKS); ! 2355: req_sense(s_id); ! 2356: if ((*fn)(s_id, buf)) ! 2357: goto init_call_done; ! 2358: } ! 2359: ! 2360: scsireset(); ! 2361: req_sense(s_id); ! 2362: if ((*fn)(s_id, buf)) ! 2363: goto init_call_done; ! 2364: } ! 2365: ! 2366: ret = 0; ! 2367: ! 2368: init_call_done: ! 2369: spl(s); ! 2370: return ret; ! 2371: } ! 2372: ! 2373: /* ! 2374: * xpmod() ! 2375: * ! 2376: * Command/Data and Message bits are swapped on-board (outside the chip) ! 2377: * on older Future Domain host boards. ! 2378: */ ! 2379: static uchar xpmod(oldphase) ! 2380: uchar oldphase; ! 2381: { ! 2382: uchar ret = oldphase; ! 2383: ! 2384: if (swap_status_bits) { ! 2385: ret &= ~(RS_CTRL_DATA | RS_MESSAGE); ! 2386: if (oldphase & RS_MESSAGE) ! 2387: ret |= RS_CTRL_DATA; ! 2388: if (oldphase & RS_CTRL_DATA) ! 2389: ret |= RS_MESSAGE; ! 2390: } ! 2391: return ret; ! 2392: } ! 2393: ! 2394: /* ! 2395: * tbparms() ! 2396: * ! 2397: * If the drive table has already been patched for this SCSI id, do nothing. ! 2398: * Otherwise, given the real-mode drive number (tbnum) and the SCSI id (s_id), ! 2399: * look for drive parameters from tertiary boot, and copy into driver ! 2400: * data block if we find them. ! 2401: */ ! 2402: static void tbparms(tbnum, s_id) ! 2403: int tbnum, s_id; ! 2404: { ! 2405: FIFO *ffp; ! 2406: typed_space *tp; ! 2407: extern typed_space boot_gift; ! 2408: ! 2409: if (drv_parm[s_id].ncyl == 0 ! 2410: && F_NULL != (ffp = fifo_open(&boot_gift, 0))) { ! 2411: ! 2412: if (T_NULL != (tp = fifo_read(ffp))) { ! 2413: BIOS_DISK *bdp = (BIOS_DISK *)tp->ts_data; ! 2414: if ((T_BIOS_DISK == tp->ts_type) && ! 2415: (tbnum == bdp->dp_drive) ) { ! 2416: drv_parm[s_id].ncyl = bdp->dp_cylinders; ! 2417: drv_parm[s_id].nhead = bdp->dp_heads; ! 2418: drv_parm[s_id].nspt = bdp->dp_sectors; ! 2419: } ! 2420: } ! 2421: fifo_close(ffp); ! 2422: } ! 2423: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.