⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -