📄 sc.c
字号:
if (ints & INTS_DISCON) { if (hs->sc_msg[0] == MSG_CMD_COMPLETE) { hd->scsi_ints = ints; if (hs->sc_lock != NULL) { *(hs->sc_lock) = SC_IO_COMPLETE; } else { (dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat); } return;#ifndef NODISCONNECT } else if (hs->sc_msg[0] == MSG_DISCONNECT) {#ifdef DEBUGPRINT dbgprintf("scintr: DISCONNECT : ctlr = %d, slave = %d, cdb = %s\n", dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0]));#endif hd->scsi_ints = ints; scpend(dq); dq = hs->sc_sq.dq_forw; if (dq != &hs->sc_sq) (dq->dq_driver->d_start)(dq->dq_unit); return;#endif } else goto abort;#ifndef NODISCONNECT } else if (ints & INTS_RESEL) { temp = hd->scsi_temp & ~(1 << SCSI_ID); for (slave = 0; temp != 1; slave++) { temp >>= 1; } hd->scsi_ints = ints; scrschdl(ctlr, slave); dq = hs->sc_sq.dq_forw;#ifdef DEBUGPRINT dbgprintf("\n"); dbgprintf("scintr: RESELECT : ctlr = %d, slave = %d, cdb = %s\n", dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0]));#endif#endif } else if (ints & INTS_CMD_DONE) { if (hs->sc_phase == BUS_FREE_PHASE) goto abort; else if (hs->sc_phase == MESG_IN_PHASE) { hd->scsi_scmd = SCMD_RST_ACK; if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || (hs->sc_msg[0] == MSG_DISCONNECT)) { hd->scsi_ints = ints; hs->sc_phase = BUS_FREE_PHASE; return; } } if (hs->sc_flags & SC_SEL_TIMEOUT) hs->sc_flags &= ~SC_SEL_TIMEOUT; } else if (ints & INTS_SRV_REQ) { if (hs->sc_phase != MESG_IN_PHASE) goto abort; } else if (ints & INTS_TIMEOUT) { if (hs->sc_phase == ARB_SEL_PHASE) { if (hs->sc_flags & SC_SEL_TIMEOUT) { hd->scsi_ints = ints; hs->sc_flags &= ~SC_SEL_TIMEOUT; /* Such SCSI Device is not conected. */ if (hs->sc_lock != NULL) { *(hs->sc_lock) = SC_DEV_NOT_FOUND; } else { (dq->dq_driver->d_intr)(dq->dq_unit, SC_DEV_NOT_FOUND); } return; } else { /* wait more 250 usec */ hs->sc_flags |= SC_SEL_TIMEOUT; hd->scsi_temp = 0; hd->scsi_tch = 0; hd->scsi_tcm = 0x06; hd->scsi_tcl = 0x40; hd->scsi_ints = ints; return; } } else goto abort; } else goto abort; hd->scsi_ints = ints; /* * Next SCSI Transfer */ wait = SC_TIMEOUT; while ((hd->scsi_psns & PSNS_REQ) == 0) { if (wait < 0) {/* hd->scsi_scmd = SCMD_SET_ATN; */ hd->scsi_scmd = SCMD_RST; DELAY(40); /* wait 25 micro sec */ hd->scsi_scmd = 0; wait = SC_TIMEOUT; while (wait-- > 0) DELAY(1); if (hs->sc_lock != NULL) { *(hs->sc_lock) = SC_IO_TIMEOUT; } else { (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT); } return; } DELAY(1); wait--; } hs->sc_phase = hd->scsi_psns & PHASE;#ifdef DEBUGPRINT dbgprintf("scintr: %s\n", phase_name(hs->sc_phase));#endif if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) { len = ( hs->sc_lock != NULL ? hs->sc_len : dq->dq_bp->b_bcount ); buf = ( hs->sc_lock != NULL ? hs->sc_buf : (u_char *) dq->dq_bp->b_un.b_addr ); } else if (hs->sc_phase == CMD_PHASE) { len = ( hs->sc_lock != NULL ? hs->sc_cdblen : dq->dq_cdb->len ); buf = ( hs->sc_lock != NULL ? hs->sc_cdb : dq->dq_cdb->cdb ); } else if (hs->sc_phase == STATUS_PHASE) { len = 1; buf = &hs->sc_stat; } else { if (hs->sc_phase == MESG_OUT_PHASE) {#ifndef NODISCONNECT hs->sc_msg[0] = MSG_IDENTIFY_DR;#else hs->sc_msg[0] = MSG_IDENTIFY;#endif } len = 1; buf = hs->sc_msg; }#ifdef XFER_ENABLE if ((hs->sc_lock == NULL) && (hs->sc_phase == DATA_IN_PHASE)) { dq->dq_xferp = buf; dq->dq_xfercnt = len; txfer_start(hd, len, hs->sc_phase); return; }#endif ixfer_start(hd, len, hs->sc_phase); if (hs->sc_phase & PHASE_IO) { if ((wait = ixfer_in(hd, len, buf)) == -1) { goto time_out; } if (dq->dq_imin == -1) dq->dq_imin = wait; else dq->dq_imin = min(wait, dq->dq_imin); dq->dq_imax = max(wait, dq->dq_imax); } else { if ((wait = ixfer_out(hd, len, buf)) == -1) { goto time_out; } if (dq->dq_omin == -1) dq->dq_omin = wait; else dq->dq_omin = min(wait, dq->dq_omin); dq->dq_omax = max(wait, dq->dq_omax); } return; time_out: scabort(hs, hd); printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); if (hs->sc_lock != NULL) { *(hs->sc_lock) = SC_IO_TIMEOUT; } else { (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT); } return; /* * SCSI Abort */ abort: /* SCSI IO failed */ scabort(hs, hd); hd->scsi_ints = ints; if (hs->sc_lock != NULL) { *(hs->sc_lock) = SC_IO_FAILED; } else { (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_FAILED); } return;}intscabort(hs, hd) register struct sc_softc *hs; volatile register struct scsidevice *hd;{ int len; u_char junk;#ifdef DEBUGPRINT dbgprintall(); printf("\n");#endif printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); if (hd->scsi_ints != 0) hd->scsi_ints = hd->scsi_ints; printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset INTS reg.\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0) /* no longer connected to scsi target */ return; /* get the number of bytes remaining in current xfer + fudge */ len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl; printf("scabort: Current xfer count = %d\n", len); /* for that many bus cycles, try to send an abort msg */ for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {/* hd->scsi_scmd = SCMD_SET_ATN; printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ATN\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); */ while ((hd->scsi_psns & PSNS_REQ) == 0) { printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); if (! (hd->scsi_ssts & SSTS_INITIATOR)) goto out; DELAY(1); }/* if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) { hd->scsi_scmd = SCMD_RST_ATN; printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ATN\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); } */ hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE; printf("scabort: Phase = %s\n", phase_name(hs->sc_phase)); if (hd->scsi_psns & PHASE_IO) { /* one of the input phases - read & discard a byte */ hd->scsi_scmd = SCMD_SET_ACK; printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); while (hd->scsi_psns & PSNS_REQ) { printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); DELAY(1); } junk = hd->scsi_temp; printf("scabort: TEMP = 0x%s\n", hexstr(junk, 2)); } else { /* one of the output phases - send an abort msg */ hd->scsi_temp = MSG_ABORT; hd->scsi_scmd = SCMD_SET_ACK; printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); while (hd->scsi_psns & PSNS_REQ) { printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); DELAY(1); } } hd->scsi_scmd = SCMD_RST_ACK; printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ACK\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); }out: /* * Either the abort was successful & the bus is disconnected or * the device didn't listen. If the latter, announce the problem. * Either way, reset the card & the SPC. */ if (len < 0 && hs) printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n", hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts); while (hd->scsi_ints == 0) DELAY(1); hd->scsi_ints = hd->scsi_ints; printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); printf("scabort: SCSI abort operation is done\n");}/* * SPC device queue handling */intscreq(dq) register struct scsi_queue *dq;{ register struct sc_softc *hs = &sc_softc[dq->dq_ctlr]; register struct scsi_queue *hq = &hs->sc_sq; insque(dq, hq->dq_back); if (dq->dq_back == hq) {#ifdef QUE_DEBUG printf("screq: slave = %d, command = %s\n", hq->dq_forw->dq_slave, scsi_command(hq->dq_forw->dq_cdb->cdb[0]));#endif return(1); } return(0);}#ifndef NODISCONNECTintscpend(dq) register struct scsi_queue *dq;{ register struct sc_softc *hs = &sc_softc[dq->dq_ctlr]; register struct scsi_queue *hq = &hs->sc_sq; register struct scsi_queue *wq = &hs->sc_wq; remque(dq); insque(dq, wq->dq_back);}intscrschdl(ctlr, slave) register int ctlr; register int slave;{ register struct sc_softc *hs = &sc_softc[ctlr]; register struct scsi_queue *wq = &hs->sc_wq; register struct scsi_queue *hq = &hs->sc_sq; register struct scsi_queue *dq; for (dq = wq->dq_forw; dq != wq; dq = dq->dq_forw) { if (dq->dq_slave == slave) goto found; } return(0); found: remque(dq); insque(dq, hq); return(1);}#endifintscfree(dq) register struct scsi_queue *dq;{ register struct sc_softc *hs = &sc_softc[dq->dq_ctlr]; register struct scsi_queue *hq = &hs->sc_sq; int status = hs->sc_stat; remque(dq); hs->sc_flags = 0; hs->sc_phase = BUS_FREE_PHASE; hs->sc_stat = 0; hs->sc_msg[0] = 0; if ((dq = hq->dq_forw) != hq) {#ifdef QUE_DEBUG printf("scfree: slave = %d, command = %s\n", dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0]));#endif (dq->dq_driver->d_start)(dq->dq_unit); } return(status);}/* * SCSI common interface */int scsi_lock[NSC];intscsi_result(unit, stat) int unit, stat;{#ifdef SCSI_DEBUG printf("scsi_result: stat = %s\n", scsi_status(stat));#endif if (stat < 0) scsi_lock[unit] = stat; else scsi_lock[unit] = SC_IO_COMPLETE;}struct driver scsi_driver = { (int (*)()) 0, "scsi", (int (*)()) 0, (int (*)()) 0, scsi_result, (int (*)()) 0};struct scsi_queue scsi_entry[NSC];intscsi_immed_command(ctlr, slave, lun, cdb, buf, len) int ctlr, slave, lun; struct scsi_fmt_cdb *cdb; u_char *buf; unsigned len;{ register struct sc_softc *hs = &sc_softc[ctlr]; volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr; register struct scsi_queue *dq = &scsi_entry[ctlr]; register struct buf *bp; int s, status, wait = 30;#ifdef SCSI_DEBUG printf("scsi_immed_command( %d, %d, %d, cdb(%d,%s), buf, %d): Start\n", ctlr, slave, lun, cdb->len, scsi_command(cdb->cdb[0]), len);#endif bp = geteblk(len); bp->b_flags = B_BUSY; s = splbio(); dq->dq_unit = ctlr; dq->dq_ctlr = ctlr; dq->dq_slave = slave; dq->dq_driver = &scsi_driver; dq->dq_cdb = cdb; dq->dq_bp = bp; scsi_lock[ctlr] = SC_IN_PROGRESS; if (screq(dq)) scstart(ctlr); splx(s); while (scsi_lock[ctlr] == SC_IN_PROGRESS) { if (wait < 0) { scabort(hs, hd); s = splbio(); status = scfree(dq); splx(s); bp->b_flags = 0; return(SC_IO_FAILED); } DELAY(100000); wait--; } s = splbio(); status = scfree(dq); splx(s); if (scsi_lock[ctlr] < 0) status = scsi_lock[ctlr]; bcopy(bp->b_un.b_addr, buf, len); brelse(bp);#ifdef SCSI_DEBUG printf("scsi_immed_command: Status -- 0x%x\n", status);#endif return(status);}intsc_test_unit_rdy(ctlr, slave, lun) int ctlr, slave, lun;{ static struct scsi_fmt_cdb cdb = { 6, CMD_TEST_UNIT_READY }; int stat; while ((stat = scsi_immed_command(ctlr, slave, lun, &cdb, (u_char *) 0, 0)) == SC_BUSY) { DELAY(10000); } return(stat);}intsc_request_sense(ctlr, slave, lun, buf, len) int ctlr, slave, lun; u_char *buf; unsigned len;{ register struct sc_softc *hs = &sc_softc[ctlr]; volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr; static struct scsi_fmt_cdb req_cmd = { 6, CMD_REQUEST_SENSE }; int s, status, lock;#ifdef REQ_DEBUG printf("sc_request_sense( %d, %d, %d, buf, %d) -- Start\n", ctlr, slave, lun, len);#endif req_cmd.cdb[1] = lun; req_cmd.cdb[4] = len; if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) return(0); s = splbio(); hs->sc_flags = 0; hs->sc_phase = ARB_SEL_PHASE; hs->sc_cdb = req_cmd.cdb; hs->sc_cdblen = req_cmd.len; hs->sc_buf = buf; hs->sc_len = len; hs->sc_stat = 0; hs->sc_msg[0] = 0; lock = SC_IN_PROGRESS; hs->sc_lock = &lock; issue_select(hd, slave, 0); spl0(); while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) DELAY(10); splbio(); hs->sc_flags = 0; hs->sc_phase = BUS_FREE_PHASE; hs->sc_cdb = NULL; hs->sc_cdblen = 0; hs->sc_buf = NULL; hs->sc_len = 0; hs->sc_lock = NULL; status = hs->sc_stat; hs->sc_stat = 0; hs->sc_msg[0] = 0; splx(s); if (lock == SC_IO_COMPLETE) {#ifdef REQ_DEBUG printf("sc_request_sense: Status -- 0x%x\n", status);#endif return(status); } else { return(lock); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -