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

📄 sc.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1992 OMRON Corporation. * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * OMRON Corporation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)sc.c	8.1 (Berkeley) 6/10/93 *//* * sc.c -- SCSI Protocole Controller (SPC)  driver * remaked by A.Fujita, MAR-11-199 */#define NSC	1#include <sys/param.h>#include <luna68k/dev/scsireg.h>#include <luna68k/stand/device.h>#include <luna68k/stand/scsivar.h>#define SCSI_IPL	2#define SCSI_ID		7int	scinit(), scstart(), scgo(), scintr(), scdone();void	screset();struct	driver scdriver = {	scinit, "sc", scstart, scgo, scintr, scdone};struct	scsi_softc scsi_softc[NSC];/* * Initialize SPC & Data Structure */intscinit(hc)	register struct hp_ctlr *hc;{	register struct scsi_softc *hs = &scsi_softc[hc->hp_unit];	register int i;	hc->hp_ipl    = SCSI_IPL;	hs->sc_hc     = hc;	hs->sc_flags  = 0;	hs->sc_phase  = BUS_FREE_PHASE;	hs->sc_target = SCSI_ID;	hs->sc_cdb    = NULL;	hs->sc_cdblen = 0;	hs->sc_buf    = NULL;	hs->sc_len    = 0;	hs->sc_lock   = NULL;	hs->sc_stat   = 0;	hs->sc_msg[0] = 0;	screset(hc->hp_unit);	return(1);}voidscreset(unit)	register int unit;{	register struct scsi_softc *hs = &scsi_softc[unit];	volatile register struct scsidevice *hd =				(struct scsidevice *)hs->sc_hc->hp_addr;	printf("sc%d: ", unit);	/*	 * Disable interrupts then reset the FUJI chip.	 */	hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;	hd->scsi_scmd = 0;	hd->scsi_pctl = 0;	hd->scsi_temp = 0;	hd->scsi_tch  = 0;	hd->scsi_tcm  = 0;	hd->scsi_tcl  = 0;	hd->scsi_ints = 0;	/* We can use Asynchronous Transfer only */	printf("async");	/*	 * Configure MB89352 with its SCSI address, all	 * interrupts enabled & appropriate parity.	 */	hd->scsi_bdid = SCSI_ID;	hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB|			SCTL_PARITY_ENAB | SCTL_RESEL_ENAB |			SCTL_INTR_ENAB;	printf(", parity");	DELAY(400);	hd->scsi_sctl &= ~SCTL_DISABLE;	printf(", scsi id %d\n", SCSI_ID);}/* * SPC Arbitration/Selection routine */intissue_select(hd, target)	volatile register struct scsidevice *hd;	u_char target;{	hd->scsi_pctl = 0;	hd->scsi_temp = (1 << SCSI_ID) | (1 << target);	/* select timeout is hardcoded to 2ms */	hd->scsi_tch = 0;	hd->scsi_tcm = 32;	hd->scsi_tcl = 4;	hd->scsi_scmd = SCMD_SELECT;	return (1);}/* * SPC Manual Transfer routines *//* not yet *//* * SPC Program Transfer routines */intixfer_start(hd, len, phase, wait)	volatile register struct scsidevice *hd;	int len;	u_char phase;	register int wait;{	hd->scsi_tch  = ((len & 0xff0000) >> 16);	hd->scsi_tcm  = ((len & 0x00ff00) >>  8);	hd->scsi_tcl  =  (len & 0x0000ff);	hd->scsi_pctl = phase;	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;}intixfer_out(hd, len, buf)	volatile register struct scsidevice *hd;	int len;	register u_char *buf;{	for(; len > 0; len--) {		while (hd->scsi_ssts & SSTS_DREG_FULL) {			DELAY(5);		}		hd->scsi_dreg = *buf++;	}}intixfer_in(hd, len, buf)	volatile register struct scsidevice *hd;	int len;	register u_char *buf;{	for (; len > 0; len--) {		int i;		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {			DELAY(5);		}		*buf++ = hd->scsi_dreg;	}}/* * SPC drive routines */intscrun(ctlr, slave, cdb, cdblen, buf, len, lock)	int ctlr, slave;	u_char *cdb;	int cdblen;	u_char *buf;	int len;	int *lock;{	register struct scsi_softc *hs = &scsi_softc[ctlr];	volatile register struct scsidevice *hd = 		(struct scsidevice *) hs->sc_hc->hp_addr;	if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))		return(0);	hs->sc_flags  = 0;	hs->sc_phase  = ARB_SEL_PHASE;	hs->sc_target = slave;	hs->sc_cdb    = cdb;	hs->sc_cdblen = cdblen;	hs->sc_buf    = buf;	hs->sc_len    = len;	hs->sc_lock   = lock;	hs->sc_stat   = 0;	hs->sc_msg[0] = 0;	*(hs->sc_lock) = SC_IN_PROGRESS;	issue_select(hd, hs->sc_target);	return(1);}intscfinish(ctlr)	int ctlr;{	register struct scsi_softc *hs = &scsi_softc[ctlr];	int status = hs->sc_stat;	hs->sc_flags  = 0;	hs->sc_phase  = BUS_FREE_PHASE;	hs->sc_target = SCSI_ID;	hs->sc_cdb    = NULL;	hs->sc_cdblen = 0;	hs->sc_buf    = NULL;	hs->sc_len    = 0;	hs->sc_lock   = NULL;	hs->sc_stat   = 0;	hs->sc_msg[0] = 0;	return(status);}intscabort(hs, hd)	register struct scsi_softc *hs;	volatile register struct scsidevice *hd;{	int len;	u_char junk;	printf("sc%d: abort  phase=0x%x, ssts=0x%x, ints=0x%x\n",		hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts,		hd->scsi_ints);	if (hd->scsi_ints != 0)		hd->scsi_ints = hd->scsi_ints;	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;	/* 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;		while ((hd->scsi_psns & PSNS_REQ) == 0) {			if (! (hd->scsi_ssts & SSTS_INITIATOR))				goto out;			DELAY(1);		}		if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)			hd->scsi_scmd = SCMD_RST_ATN;		hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;		if (hd->scsi_psns & PHASE_IO) {			/* one of the input phases - read & discard a byte */			hd->scsi_scmd = SCMD_SET_ACK;			while (hd->scsi_psns & PSNS_REQ)				DELAY(1);			junk = hd->scsi_temp;		} else {			/* one of the output phases - send an abort msg */			hd->scsi_temp = MSG_ABORT;			hd->scsi_scmd = SCMD_SET_ACK;			while (hd->scsi_psns & PSNS_REQ)				DELAY(1);		}		hd->scsi_scmd = SCMD_RST_ACK;	}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);}/* * SCSI Command Handler */intscsi_test_unit_rdy(ctlr, slave, unit)	int ctlr, slave, unit;{	static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };	int status, lock;#ifdef DEBUG	printf("scsi_test_unit_rdy( %d, %d, %d): Start\n", ctlr, slave, unit);#endif	cdb.lun = unit;	if (!(scrun(ctlr, slave, &cdb, 6, (u_char *) 0, 0, &lock))) {#ifdef DEBUG		printf("scsi_test_unit_rdy: Command Transfer Failed.\n");#endif		return(-1);	}	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))		DELAY(10);	status = scfinish(ctlr);	if (lock == SC_IO_COMPLETE) {#ifdef DEBUG		printf("scsi_test_unit_rdy: Status -- 0x%x\n", status);#endif		return(status);	} else {		return(lock);	}}intscsi_request_sense(ctlr, slave, unit, buf, len)	int ctlr, slave, unit;	u_char *buf;	unsigned len;{	static struct scsi_cdb6 cdb = {	CMD_REQUEST_SENSE };	int status, lock;#ifdef DEBUG	printf("scsi_request_sense: Start\n");#endif	/* Request Sense$N>l9g!"E>Aw$5$l$k%G!<%?D9$O%?!<%2368H$K0MB8$7!"        */	/* %;%s%9%G!<%?$N#8/usr/src/sys/luna68k/stand/SCCS/s.sc.c$%HL\$NAddtional Sens Length$K$h$jF0E*$K7hDj$9$k!#*/	/* $3$3$G$O%G!<%?!<E>Aw?t$rcdb$NAllocation Length$K:GDcD9$G$"$k#8/usr/src/sys/luna68k/stand/SCCS/s.sc.c$%H */	/* $r8GDj$7$F!"#S#P#C$N=hM}%7!<%1%s%9$rJx$5$J$$$h$&$K$7$F$$$k!#         */	/* %F!<@(#)sc.c	8.1f%K373H$N>uBV$rD4$Y$k$?$a!"Addtional Sens Field$r%"%/%;%9$9$k */	/* I,MW$,$"$k$N$G6/10/93P%$%98.1i%$%PB&$Glen$r7hDj$9$k$3$H$K$9$k            */	cdb.lun = unit;	cdb.len = len;	if (!(scrun(ctlr, slave, &cdb, 6, buf, len, &lock))) {#ifdef DEBUG		printf("scsi_request_sense: Command Transfer Failed.\n");#endif		return(-1);	}	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))		DELAY(10);	status = scfinish(ctlr);	if (lock == SC_IO_COMPLETE) {#ifdef DEBUG		printf("scsi_request_sense: Status -- 0x%x\n", status);#endif		return(status);	} else {		return(lock);	}}intscsi_immed_command(ctlr, slave, unit, cdb, buf, len)	int ctlr, slave, unit;	struct scsi_fmt_cdb *cdb;	u_char *buf;	unsigned len;{	int lock, status;#ifdef DEBUG	printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n",	       ctlr, slave, unit, cdb->len, len);#endif	cdb->cdb[1] |= unit << 5;	if (!(scrun(ctlr, slave, &cdb->cdb[0], cdb->len, buf, len, &lock))) {#ifdef DEBUG		printf("scsi_immed_command: Command Transfer Failed.\n");#endif		return(-1);	}	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))		DELAY(10);	status = scfinish(ctlr);	if (lock == SC_IO_COMPLETE) {#ifdef DEBUG		printf("scsi_immed_command: Status -- 0x%x\n", status);#endif		return(status);	} else {		return(lock);	}}intscsi_format_unit(ctlr, slave, unit)	int ctlr, slave, unit;{	static struct scsi_cdb6 cdb = { CMD_FORMAT_UNIT, 0, 0, 0, 0, 0 };	int status, lock, count = 0;#ifdef DEBUG	printf("scsi_format_unit( %d, %d, %d): Start\n", ctlr, slave, unit);#endif	cdb.lun = unit;	if (!(scrun(ctlr, slave, &cdb, 6, (u_char *) 0, 0, &lock))) {#ifdef DEBUG		printf("scsi_format_unit: Command Transfer Failed.\n");#endif		return(-1);	}	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {		DELAY(1000000);#ifdef DEBUG		if ((count % 60) == 0)			printf("scsi_format_unit: %d\n");#endif	}	status = scfinish(ctlr);	if (lock == SC_IO_COMPLETE) {#ifdef DEBUG		printf("scsi_format_unit: Status -- 0x%x\n", status);#endif		return(status);	} else {		return(lock);	}}/* * ???? */intscstart(){}intscgo(){}intscdone(){}/* * Interrupt Routine */intscintr(){	register struct scsi_softc *hs;	volatile register struct scsidevice *hd;	register u_char ints, temp;	register int i;	u_char *buf;	int len;	for (i = 0; i < NSC; i++) {		hs = &scsi_softc[i];		hd = (struct scsidevice *) hs->sc_hc->hp_addr;		if ((ints = hd->scsi_ints) != 0)			goto get_intr;	}	/* Unknown Interrupt occured */	return;	/*	 * Interrupt	 */ get_intr:#ifdef DEBUG	printf("scintr: INTS 0x%x, SSTS 0x%x,  PCTL 0x%x,  PSNS 0x%x    0x%x\n",	        ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns,	        hs->sc_phase);#endif	if (ints & INTS_RESEL) {		if (hs->sc_phase == BUS_FREE_PHASE) {			temp = hd->scsi_temp & ~(1 << SCSI_ID);			for (i = 0; temp != 1; i++) {				temp >>= 1;			}			hs->sc_target = i;			*(hs->sc_lock) = SC_IN_PROGRESS;		} else 			goto abort;	} else if (ints & INTS_DISCON) {		if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || (hs->sc_msg[0] == MSG_DISCONNECT)) {			hs->sc_phase  = BUS_FREE_PHASE;			hs->sc_target = SCSI_ID;			if (hs->sc_msg[0] == MSG_CMD_COMPLETE) 				/* SCSI IO complete */				*(hs->sc_lock) = SC_IO_COMPLETE;			else				/* Cisconnected from Target */				*(hs->sc_lock) = SC_DISCONNECTED;			hd->scsi_ints = ints;			return;		} else			goto abort;	} 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;			hd->scsi_ints = ints;			hs->sc_phase  = hd->scsi_psns & 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) {				hs->sc_flags &= ~SC_SEL_TIMEOUT;				hs->sc_phase  = BUS_FREE_PHASE;				hs->sc_target = SCSI_ID;				/* Such SCSI Device is not conected. */				*(hs->sc_lock) = SC_DEV_NOT_FOUND;				hd->scsi_ints = ints;				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	 */	while ((hd->scsi_psns & PSNS_REQ) == 0) {		DELAY(1);	}	hs->sc_phase = hd->scsi_psns & PHASE;	if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) {		len = hs->sc_len;		buf = hs->sc_buf;	} else if (hs->sc_phase == CMD_PHASE) {		len = hs->sc_cdblen;		buf = hs->sc_cdb;	} else if (hs->sc_phase == STATUS_PHASE) {		len = 1;		buf = &hs->sc_stat;	} else {		len = 1;		buf = hs->sc_msg;	}	ixfer_start(hd, len, hs->sc_phase, 0);	if (hs->sc_phase & PHASE_IO)		ixfer_in(hd, len, buf);	else		ixfer_out(hd, len, buf);	return;	/*	 * SCSI Abort	 */ abort:	/* SCSI IO failed */	scabort(hs, hd);	hd->scsi_ints = ints;	*(hs->sc_lock) = SC_IO_FAILED;	return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -