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

📄 sc.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "sc.h"#if	NSC > 0#ifndef lintstatic	char sccsid[] = "@(#)sc.c 1.1 92/07/30 SMI";#endif/* * Copyright (C) 1989, Sun Microsystems, Inc. *//* * * TO DO:	1. reimplment PARITY support *		2. handle linked commands * */#include <scsi/scsi.h>#include <scsi/adapters/screg.h>#include <sys/mman.h>#include <machine/pte.h>#include <machine/cpu.h>#include <vm/seg.h>/* * Definitions *//*#define	SC_PARITY	/* Compile in (cough) Parity support *//*#define	SC_LINKED	/* Compile in linked command support *//*#define	SCDEBUG		/* Compile in debug code */#ifdef	SC_PARITY---- BLETCH ----- PARITY NOT SUPPORTED YET#endif#ifdef	SCDEBUG#define	DEBUGGING	(scdebug || (scsi_options & SCSI_DEBUG_HA))#define	DPRINTF(str)		if (DEBUGGING) sc_printf(sc, str)#define	DPRINTF1(str, x)	if (DEBUGGING) sc_printf(sc, str, x)#define	DPRINTF2(str, x, y)	if (DEBUGGING) sc_printf(sc, str, x, y)#define	DPRINTF3(str, x, y, z)	if (DEBUGGING) sc_printf(sc, str, x, y, z)#else#define	DPRINTF#define	DPRINTF1#define	DPRINTF2#define	DPRINTF3#endif#define	TRUE		1#define	FALSE		0#define	UNDEFINED	-1#define	Tgt(sp)		((sp)->cmd_pkt.pkt_address.a_target)#define	Lun(sp)		((sp)->cmd_pkt.pkt_address.a_lun)#define	Nextcmd(sp)	((struct scsi_cmd *)((sp)->cmd_pkt.pkt_ha_private))#define	CNAME	scdriver.mdr_cname#define	CNUM	sc-sc_softc#define	INTPENDING(reg) ((reg)->icr & (ICR_INTERRUPT_REQUEST | ICR_BUS_ERROR))/* * SCSI Architecture Interface functions */static int sc_start(), sc_abort(), sc_reset(), sc_getcap(), sc_setcap();/* * Local && h/w related functions */static void screset(), sc_watch(), sc_ustart(), sc_finish(), sc_abort_cmd();static void sc_printf(), sc_flush();/* * Local static data */static struct scsitwo sc_softc[NSC];static char *scbits =	"\20\20Per\17Berr\16Odd\15IRQ\14REQ\13MSG\12CD\11IO\03Wrd\02Dma\01Ena";static long sc_kment;static int sc_mapins;#ifdef	SCDEBUGstatic int scdebug;#endif	SCDEBUG/* * External references */extern struct seg kseg;/* * Config dependencies */static int scprobe(), scslave(), scattach(), scpoll();int scintr();struct	mb_driver scdriver = {	scprobe, scslave, scattach, 0, 0, scpoll,	sizeof (struct screg), "scsibus", 0, "sc", 0, MDR_BIODMA,};static intscprobe(reg, ctlr)caddr_t reg;int ctlr;{	static char scwstart = 0;	register struct scsitwo *sc;	register struct screg *btmp = (struct screg *) reg;	/* probe for different scsi host adaptor interfaces */	if (peek((short *)&btmp->dma_count) == -1) {		return (0);	}	/* validate ctlr by write/read/cmp with a data pattern */	btmp->dma_count = 0x6789;	if (btmp->dma_count != 0x6789) {		return (0);	}	if (ctlr >= NSC) {		printf("%s%d: illegal controller number", CNAME, ctlr);		return (0);	}	sc_kment = rmalloc(kernelmap, mmu_btopr(MMU_PAGESIZE));	if (sc_kment == 0)		return (0);	sc = &sc_softc[ctlr];	sc->sc_reg = btmp;	sc->sc_tran.tran_start 		= sc_start;	sc->sc_tran.tran_abort		= sc_abort;	sc->sc_tran.tran_reset		= sc_reset;	sc->sc_tran.tran_getcap		= sc_getcap;	sc->sc_tran.tran_setcap		= sc_setcap;	sc->sc_tran.tran_pktalloc 	= scsi_std_pktalloc;	sc->sc_tran.tran_dmaget		= scsi_std_dmaget;	sc->sc_tran.tran_pktfree	= scsi_std_pktfree;	sc->sc_tran.tran_dmafree	= scsi_std_dmafree;	screset(sc, 0);	if (!scwstart) {		scwstart++;		timeout (sc_watch, (caddr_t) 0, hz);	}	return (sizeof (struct screg));}/*ARGSUSED1*/static intscslave(md, reg)struct mb_device *md;caddr_t reg;{	struct scsitwo *sc = &sc_softc[md->md_unit];	md->md_slave = HOST_ID << 3;#ifndef	SC_LINKED	/*	 * Disable linked commands for the moment...	 */	if (scsi_options & SCSI_OPTIONS_LINK) {		scsi_options ^= SCSI_OPTIONS_LINK;		sc_printf(sc, "disabling linked command support\n");	}#endif	return (1);}static intscattach(md)struct mb_device *md;{	int i;	static int sc_spl = 0;	struct scsitwo *sc = &sc_softc[md->md_unit];	/*	 * Calculate max spl value so far seen	 */	sc_spl = MAX(sc_spl, pritospl(md->md_intpri));	/*	 * Make sure that everyone, including us, is locking at	 * the same priority.	 */	for (i = 0; i <= md->md_unit; i++) {		sc_softc[i].sc_tran.tran_spl = sc_spl;	}	/*	 * Initialize interrupt register	 */	if (md->md_mc->mc_intr) {		/* set up for vectored interrupts */		sc->sc_reg->intvec = md->md_mc->mc_intr->v_vec;		*(md->md_mc->mc_intr->v_vptr) = (int) sc;	} else {		/* use auto-vectoring */		sc->sc_reg->intvec = AUTOBASE + md->md_mc->mc_intpri;	}	/*	 * Now make ourselves known to the rest of the SCSI world	 */	scsi_config(&sc->sc_tran, md);}/* * *	Begin of external interface routines * */static intsc_start(sp)register struct scsi_cmd *sp;{	auto int s;	register struct scsitwo *sc;	register struct scsi_cmd *xp;	sc = (struct scsitwo *) sp->cmd_pkt.pkt_address.a_cookie;	s = splr(sc->sc_tran.tran_spl);	if (xp = sc->sc_que) {		for (;;) {			if (Tgt(xp) == Tgt(sp) && Lun(xp) == Lun(sp)) {				/* Queueing error */				(void) splx(s);				return (FALSE);			}			if (Nextcmd(xp) == 0)				break;			else				xp = Nextcmd(xp);		}		Nextcmd(xp) = sp;	} else {		sc->sc_que = sp;	}	Nextcmd(sp) = 0;	/*	 * reinitialize some fields that need it...	 */	sp->cmd_pkt.pkt_resid = 0;	sp->cmd_pkt.pkt_reason = sp->cmd_pkt.pkt_state =		sp->cmd_pkt.pkt_statistics = 0;	sp->cmd_cdbp = (caddr_t) sp->cmd_pkt.pkt_cdbp;	sp->cmd_scbp = sp->cmd_pkt.pkt_scbp; *sp->cmd_scbp = 0;	if (sp->cmd_timeout = sp->cmd_pkt.pkt_time)		sp->cmd_flags |= CFLAG_WATCH;	else		sp->cmd_flags &= ~CFLAG_WATCH;	sp->cmd_data = sp->cmd_saved_data = sp->cmd_mapping;	sp->cmd_cursubseg = &sp->cmd_subseg;	sp->cmd_subseg.d_base = sp->cmd_mapping;	sp->cmd_subseg.d_count = 0;	sp->cmd_subseg.d_next = (struct dataseg *) 0;	sp->cmd_flags &= ~(CFLAG_NEEDSEG|CFLAG_CMDDISC);	/*	 * Okay- if this command is a polling command,	 * and we're not the head of the queue, we have to	 * wait for the commands ahead of us to finish.	 */	if (sp->cmd_pkt.pkt_flags & FLAG_NOINTR) {		int id;		while (sc->sc_que != sp) {			DPRINTF ("polled command waiting\n");			sc_dopoll(sc, sc->sc_cmdid);		}		id = sc->sc_cmdid;		DPRINTF1 ("starting polling cmd #%d\n", id);		sc_ustart(sc);		DPRINTF ("waiting polled cmd completion\n");		sc_dopoll(sc, id);		DPRINTF1 ("polled cmd #%d complete\n", id);		if (sc->sc_que)			sc_ustart(sc);	} else if (sc->sc_que == sp) {		sc_ustart(sc);	}	(void) splx(s);	return (TRUE);}/*ARGSUSED*/static intsc_abort(ap, pkt)struct scsi_address *ap;struct scsi_pkt *pkt;{	if (pkt != (struct scsi_pkt *) 0)		return (FALSE);	else		return (FALSE);}static intsc_reset(ap, level)struct scsi_address *ap;int level;{	struct scsitwo *sc = (struct scsitwo *) ap->a_cookie;	struct scsi_cmd *sp = sc->sc_que;	screset(sc, 0);	if (sp) {		/*		 * If we're resetting everything, remove		 * the current wait queue from reconsideration		 * after we reset and blow away the current		 * command.		 */		if (level == RESET_ALL) {			sp = Nextcmd(sc->sc_que);			Nextcmd(sc->sc_que) = 0;		}		sp->cmd_pkt.pkt_reason = CMD_RESET;		sc_finish(sc);		/*		 * walk down the unrooted wait queue, 'finishing' off		 * all the commands therein...		 */		if (level == RESET_ALL) {			while (sp) {				struct scsi_cmd *xp;				xp = Nextcmd(sp);				sp->cmd_pkt.pkt_reason = CMD_RESET;				(*sp->cmd_pkt.pkt_comp)(sp);				sp = xp;			}		}		return (TRUE);	} else {		return (FALSE);	}}/*ARGSUSED*/static intsc_getcap(ap, cap)struct scsi_address *ap;char *cap;{	if (cap == (char *) 0)		return (UNDEFINED);	else if (strncmp("dma_max", cap, 7) == 0)		return (1<<16);	else if (strncmp("msg_out", cap, 7) == 0)		return (0);	else if (strncmp("disconnect", cap, 10) == 0)		return (0);	else if (strncmp("synchronous", cap, 11) == 0)		return (0);	else if (strncmp("parity", cap, 6) == 0)		return (0);	else if (strncmp("initiator-id", cap, 12) == 0)		return (HOST_ID);	else		return (UNDEFINED);}/*ARGSUSED*/static intsc_setcap(ap, cap, value)struct scsi_address *ap;char *cap;int value;{	/*	 * Cannot set any values yet	 */	return (UNDEFINED);}/* * * Internal start routine * */static voidsc_ustart(sc)register struct scsitwo *sc;{	register i;	register struct scsi_cmd *sp = sc->sc_que;	char dkn;	int r;	if (!sp)		return;	else if ((dkn = sp->cmd_pkt.pkt_pmon) >= 0) {		dk_busy |= (1<<dkn);		dk_xfer[dkn]++;		if ((sp->cmd_flags & CFLAG_DMASEND) == 0)			dk_read[dkn]++;		dk_wds[dkn] += sp->cmd_dmacount >> 6;	}	/*	 * sc_select will wait for the scsi bus to be free, attempt	 * to select the target, will set up the dma engine for any	 * possible dma transfer, and will set the icr bits for having	 * interrupts enabled if this is an interrupting command.	 *	 */	sc->sc_busy = 1;	if (sc_select(sc) == FALSE) {		sc_finish(sc);		return;	}	/*	 * At this point, we should either ge into STATUS phase or into	 * COMMAND phase.	 */#ifdef	SCDEBUG	if (DEBUGGING) {		sc_printf(sc, "%d.%d cmd=", Tgt(sp), Lun(sp));		for (i = 0; i < sp->cmd_cdblen; i++) {			printf(" 0x%x", sp->cmd_cdbp[i]);		}		printf("\n");	}#endif	SCDEBUG	for (r = i = 0; i < sp->cmd_cdblen; i++) {		if ((r = sc_putbyte(sc, ICR_COMMAND, sp->cmd_cdbp[i])) <= 0) {			break;		}	}	if (r < 0) {		sc_printf(sc, "couldn't send command\n");		sc_abort_cmd(sc);	} else if (i > 0) {		sp->cmd_pkt.pkt_state |= STATE_SENT_CMD;		sp->cmd_cdbp = (caddr_t) (((u_long)sp->cmd_cdbp) + i);	}	/*	 * We will either let interrupts drive us the rest of the	 * way, or call a polling routine to do that for us	 */}static int

⌨️ 快捷键说明

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