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