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

📄 sc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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.2 (Berkeley) 12/6/93 *//* * sc.c -- FUJITSU MB89352 SCSI Protocole Controller (SPC) Device Driver * * remaked by A.Fujita,		Mar-22-1992 * remaked again by A.Fujita,	Apr-16-1992 */#define DEBUG_FUNC#include "sc.h"#if NSC > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/buf.h>#include <luna68k/dev/device.h>#include <luna68k/dev/screg.h>#include <luna68k/dev/scvar.h>/* * SC Driver Options */#define	QUADBYTES	/* 4 bytes access to SPC DREG Reg. */#define	NODISCONNECT	/* not used SCSI DISCONNECT Ops. */#undef	XFER_ENABLE	/* using interrupt for DREG access */#define SCSI_IPL	2#define SCSI_ID		7extern char *hexstr();int	scinit(), scstart(), scintr();void	screset();struct	driver scdriver = {	scinit, "sc", scstart, (int (*)()) 0, scintr, (int (*)()) 0};struct	sc_softc sc_softc[NSC];#define	SC_TIMEOUT	0x01400000	/* (20971520) *//* * for DEBUG */char *scsi_status(stat)	u_char stat;{	if ((stat & 0x1e) == 0)		return("Good");	else if ((stat & 0x1e) == STS_CHECKCOND)		return("Check Condition");	else if ((stat & 0x1e) == STS_CONDMET)		return("Condition Met");	else if ((stat & 0x1e) == STS_BUSY)		return("Busy");	else if ((stat & 0x1e) == STS_INTERMED)		return("Intermediate status sent");	else if ((stat & 0x1e) == STS_EXT)		return("Extended status valid");	else		return("Unknown Status");}#ifdef DEBUG_FUNCchar *scsi_command(cmd)	u_char cmd;{	if (cmd == CMD_TEST_UNIT_READY)		return("TEST_UNIT_READY");	else if (cmd == CMD_REQUEST_SENSE)		return("REQUEST_SENSE");	else if (cmd == CMD_INQUIRY)		return("INQUIRY");	else if (cmd == CMD_READ)		return("READ");	else if (cmd == CMD_WRITE)		return("WRITE");	else if (cmd == CMD_READ_EXT)		return("READ EXT");	else if (cmd == CMD_WRITE_EXT)		return("WRITE_EXT");	else if (cmd == CMD_READ_CAPACITY)		return("READ_CAPACITY");	else		return(hexstr(cmd, 2));}char *scsi_mesg(mesg)	u_char mesg;{	if (mesg == MSG_CMD_COMPLETE)		return("Command Complete");	else if (mesg == MSG_EXT_MESSAGE)		return("Extended Message");	else if (mesg == MSG_SAVE_DATA_PTR)		return("Save Data Pointer");	else if (mesg == MSG_RESTORE_PTR)		return("Restore Pointer");	else if (mesg == MSG_DISCONNECT)		return("Disconnect");	else if (mesg == MSG_INIT_DETECT_ERROR)		return("Initiator Detected Error");	else if (mesg == MSG_ABORT)		return("Abort");	else if (mesg == MSG_REJECT)		return("Message Reject");	else if (mesg == MSG_NOOP)		return("No Operation");	else if (mesg == MSG_PARITY_ERROR)		return("Message Parity Error");	else if (mesg == MSG_BUS_DEVICE_RESET)		return("Bus Device Reset");	else if (mesg == MSG_IDENTIFY)		return("Identify");	else if (mesg == MSG_IDENTIFY_DR)		return("Identify (Disconnect)");	else		return("Unknown Message");}char *phase_name(phase)	u_char phase;{	if (phase == DATA_OUT_PHASE)		return("Data Out");	else if (phase == DATA_IN_PHASE)		return("Data In");	else if (phase == CMD_PHASE)		return("Command");	else if (phase == STATUS_PHASE)		return("Status");	else if (phase == BUS_FREE_PHASE)		return("Bus Free");	else if (phase == ARB_SEL_PHASE)		return("Arbitration/Select");	else if (phase == MESG_OUT_PHASE)		return("Message Out");	else if (phase == MESG_IN_PHASE)		return("Message In");	else		return("Unknown");}#endif/* * Initialize SPC & Data Structure */intscinit(hc)	register struct hp_ctlr *hc;{	register struct sc_softc *hs = &sc_softc[hc->hp_unit];	register int i;	hc->hp_ipl    = SCSI_IPL;	hs->sc_hc     = hc;	hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq;	hs->sc_wq.dq_forw = hs->sc_wq.dq_back = &hs->sc_wq;	hs->sc_flags  = 0;	hs->sc_phase  = BUS_FREE_PHASE;	hs->sc_stat   = 0;	hs->sc_msg[0] = 0;	screset(hc->hp_unit);	return(1);}voidscreset(unit)	register int unit;{	register struct sc_softc *hs = &sc_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, flags)	volatile register struct scsidevice *hd;	u_char target;	int flags;{#ifndef NODISCONNECT	if (flags & DQ_DISCONNECT) {		hd->scsi_scmd = SCMD_SET_ATN;	}#endif	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)	volatile register struct scsidevice *hd;	register int len;	register u_char phase;{	register int wait = 0;	hd->scsi_sdgc = 0;	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;	while ((hd->scsi_ssts & SSTS_BUSY) == 0) {		if (wait > SC_TIMEOUT) {			panic("ixfer_start: too long wait");		}		wait++;		DELAY(1);	}}intixfer_out(hd, len, buf)	volatile register struct scsidevice *hd;	register int len;	register u_char *buf;{	u_char *t = buf;	register int wait = 0;#ifdef QUADBYTES	register int qwait = 0;	register int l_len = len >> 3;	register u_long * l_buf = (u_long *) buf;	for(; l_len > 0; l_len--) {		while ((hd->scsi_ssts & SSTS_DREG_EMPTY) == 0) {			if (qwait > SC_TIMEOUT) {				printf("ixfer_out: quad time out\n");				printf("ixfer_out: %d bytes sended\n",				       (((u_char *) l_buf) - t));				printf("ixfer_out: TC = %d\n",				       ( hd->scsi_tch << 16 ) |				       ( hd->scsi_tcm <<  8 ) |				       ( hd->scsi_tcl ));				return(-1);			}			qwait++;			DELAY(1);		}		*((u_long *) &hd->scsi_dreg) = *l_buf++;		*((u_long *) &hd->scsi_dreg) = *l_buf++;	}	len &= 0x07;	buf = (u_char *) l_buf;#endif	for(; len > 0; len--) {		while (hd->scsi_ssts & SSTS_DREG_FULL) {			if (wait > SC_TIMEOUT) {				printf("ixfer_out: time out\n");				printf("ixfer_out: %d bytes sended\n",				       (buf - t));				return(-1);			}			wait++;			DELAY(1);		}		hd->scsi_dreg = *buf++;	}#ifdef QUADBYTES	return(qwait);#else	return(wait);#endif}intixfer_in(hd, len, buf)	volatile register struct scsidevice *hd;	register int len;	register u_char *buf;{	u_char *t = buf;	register int wait = 0;#ifdef QUADBYTES	register int qwait = 0;	register int l_len = len >> 3;	register u_long * l_buf = (u_long *) buf;	for(; l_len > 0; l_len--) {		while ((hd->scsi_ssts & SSTS_DREG_FULL) == 0) {			if (qwait > SC_TIMEOUT) {				printf("ixfer_in: quad time out\n");				printf("ixfer_in: %d bytes recieved\n",				       (((u_char *) l_buf) - t));				return(-1);			}			qwait++;			DELAY(1);		}		*l_buf++ = *((u_long *) &hd->scsi_dreg);		*l_buf++ = *((u_long *) &hd->scsi_dreg);	}	len &= 0x07;	buf = (u_char *) l_buf;#endif	for (; len > 0; len--) {		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {			if (wait > SC_TIMEOUT) {				printf("ixfer_in: time out\n");				printf("ixfer_in: %d bytes recieved\n",				       (buf - t));				return(-1);			}			wait++;			DELAY(1);		}		*buf++ = hd->scsi_dreg;	}#ifdef QUADBYTES	return(qwait);#else	return(wait);#endif}#ifdef XFER_ENABLE/* * SPC Interrupt base Transfer Routines */inttxfer_start(hd, len, phase)	volatile register struct scsidevice *hd;	register int len;	register u_char phase;{	register int wait = 0;	hd->scsi_sdgc = SDGC_XFER_ENAB;		/* for interrupt */	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;	while ((hd->scsi_ssts & SSTS_BUSY) == 0) {		if (wait > SC_TIMEOUT) {			panic("ixfer_start: too long wait");		}		wait++;		DELAY(1);	}}inttxfer_in(ctlr)	register int ctlr;{	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 = hs->sc_sq.dq_forw;#ifdef QUADBYTES	register u_long *lp;	if (hd->scsi_ssts & SSTS_DREG_FULL) {		lp = (u_long *) dq->dq_xferp;		*lp++ = *((u_long *) &hd->scsi_dreg);		*lp++ = *((u_long *) &hd->scsi_dreg);		dq->dq_xferp = (u_char *) lp;		dq->dq_xfercnt -= 8;		goto xfer_done;	}#endif	*dq->dq_xferp++ = hd->scsi_dreg;	dq->dq_xfercnt--; xfer_done:#ifdef DEBUGPRINT	if (dq->dq_xfercnt == 0) {		dbgprintf("txfer_in: ");		dbgprintf("dq->dq_bp->b_un.b_addr = 0x%s, ", hexstr(dq->dq_bp->b_un.b_addr, 8));		dbgprintf("dq->dq_xferp = 0x%s :", hexstr(dq->dq_xferp, 8));		dbgprintf("done\n");	}#endif}#endif/* * SCSI Job Handler */intscstart(ctlr)	int ctlr;{	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 = hs->sc_sq.dq_forw;	dq->dq_imax =  0;	dq->dq_imin = -1;	dq->dq_omax =  0;	dq->dq_omin = -1;	hs->sc_flags  = 0;	hs->sc_phase  = ARB_SEL_PHASE;	hs->sc_stat   = 0;	hs->sc_msg[0] = 0;#ifdef DEBUGPRINT	dbgprintf("\n");	dbgprintf("scstart: ID = %d\n", dq->dq_slave);	dbgprintf("scstart: cdb[0] = %s\n", scsi_command(dq->dq_cdb->cdb[0]));	dbgprintf("scstart: cdb[1] = 0x%s\n", hexstr(dq->dq_cdb->cdb[1], 2));	dbgprintf("scstart: cdb[2] = 0x%s\n", hexstr(dq->dq_cdb->cdb[2], 2));	dbgprintf("scstart: cdb[3] = 0x%s\n", hexstr(dq->dq_cdb->cdb[3], 2));	dbgprintf("scstart: cdb[4] = 0x%s\n", hexstr(dq->dq_cdb->cdb[4], 2));	dbgprintf("scstart: cdb[5] = 0x%s\n", hexstr(dq->dq_cdb->cdb[5], 2));	if (dq->dq_cdb->cdb[0] & 0xE0) {		dbgprintf("scstart: cdb[6] = 0x%s\n", hexstr(dq->dq_cdb->cdb[6], 2));		dbgprintf("scstart: cdb[7] = 0x%s\n", hexstr(dq->dq_cdb->cdb[7], 2));		dbgprintf("scstart: cdb[8] = 0x%s\n", hexstr(dq->dq_cdb->cdb[8], 2));		dbgprintf("scstart: cdb[9] = 0x%s\n", hexstr(dq->dq_cdb->cdb[9], 2));	}	dbgprintf("scstart: bp->b_bcount = %d\n", dq->dq_bp->b_bcount);	dbgprintf("scstart: %s\n", phase_name(hs->sc_phase));#endif	issue_select(hd, dq->dq_slave, dq->dq_flags);	return(1);}int_scintr(){	register struct sc_softc *hs;	volatile register struct scsidevice *hd;	register int ctlr;	for (ctlr = 0; ctlr < NSC; ctlr++) {		hs = &sc_softc[ctlr];		hd = (struct scsidevice *) hs->sc_hc->hp_addr;#ifdef XFER_ENABLE		if (((hd->scsi_psns & PHASE) == DATA_IN_PHASE) &&		    (hd->scsi_serr & SERR_XFER_OUT))			txfer_in(ctlr);#endif		if (hd->scsi_ints != 0)			scintr(ctlr);	}	return;}intscintr(ctlr)	register int ctlr;{	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 = hs->sc_sq.dq_forw;	register u_char ints, temp;	register int i, slave;	int wait, len;	u_char *buf;	ints = hd->scsi_ints;#ifdef DEBUGPRINT	dbgprintf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x",	       ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);	if (hs->sc_phase == CMD_PHASE)		dbgprintf("   [%s]", scsi_command(dq->dq_cdb->cdb[0]));	if (hs->sc_phase & PHASE_MSG)		dbgprintf("   [%s]", scsi_mesg(hs->sc_msg[0]));	dbgprintf("\n");#endif

⌨️ 快捷键说明

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