141488Smckusick /* 241488Smckusick * Copyright (c) 1988 University of Utah. 341488Smckusick * Copyright (c) 1990 The Regents of the University of California. 441488Smckusick * All rights reserved. 541488Smckusick * 641488Smckusick * This code is derived from software contributed to Berkeley by 741488Smckusick * Van Jacobson of Lawrence Berkeley Laboratory and the Systems 841488Smckusick * Programming Group of the University of Utah Computer Science Department. 941488Smckusick * 1041488Smckusick * %sccs.include.redist.c% 1141488Smckusick * 1241488Smckusick * from: Utah $Hdr: scsi.c 1.3 90/01/27$ 1341488Smckusick * 14*54073Shibler * @(#)scsi.c 7.5 (Berkeley) 06/18/92 1541488Smckusick */ 1641488Smckusick 1741488Smckusick /* 1841488Smckusick * SCSI bus driver for standalone programs. 1941488Smckusick */ 2041488Smckusick 21*54073Shibler #include "sys/param.h" 22*54073Shibler #include "sys/reboot.h" 23*54073Shibler #include "hp/dev/device.h" 2445790Sbostic #include "../dev/scsireg.h" 2541488Smckusick #include "scsivar.h" 2641488Smckusick 2741488Smckusick #include "saio.h" 2841488Smckusick #include "samachdep.h" 2941488Smckusick 3041488Smckusick struct scsi_softc scsi_softc[NSCSI]; 3141488Smckusick 3241488Smckusick void scsireset(); 33*54073Shibler int scsi_cmd_wait = 50000; /* use the "real" driver init_wait value */ 34*54073Shibler int scsi_data_wait = 50000; /* use the "real" driver init_wait value */ 3541488Smckusick 3641488Smckusick scsiinit() 3741488Smckusick { 3841488Smckusick extern struct hp_hw sc_table[]; 3941488Smckusick register struct hp_hw *hw; 4041488Smckusick register struct scsi_softc *hs; 4141488Smckusick register int i, addr; 42*54073Shibler static int waitset = 0; 4341488Smckusick 4441488Smckusick i = 0; 4549334Shibler for (hw = sc_table; i < NSCSI && hw < &sc_table[MAXCTLRS]; hw++) { 4649334Shibler if (!HW_ISSCSI(hw)) 4741488Smckusick continue; 4841488Smckusick hs = &scsi_softc[i]; 4949334Shibler hs->sc_addr = hw->hw_kva; 5041488Smckusick scsireset(i); 5141488Smckusick if (howto & RB_ASKNAME) 5241488Smckusick printf("scsi%d at sc%d\n", i, hw->hw_sc); 53*54073Shibler hw->hw_pa = (caddr_t) i; /* XXX for autoconfig */ 5441488Smckusick hs->sc_alive = 1; 5541488Smckusick i++; 5641488Smckusick } 57*54073Shibler /* 58*54073Shibler * Adjust the wait values 59*54073Shibler */ 60*54073Shibler if (!waitset) { 61*54073Shibler scsi_cmd_wait *= cpuspeed; 62*54073Shibler scsi_data_wait *= cpuspeed; 63*54073Shibler waitset = 1; 64*54073Shibler } 6541488Smckusick } 6641488Smckusick 6741488Smckusick scsialive(unit) 6841488Smckusick register int unit; 6941488Smckusick { 7041488Smckusick if (unit >= NSCSI || scsi_softc[unit].sc_alive == 0) 7141488Smckusick return (0); 7241488Smckusick return (1); 7341488Smckusick } 7441488Smckusick 7541488Smckusick void 7641488Smckusick scsireset(unit) 7741488Smckusick register int unit; 7841488Smckusick { 7941488Smckusick volatile register struct scsidevice *hd; 8041488Smckusick register struct scsi_softc *hs; 8141488Smckusick u_int i; 8241488Smckusick 8341488Smckusick hs = &scsi_softc[unit]; 8441488Smckusick hd = (struct scsidevice *)hs->sc_addr; 8541488Smckusick hd->scsi_id = 0xFF; 8641488Smckusick DELAY(100); 8741488Smckusick /* 8841488Smckusick * Disable interrupts then reset the FUJI chip. 8941488Smckusick */ 9041488Smckusick hd->scsi_csr = 0; 9141488Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; 9241488Smckusick hd->scsi_scmd = 0; 9341488Smckusick hd->scsi_tmod = 0; 9441488Smckusick hd->scsi_pctl = 0; 9541488Smckusick hd->scsi_temp = 0; 9641488Smckusick hd->scsi_tch = 0; 9741488Smckusick hd->scsi_tcm = 0; 9841488Smckusick hd->scsi_tcl = 0; 9941488Smckusick hd->scsi_ints = 0; 10041488Smckusick 10141488Smckusick /* 10241488Smckusick * Configure the FUJI chip with its SCSI address, all 10341488Smckusick * interrupts enabled & appropriate parity. 10441488Smckusick */ 10541488Smckusick i = (~hd->scsi_hconf) & 0x7; 10641488Smckusick hs->sc_scsi_addr = 1 << i; 10741488Smckusick hd->scsi_bdid = i; 10841488Smckusick if (hd->scsi_hconf & HCONF_PARITY) 10941488Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 11041488Smckusick SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 11141488Smckusick SCTL_INTR_ENAB | SCTL_PARITY_ENAB; 11241488Smckusick else 11341488Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 11441488Smckusick SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 11541488Smckusick SCTL_INTR_ENAB; 11641488Smckusick hd->scsi_sctl &=~ SCTL_DISABLE; 11741488Smckusick } 11841488Smckusick 11941488Smckusick 12041488Smckusick int 12141488Smckusick scsiabort(hs, hd) 12241488Smckusick register struct scsi_softc *hs; 12341488Smckusick volatile register struct scsidevice *hd; 12441488Smckusick { 125*54073Shibler printf("scsi%d error: scsiabort\n", hs - scsi_softc); 126*54073Shibler 127*54073Shibler scsireset(hs - scsi_softc); 12841488Smckusick return (0); 12941488Smckusick } 13041488Smckusick 13141488Smckusick static int 13241488Smckusick issue_select(hd, target, our_addr) 13341488Smckusick volatile register struct scsidevice *hd; 13441488Smckusick u_char target, our_addr; 13541488Smckusick { 13641488Smckusick if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) 13741488Smckusick return (1); 13841488Smckusick 13941488Smckusick if (hd->scsi_ints & INTS_DISCON) 14041488Smckusick hd->scsi_ints = INTS_DISCON; 14141488Smckusick 14241488Smckusick hd->scsi_pctl = 0; 14341488Smckusick hd->scsi_temp = (1 << target) | our_addr; 14441488Smckusick /* select timeout is hardcoded to 2ms */ 14541488Smckusick hd->scsi_tch = 0; 14641488Smckusick hd->scsi_tcm = 32; 14741488Smckusick hd->scsi_tcl = 4; 14841488Smckusick 14941488Smckusick hd->scsi_scmd = SCMD_SELECT; 15041488Smckusick return (0); 15141488Smckusick } 15241488Smckusick 15341488Smckusick static int 15441488Smckusick wait_for_select(hd) 15541488Smckusick volatile register struct scsidevice *hd; 15641488Smckusick { 157*54073Shibler register int wait; 15841488Smckusick u_char ints; 15941488Smckusick 160*54073Shibler wait = scsi_data_wait; 161*54073Shibler while ((ints = hd->scsi_ints) == 0) { 162*54073Shibler if (--wait < 0) 163*54073Shibler return (1); 16441488Smckusick DELAY(1); 165*54073Shibler } 16641488Smckusick hd->scsi_ints = ints; 16741488Smckusick return (!(hd->scsi_ssts & SSTS_INITIATOR)); 16841488Smckusick } 16941488Smckusick 17041488Smckusick static int 17141488Smckusick ixfer_start(hd, len, phase, wait) 17241488Smckusick volatile register struct scsidevice *hd; 17341488Smckusick int len; 17441488Smckusick u_char phase; 17541488Smckusick register int wait; 17641488Smckusick { 17741488Smckusick 17841488Smckusick hd->scsi_tch = len >> 16; 17941488Smckusick hd->scsi_tcm = len >> 8; 18041488Smckusick hd->scsi_tcl = len; 18141488Smckusick hd->scsi_pctl = phase; 18241488Smckusick hd->scsi_tmod = 0; /*XXX*/ 18341488Smckusick hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 18441488Smckusick 18541488Smckusick /* wait for xfer to start or svc_req interrupt */ 18641488Smckusick while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 18741488Smckusick if (hd->scsi_ints || --wait < 0) 18841488Smckusick return (0); 18941488Smckusick DELAY(1); 19041488Smckusick } 19141488Smckusick return (1); 19241488Smckusick } 19341488Smckusick 19441488Smckusick static int 19541488Smckusick ixfer_out(hd, len, buf) 19641488Smckusick volatile register struct scsidevice *hd; 19741488Smckusick int len; 19841488Smckusick register u_char *buf; 19941488Smckusick { 20041488Smckusick register int wait = scsi_data_wait; 20141488Smckusick 20241488Smckusick for (; len > 0; --len) { 20341488Smckusick while (hd->scsi_ssts & SSTS_DREG_FULL) { 20441488Smckusick if (hd->scsi_ints || --wait < 0) 20541488Smckusick return (len); 20641488Smckusick DELAY(1); 20741488Smckusick } 20841488Smckusick hd->scsi_dreg = *buf++; 20941488Smckusick } 21041488Smckusick return (0); 21141488Smckusick } 21241488Smckusick 21341488Smckusick static int 21441488Smckusick ixfer_in(hd, len, buf) 21541488Smckusick volatile register struct scsidevice *hd; 21641488Smckusick int len; 21741488Smckusick register u_char *buf; 21841488Smckusick { 21941488Smckusick register int wait = scsi_data_wait; 22041488Smckusick 22141488Smckusick for (; len > 0; --len) { 22241488Smckusick while (hd->scsi_ssts & SSTS_DREG_EMPTY) { 22341488Smckusick if (hd->scsi_ints || --wait < 0) { 22441488Smckusick while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) { 22541488Smckusick *buf++ = hd->scsi_dreg; 22641488Smckusick --len; 22741488Smckusick } 22841488Smckusick return (len); 22941488Smckusick } 23041488Smckusick DELAY(1); 23141488Smckusick } 23241488Smckusick *buf++ = hd->scsi_dreg; 23341488Smckusick } 23441488Smckusick return (len); 23541488Smckusick } 23641488Smckusick 23741488Smckusick static int 23841488Smckusick scsiicmd(hs, target, cbuf, clen, buf, len, xferphase) 23941488Smckusick struct scsi_softc *hs; 24041488Smckusick int target; 24141488Smckusick u_char *cbuf; 24241488Smckusick int clen; 24341488Smckusick u_char *buf; 24441488Smckusick int len; 24541488Smckusick u_char xferphase; 24641488Smckusick { 24741488Smckusick volatile register struct scsidevice *hd = 24841488Smckusick (struct scsidevice *)hs->sc_addr; 24941488Smckusick u_char phase, ints; 25041488Smckusick register int wait; 25141488Smckusick 25241488Smckusick /* select the SCSI bus (it's an error if bus isn't free) */ 25341488Smckusick if (issue_select(hd, target, hs->sc_scsi_addr)) 254*54073Shibler return (-2); 25541488Smckusick if (wait_for_select(hd)) 256*54073Shibler return (-2); 25741488Smckusick /* 25841488Smckusick * Wait for a phase change (or error) then let the device 25941488Smckusick * sequence us through the various SCSI phases. 26041488Smckusick */ 261*54073Shibler hs->sc_stat = -1; 26241488Smckusick phase = CMD_PHASE; 26341488Smckusick while (1) { 26441488Smckusick wait = scsi_cmd_wait; 26541488Smckusick switch (phase) { 26641488Smckusick 26741488Smckusick case CMD_PHASE: 26841488Smckusick if (ixfer_start(hd, clen, phase, wait)) 26941488Smckusick if (ixfer_out(hd, clen, cbuf)) 27041488Smckusick goto abort; 27141488Smckusick phase = xferphase; 27241488Smckusick break; 27341488Smckusick 27441488Smckusick case DATA_IN_PHASE: 27541488Smckusick if (len <= 0) 27641488Smckusick goto abort; 27741488Smckusick wait = scsi_data_wait; 27841488Smckusick if (ixfer_start(hd, len, phase, wait) || 27941488Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 28041488Smckusick ixfer_in(hd, len, buf); 28141488Smckusick phase = STATUS_PHASE; 28241488Smckusick break; 28341488Smckusick 28441488Smckusick case DATA_OUT_PHASE: 28541488Smckusick if (len <= 0) 28641488Smckusick goto abort; 28741488Smckusick wait = scsi_data_wait; 28841488Smckusick if (ixfer_start(hd, len, phase, wait)) 28941488Smckusick if (ixfer_out(hd, len, buf)) 29041488Smckusick goto abort; 29141488Smckusick phase = STATUS_PHASE; 29241488Smckusick break; 29341488Smckusick 29441488Smckusick case STATUS_PHASE: 29541488Smckusick wait = scsi_data_wait; 29641488Smckusick if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) || 29741488Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 29841488Smckusick ixfer_in(hd, sizeof(hs->sc_stat), &hs->sc_stat); 29941488Smckusick phase = MESG_IN_PHASE; 30041488Smckusick break; 30141488Smckusick 30241488Smckusick case MESG_IN_PHASE: 30341488Smckusick if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) || 30441488Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { 30541488Smckusick ixfer_in(hd, sizeof(hs->sc_msg), &hs->sc_msg); 30641488Smckusick hd->scsi_scmd = SCMD_RST_ACK; 30741488Smckusick } 30841488Smckusick phase = BUS_FREE_PHASE; 30941488Smckusick break; 31041488Smckusick 31141488Smckusick case BUS_FREE_PHASE: 312*54073Shibler goto out; 31341488Smckusick 31441488Smckusick default: 315*54073Shibler printf("scsi%d: unexpected scsi phase %d\n", 316*54073Shibler hs - scsi_softc, phase); 31741488Smckusick goto abort; 31841488Smckusick } 319*54073Shibler #ifdef SLOWSCSI 320*54073Shibler /* 321*54073Shibler * XXX we have wierd transient problems with booting from 322*54073Shibler * slow scsi disks on fast machines. I have never been 323*54073Shibler * able to pin the problem down, but a large delay here 324*54073Shibler * seems to always work. 325*54073Shibler */ 326*54073Shibler DELAY(1000); 327*54073Shibler #endif 32841488Smckusick /* wait for last command to complete */ 32941488Smckusick while ((ints = hd->scsi_ints) == 0) { 33041488Smckusick if (--wait < 0) 33141488Smckusick goto abort; 33241488Smckusick DELAY(1); 33341488Smckusick } 33441488Smckusick hd->scsi_ints = ints; 33541488Smckusick if (ints & INTS_SRV_REQ) 33641488Smckusick phase = hd->scsi_psns & PHASE; 33741488Smckusick else if (ints & INTS_DISCON) 338*54073Shibler goto out; 339*54073Shibler else if ((ints & INTS_CMD_DONE) == 0) 34041488Smckusick goto abort; 34141488Smckusick } 34241488Smckusick abort: 34341488Smckusick scsiabort(hs, hd); 344*54073Shibler out: 345*54073Shibler return (hs->sc_stat); 34641488Smckusick } 34741488Smckusick 34841488Smckusick int 349*54073Shibler scsi_test_unit_rdy(ctlr, slave) 350*54073Shibler int ctlr, slave; 35141488Smckusick { 35241488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 35341488Smckusick static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY }; 35441488Smckusick 355*54073Shibler return (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0, 356*54073Shibler STATUS_PHASE)); 35741488Smckusick } 35841488Smckusick 35941488Smckusick int 360*54073Shibler scsi_request_sense(ctlr, slave, buf, len) 361*54073Shibler int ctlr, slave; 36241488Smckusick u_char *buf; 36341488Smckusick unsigned len; 36441488Smckusick { 36541488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 36641488Smckusick static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE }; 36741488Smckusick 36841488Smckusick cdb.len = len; 369*54073Shibler return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, 370*54073Shibler DATA_IN_PHASE)); 37141488Smckusick } 37241488Smckusick 37341488Smckusick int 374*54073Shibler scsi_read_capacity(ctlr, slave, buf, len) 375*54073Shibler int ctlr, slave; 37641488Smckusick u_char *buf; 37741488Smckusick unsigned len; 37841488Smckusick { 37941488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 38041488Smckusick static struct scsi_cdb10 cdb = { CMD_READ_CAPACITY }; 38141488Smckusick 382*54073Shibler return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, 383*54073Shibler DATA_IN_PHASE)); 38441488Smckusick } 38541488Smckusick 38641488Smckusick int 387*54073Shibler scsi_tt_read(ctlr, slave, buf, len, blk, nblk) 388*54073Shibler int ctlr, slave; 38941488Smckusick u_char *buf; 39041488Smckusick u_int len; 39141488Smckusick daddr_t blk; 39241488Smckusick u_int nblk; 39341488Smckusick { 39441488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 39541488Smckusick struct scsi_cdb10 cdb; 39641488Smckusick 39741488Smckusick bzero(&cdb, sizeof(cdb)); 39841488Smckusick cdb.cmd = CMD_READ_EXT; 39941488Smckusick cdb.lbah = blk >> 24; 40041488Smckusick cdb.lbahm = blk >> 16; 40141488Smckusick cdb.lbalm = blk >> 8; 40241488Smckusick cdb.lbal = blk; 40341488Smckusick cdb.lenh = nblk >> (8 + DEV_BSHIFT); 40441488Smckusick cdb.lenl = nblk >> DEV_BSHIFT; 405*54073Shibler return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, 406*54073Shibler DATA_IN_PHASE)); 40741488Smckusick } 40841488Smckusick 40941488Smckusick int 410*54073Shibler scsi_tt_write(ctlr, slave, buf, len, blk, nblk) 411*54073Shibler int ctlr, slave; 41241488Smckusick u_char *buf; 41341488Smckusick u_int len; 41441488Smckusick daddr_t blk; 41541488Smckusick u_int nblk; 41641488Smckusick { 41741488Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 41841488Smckusick struct scsi_cdb10 cdb; 41941488Smckusick 42041488Smckusick bzero(&cdb, sizeof(cdb)); 42141488Smckusick cdb.cmd = CMD_WRITE_EXT; 42241488Smckusick cdb.lbah = blk >> 24; 42341488Smckusick cdb.lbahm = blk >> 16; 42441488Smckusick cdb.lbalm = blk >> 8; 42541488Smckusick cdb.lbal = blk; 42641488Smckusick cdb.lenh = nblk >> (8 + DEV_BSHIFT); 42741488Smckusick cdb.lenl = nblk >> DEV_BSHIFT; 428*54073Shibler return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, 429*54073Shibler DATA_OUT_PHASE)); 43041488Smckusick } 431