1*41488Smckusick /* 2*41488Smckusick * Copyright (c) 1988 University of Utah. 3*41488Smckusick * Copyright (c) 1990 The Regents of the University of California. 4*41488Smckusick * All rights reserved. 5*41488Smckusick * 6*41488Smckusick * This code is derived from software contributed to Berkeley by 7*41488Smckusick * Van Jacobson of Lawrence Berkeley Laboratory and the Systems 8*41488Smckusick * Programming Group of the University of Utah Computer Science Department. 9*41488Smckusick * 10*41488Smckusick * %sccs.include.redist.c% 11*41488Smckusick * 12*41488Smckusick * from: Utah $Hdr: scsi.c 1.3 90/01/27$ 13*41488Smckusick * 14*41488Smckusick * @(#)scsi.c 7.1 (Berkeley) 05/08/90 15*41488Smckusick */ 16*41488Smckusick 17*41488Smckusick /* 18*41488Smckusick * SCSI bus driver for standalone programs. 19*41488Smckusick */ 20*41488Smckusick 21*41488Smckusick #include "../sys/types.h" 22*41488Smckusick #include "../sys/reboot.h" 23*41488Smckusick #include "../hpdev/device.h" 24*41488Smckusick #include "../hpdev/scsireg.h" 25*41488Smckusick #include "scsivar.h" 26*41488Smckusick 27*41488Smckusick #include "saio.h" 28*41488Smckusick #include "samachdep.h" 29*41488Smckusick 30*41488Smckusick struct scsi_softc scsi_softc[NSCSI]; 31*41488Smckusick 32*41488Smckusick #define scsiunit(x) ((x) >> 3) 33*41488Smckusick #define scsislave(x) ((x) & 7) 34*41488Smckusick 35*41488Smckusick void scsireset(); 36*41488Smckusick int scsi_cmd_wait = 500; 37*41488Smckusick int scsi_data_wait = 300000; 38*41488Smckusick 39*41488Smckusick scsiinit() 40*41488Smckusick { 41*41488Smckusick extern struct hp_hw sc_table[]; 42*41488Smckusick register struct hp_hw *hw; 43*41488Smckusick register struct scsi_softc *hs; 44*41488Smckusick register int i, addr; 45*41488Smckusick static int first = 1; 46*41488Smckusick 47*41488Smckusick i = 0; 48*41488Smckusick for (hw = sc_table; i < NSCSI && hw < &sc_table[MAX_CTLR]; hw++) { 49*41488Smckusick if (hw->hw_type != SCSI) 50*41488Smckusick continue; 51*41488Smckusick hs = &scsi_softc[i]; 52*41488Smckusick hs->sc_addr = hw->hw_addr; 53*41488Smckusick scsireset(i); 54*41488Smckusick if (howto & RB_ASKNAME) 55*41488Smckusick printf("scsi%d at sc%d\n", i, hw->hw_sc); 56*41488Smckusick /* 57*41488Smckusick * Adjust devtype on first call. This routine assumes that 58*41488Smckusick * adaptor is in the high byte of devtype. 59*41488Smckusick */ 60*41488Smckusick if (first && ((devtype >> 24) & 0xff) == hw->hw_sc) { 61*41488Smckusick devtype = (devtype & 0x00ffffff) | (i << 24); 62*41488Smckusick first = 0; 63*41488Smckusick } 64*41488Smckusick hs->sc_alive = 1; 65*41488Smckusick i++; 66*41488Smckusick } 67*41488Smckusick } 68*41488Smckusick 69*41488Smckusick scsialive(unit) 70*41488Smckusick register int unit; 71*41488Smckusick { 72*41488Smckusick unit = scsiunit(unit); 73*41488Smckusick if (unit >= NSCSI || scsi_softc[unit].sc_alive == 0) 74*41488Smckusick return (0); 75*41488Smckusick return (1); 76*41488Smckusick } 77*41488Smckusick 78*41488Smckusick void 79*41488Smckusick scsireset(unit) 80*41488Smckusick register int unit; 81*41488Smckusick { 82*41488Smckusick volatile register struct scsidevice *hd; 83*41488Smckusick register struct scsi_softc *hs; 84*41488Smckusick u_int i; 85*41488Smckusick 86*41488Smckusick unit = scsiunit(unit); 87*41488Smckusick hs = &scsi_softc[unit]; 88*41488Smckusick hd = (struct scsidevice *)hs->sc_addr; 89*41488Smckusick hd->scsi_id = 0xFF; 90*41488Smckusick DELAY(100); 91*41488Smckusick /* 92*41488Smckusick * Disable interrupts then reset the FUJI chip. 93*41488Smckusick */ 94*41488Smckusick hd->scsi_csr = 0; 95*41488Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; 96*41488Smckusick hd->scsi_scmd = 0; 97*41488Smckusick hd->scsi_tmod = 0; 98*41488Smckusick hd->scsi_pctl = 0; 99*41488Smckusick hd->scsi_temp = 0; 100*41488Smckusick hd->scsi_tch = 0; 101*41488Smckusick hd->scsi_tcm = 0; 102*41488Smckusick hd->scsi_tcl = 0; 103*41488Smckusick hd->scsi_ints = 0; 104*41488Smckusick 105*41488Smckusick /* 106*41488Smckusick * Configure the FUJI chip with its SCSI address, all 107*41488Smckusick * interrupts enabled & appropriate parity. 108*41488Smckusick */ 109*41488Smckusick i = (~hd->scsi_hconf) & 0x7; 110*41488Smckusick hs->sc_scsi_addr = 1 << i; 111*41488Smckusick hd->scsi_bdid = i; 112*41488Smckusick if (hd->scsi_hconf & HCONF_PARITY) 113*41488Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 114*41488Smckusick SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 115*41488Smckusick SCTL_INTR_ENAB | SCTL_PARITY_ENAB; 116*41488Smckusick else 117*41488Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 118*41488Smckusick SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 119*41488Smckusick SCTL_INTR_ENAB; 120*41488Smckusick hd->scsi_sctl &=~ SCTL_DISABLE; 121*41488Smckusick } 122*41488Smckusick 123*41488Smckusick 124*41488Smckusick int 125*41488Smckusick scsiabort(hs, hd) 126*41488Smckusick register struct scsi_softc *hs; 127*41488Smckusick volatile register struct scsidevice *hd; 128*41488Smckusick { 129*41488Smckusick printf("scsi error: scsiabort\n"); 130*41488Smckusick return (0); 131*41488Smckusick } 132*41488Smckusick 133*41488Smckusick static int 134*41488Smckusick issue_select(hd, target, our_addr) 135*41488Smckusick volatile register struct scsidevice *hd; 136*41488Smckusick u_char target, our_addr; 137*41488Smckusick { 138*41488Smckusick if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) 139*41488Smckusick return (1); 140*41488Smckusick 141*41488Smckusick if (hd->scsi_ints & INTS_DISCON) 142*41488Smckusick hd->scsi_ints = INTS_DISCON; 143*41488Smckusick 144*41488Smckusick hd->scsi_pctl = 0; 145*41488Smckusick hd->scsi_temp = (1 << target) | our_addr; 146*41488Smckusick /* select timeout is hardcoded to 2ms */ 147*41488Smckusick hd->scsi_tch = 0; 148*41488Smckusick hd->scsi_tcm = 32; 149*41488Smckusick hd->scsi_tcl = 4; 150*41488Smckusick 151*41488Smckusick hd->scsi_scmd = SCMD_SELECT; 152*41488Smckusick return (0); 153*41488Smckusick } 154*41488Smckusick 155*41488Smckusick static int 156*41488Smckusick wait_for_select(hd) 157*41488Smckusick volatile register struct scsidevice *hd; 158*41488Smckusick { 159*41488Smckusick u_char ints; 160*41488Smckusick 161*41488Smckusick while ((ints = hd->scsi_ints) == 0) 162*41488Smckusick DELAY(1); 163*41488Smckusick hd->scsi_ints = ints; 164*41488Smckusick return (!(hd->scsi_ssts & SSTS_INITIATOR)); 165*41488Smckusick } 166*41488Smckusick 167*41488Smckusick static int 168*41488Smckusick ixfer_start(hd, len, phase, wait) 169*41488Smckusick volatile register struct scsidevice *hd; 170*41488Smckusick int len; 171*41488Smckusick u_char phase; 172*41488Smckusick register int wait; 173*41488Smckusick { 174*41488Smckusick 175*41488Smckusick hd->scsi_tch = len >> 16; 176*41488Smckusick hd->scsi_tcm = len >> 8; 177*41488Smckusick hd->scsi_tcl = len; 178*41488Smckusick hd->scsi_pctl = phase; 179*41488Smckusick hd->scsi_tmod = 0; /*XXX*/ 180*41488Smckusick hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 181*41488Smckusick 182*41488Smckusick /* wait for xfer to start or svc_req interrupt */ 183*41488Smckusick while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 184*41488Smckusick if (hd->scsi_ints || --wait < 0) 185*41488Smckusick return (0); 186*41488Smckusick DELAY(1); 187*41488Smckusick } 188*41488Smckusick return (1); 189*41488Smckusick } 190*41488Smckusick 191*41488Smckusick static int 192*41488Smckusick ixfer_out(hd, len, buf) 193*41488Smckusick volatile register struct scsidevice *hd; 194*41488Smckusick int len; 195*41488Smckusick register u_char *buf; 196*41488Smckusick { 197*41488Smckusick register int wait = scsi_data_wait; 198*41488Smckusick 199*41488Smckusick for (; len > 0; --len) { 200*41488Smckusick while (hd->scsi_ssts & SSTS_DREG_FULL) { 201*41488Smckusick if (hd->scsi_ints || --wait < 0) 202*41488Smckusick return (len); 203*41488Smckusick DELAY(1); 204*41488Smckusick } 205*41488Smckusick hd->scsi_dreg = *buf++; 206*41488Smckusick } 207*41488Smckusick return (0); 208*41488Smckusick } 209*41488Smckusick 210*41488Smckusick static int 211*41488Smckusick ixfer_in(hd, len, buf) 212*41488Smckusick volatile register struct scsidevice *hd; 213*41488Smckusick int len; 214*41488Smckusick register u_char *buf; 215*41488Smckusick { 216*41488Smckusick register int wait = scsi_data_wait; 217*41488Smckusick 218*41488Smckusick for (; len > 0; --len) { 219*41488Smckusick while (hd->scsi_ssts & SSTS_DREG_EMPTY) { 220*41488Smckusick if (hd->scsi_ints || --wait < 0) { 221*41488Smckusick while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) { 222*41488Smckusick *buf++ = hd->scsi_dreg; 223*41488Smckusick --len; 224*41488Smckusick } 225*41488Smckusick return (len); 226*41488Smckusick } 227*41488Smckusick DELAY(1); 228*41488Smckusick } 229*41488Smckusick *buf++ = hd->scsi_dreg; 230*41488Smckusick } 231*41488Smckusick return (len); 232*41488Smckusick } 233*41488Smckusick 234*41488Smckusick static int 235*41488Smckusick scsiicmd(hs, target, cbuf, clen, buf, len, xferphase) 236*41488Smckusick struct scsi_softc *hs; 237*41488Smckusick int target; 238*41488Smckusick u_char *cbuf; 239*41488Smckusick int clen; 240*41488Smckusick u_char *buf; 241*41488Smckusick int len; 242*41488Smckusick u_char xferphase; 243*41488Smckusick { 244*41488Smckusick volatile register struct scsidevice *hd = 245*41488Smckusick (struct scsidevice *)hs->sc_addr; 246*41488Smckusick int i; 247*41488Smckusick u_char phase, ints; 248*41488Smckusick register int wait; 249*41488Smckusick 250*41488Smckusick /* select the SCSI bus (it's an error if bus isn't free) */ 251*41488Smckusick if (issue_select(hd, target, hs->sc_scsi_addr)) 252*41488Smckusick return (0); 253*41488Smckusick if (wait_for_select(hd)) 254*41488Smckusick return (0); 255*41488Smckusick /* 256*41488Smckusick * Wait for a phase change (or error) then let the device 257*41488Smckusick * sequence us through the various SCSI phases. 258*41488Smckusick */ 259*41488Smckusick phase = CMD_PHASE; 260*41488Smckusick while (1) { 261*41488Smckusick wait = scsi_cmd_wait; 262*41488Smckusick switch (phase) { 263*41488Smckusick 264*41488Smckusick case CMD_PHASE: 265*41488Smckusick if (ixfer_start(hd, clen, phase, wait)) 266*41488Smckusick if (ixfer_out(hd, clen, cbuf)) 267*41488Smckusick goto abort; 268*41488Smckusick phase = xferphase; 269*41488Smckusick break; 270*41488Smckusick 271*41488Smckusick case DATA_IN_PHASE: 272*41488Smckusick if (len <= 0) 273*41488Smckusick goto abort; 274*41488Smckusick wait = scsi_data_wait; 275*41488Smckusick if (ixfer_start(hd, len, phase, wait) || 276*41488Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 277*41488Smckusick ixfer_in(hd, len, buf); 278*41488Smckusick phase = STATUS_PHASE; 279*41488Smckusick break; 280*41488Smckusick 281*41488Smckusick case DATA_OUT_PHASE: 282*41488Smckusick if (len <= 0) 283*41488Smckusick goto abort; 284*41488Smckusick wait = scsi_data_wait; 285*41488Smckusick if (ixfer_start(hd, len, phase, wait)) 286*41488Smckusick if (ixfer_out(hd, len, buf)) 287*41488Smckusick goto abort; 288*41488Smckusick phase = STATUS_PHASE; 289*41488Smckusick break; 290*41488Smckusick 291*41488Smckusick case STATUS_PHASE: 292*41488Smckusick wait = scsi_data_wait; 293*41488Smckusick if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) || 294*41488Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 295*41488Smckusick ixfer_in(hd, sizeof(hs->sc_stat), &hs->sc_stat); 296*41488Smckusick phase = MESG_IN_PHASE; 297*41488Smckusick break; 298*41488Smckusick 299*41488Smckusick case MESG_IN_PHASE: 300*41488Smckusick if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) || 301*41488Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { 302*41488Smckusick ixfer_in(hd, sizeof(hs->sc_msg), &hs->sc_msg); 303*41488Smckusick hd->scsi_scmd = SCMD_RST_ACK; 304*41488Smckusick } 305*41488Smckusick phase = BUS_FREE_PHASE; 306*41488Smckusick break; 307*41488Smckusick 308*41488Smckusick case BUS_FREE_PHASE: 309*41488Smckusick return (1); 310*41488Smckusick 311*41488Smckusick default: 312*41488Smckusick printf("unexpected scsi phase %d\n", phase); 313*41488Smckusick goto abort; 314*41488Smckusick } 315*41488Smckusick /* wait for last command to complete */ 316*41488Smckusick while ((ints = hd->scsi_ints) == 0) { 317*41488Smckusick if (--wait < 0) 318*41488Smckusick goto abort; 319*41488Smckusick DELAY(1); 320*41488Smckusick } 321*41488Smckusick hd->scsi_ints = ints; 322*41488Smckusick if (ints & INTS_SRV_REQ) 323*41488Smckusick phase = hd->scsi_psns & PHASE; 324*41488Smckusick else if (ints & INTS_DISCON) 325*41488Smckusick return (1); 326*41488Smckusick else if ((ints & INTS_CMD_DONE) == 0) { 327*41488Smckusick goto abort; 328*41488Smckusick } 329*41488Smckusick } 330*41488Smckusick abort: 331*41488Smckusick scsiabort(hs, hd); 332*41488Smckusick return (0); 333*41488Smckusick } 334*41488Smckusick 335*41488Smckusick int 336*41488Smckusick scsi_test_unit_rdy(unit) 337*41488Smckusick { 338*41488Smckusick int ctlr = scsiunit(unit); 339*41488Smckusick int slave = scsislave(unit); 340*41488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 341*41488Smckusick static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY }; 342*41488Smckusick 343*41488Smckusick if (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0, 344*41488Smckusick STATUS_PHASE) == 0) 345*41488Smckusick return (0); 346*41488Smckusick 347*41488Smckusick return (hs->sc_stat == 0); 348*41488Smckusick } 349*41488Smckusick 350*41488Smckusick int 351*41488Smckusick scsi_request_sense(unit, buf, len) 352*41488Smckusick int unit; 353*41488Smckusick u_char *buf; 354*41488Smckusick unsigned len; 355*41488Smckusick { 356*41488Smckusick int ctlr = scsiunit(unit); 357*41488Smckusick int slave = scsislave(unit); 358*41488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 359*41488Smckusick static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE }; 360*41488Smckusick 361*41488Smckusick cdb.len = len; 362*41488Smckusick return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE)); 363*41488Smckusick } 364*41488Smckusick 365*41488Smckusick int 366*41488Smckusick scsi_read_capacity(unit, buf, len) 367*41488Smckusick int unit; 368*41488Smckusick u_char *buf; 369*41488Smckusick unsigned len; 370*41488Smckusick { 371*41488Smckusick int ctlr = scsiunit(unit); 372*41488Smckusick int slave = scsislave(unit); 373*41488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 374*41488Smckusick static struct scsi_cdb10 cdb = { CMD_READ_CAPACITY }; 375*41488Smckusick 376*41488Smckusick return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE)); 377*41488Smckusick } 378*41488Smckusick 379*41488Smckusick int 380*41488Smckusick scsi_tt_read(unit, buf, len, blk, nblk) 381*41488Smckusick int unit; 382*41488Smckusick u_char *buf; 383*41488Smckusick u_int len; 384*41488Smckusick daddr_t blk; 385*41488Smckusick u_int nblk; 386*41488Smckusick { 387*41488Smckusick int ctlr = scsiunit(unit); 388*41488Smckusick int slave = scsislave(unit); 389*41488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 390*41488Smckusick struct scsi_cdb10 cdb; 391*41488Smckusick int stat; 392*41488Smckusick 393*41488Smckusick bzero(&cdb, sizeof(cdb)); 394*41488Smckusick cdb.cmd = CMD_READ_EXT; 395*41488Smckusick cdb.lbah = blk >> 24; 396*41488Smckusick cdb.lbahm = blk >> 16; 397*41488Smckusick cdb.lbalm = blk >> 8; 398*41488Smckusick cdb.lbal = blk; 399*41488Smckusick cdb.lenh = nblk >> (8 + DEV_BSHIFT); 400*41488Smckusick cdb.lenl = nblk >> DEV_BSHIFT; 401*41488Smckusick stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE); 402*41488Smckusick if (stat == 0) 403*41488Smckusick return (1); 404*41488Smckusick return (hs->sc_stat); 405*41488Smckusick } 406*41488Smckusick 407*41488Smckusick int 408*41488Smckusick scsi_tt_write(unit, buf, len, blk, nblk) 409*41488Smckusick int unit; 410*41488Smckusick u_char *buf; 411*41488Smckusick u_int len; 412*41488Smckusick daddr_t blk; 413*41488Smckusick u_int nblk; 414*41488Smckusick { 415*41488Smckusick int ctlr = scsiunit(unit); 416*41488Smckusick int slave = scsislave(unit); 417*41488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 418*41488Smckusick struct scsi_cdb10 cdb; 419*41488Smckusick int stat; 420*41488Smckusick 421*41488Smckusick bzero(&cdb, sizeof(cdb)); 422*41488Smckusick cdb.cmd = CMD_WRITE_EXT; 423*41488Smckusick cdb.lbah = blk >> 24; 424*41488Smckusick cdb.lbahm = blk >> 16; 425*41488Smckusick cdb.lbalm = blk >> 8; 426*41488Smckusick cdb.lbal = blk; 427*41488Smckusick cdb.lenh = nblk >> (8 + DEV_BSHIFT); 428*41488Smckusick cdb.lenl = nblk >> DEV_BSHIFT; 429*41488Smckusick stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE); 430*41488Smckusick if (stat == 0) 431*41488Smckusick return (1); 432*41488Smckusick return (hs->sc_stat); 433*41488Smckusick } 434