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

📄 sc.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
sc_select(sc)register struct scsitwo *sc;{	register struct scsi_cmd *sp = sc->sc_que;	register int i;	u_short icr_mode;	DPRINTF2 ("select %d.%d\n", Tgt(sp), Lun(sp));	/*	 * make sure scsi bus is not continuously busy	 */	for (i = SC_WAIT_COUNT; i > 0; i--) {		if ((sc->sc_reg->icr & ICR_BUSY) == 0)			break;		DELAY(10);	}	if (i == 0) {		sc_printf(sc, "scsi bus continuously busy: ICR=0x%b\n",			sc->sc_reg->icr, scbits);		sp->cmd_pkt.pkt_reason = CMD_INCOMPLETE;		screset(sc, 1); /* XXX? */		return (FALSE);	}	/*	 * Got the bus...	 */	sp->cmd_pkt.pkt_state |= STATE_GOT_BUS;	/*	 * select target and wait for response	 */	sc->sc_reg->icr = 0; /* Make sure SECONDBYTE flag is clear */	/*	 * Since we aren't an arbitrating initiator, we only	 * put in the target address and *not* our own as well.	 */	sc->sc_reg->data = 1 << Tgt(sp);	sc->sc_reg->icr = ICR_SELECT;	/*	 * See if target responds to selection	 */	if (sc_wait((u_short *)&sc->sc_reg->icr, SC_SHORT_WAIT, ICR_BUSY)) {		DPRINTF2 ("%d.%d didn't select\n", Tgt(sp), Lun(sp));		sc->sc_reg->data = 0;		sc->sc_reg->icr = 0;		sp->cmd_pkt.pkt_reason = CMD_INCOMPLETE;		return (FALSE);	}	/*	 * Got the target...	 */	sp->cmd_pkt.pkt_state |= STATE_GOT_TARGET;	icr_mode = 0;	if ((sp->cmd_pkt.pkt_flags & FLAG_NOINTR) == 0) {		icr_mode |= ICR_INTERRUPT_ENABLE;	}	/*	 * If a data transfer is expected, set it up here...	 */	if (sp->cmd_dmacount && (sp->cmd_flags&CFLAG_DMAVALID)) {		SET_DMA_ADDR (sc->sc_reg, ((int)sp->cmd_data));		sc->sc_reg->dma_count = ~sp->cmd_dmacount;		if (((int)sp->cmd_data)&0x1) {			DPRINTF ("odd byte DMA address\n");		} else {			icr_mode |= ICR_WORD_MODE;		}		icr_mode |= ICR_DMA_ENABLE;	}	/*	 * set the interrupt register	 */	sc->sc_reg->icr = icr_mode;	return (TRUE);}/* * * finish routine * */static voidsc_finish(sc)register struct scsitwo *sc;{	register struct scsi_cmd *sp = sc->sc_que;	char dkn, wasintr;	sc->sc_reg->icr = 0;	/* clear any pending interrupts */	sc->sc_busy = 0;	if ((dkn = sp->cmd_pkt.pkt_pmon) >= 0) {		dk_busy &= ~(1<<dkn);	}	DPRINTF1 ("finishing command %d\n", sc->sc_cmdid);	sc->sc_cmdid++;	sc->sc_que = Nextcmd(sp);	if (sp->cmd_pkt.pkt_state & STATE_XFERRED_DATA) {		/*		 * Since we cannot disconnect, we cannot have had more		 * than one data segment		 */		if (sp->cmd_subseg.d_next != (struct dataseg *) 0) {			panic("sc_finish: more than one segment with data");			/* NOTREACHED */		}		sp->cmd_pkt.pkt_resid =			sp->cmd_dmacount - sp->cmd_subseg.d_count;	}	wasintr = (sp->cmd_pkt.pkt_flags & FLAG_NOINTR)? 0: 1;	(*sp->cmd_pkt.pkt_comp)(sp);	if (wasintr && sc->sc_que && sc->sc_busy == 0) {		sc_ustart(sc);	}}/* * Interrupt service section */static intsc_dopoll(sc, id)register struct scsitwo *sc;register id;{	register i;	struct scsi_cmd *sp = sc->sc_que;	for (i = 0; i < 300000 && id == sc->sc_cmdid; i++) {		if (INTPENDING(sc->sc_reg)) {			scintr(sc);			i = 0;		} else {			DELAY(500);		}	}	if (i >= 300000) {		sc_printf(sc, "polled command timeout\n");		sp->cmd_pkt.pkt_reason = CMD_TIMEOUT;		screset(sc, 0);		sc_finish(sc);	}}/* * Handle a polling (autovectored) SCSI bus interrupt. */static intscpoll(){	register struct scsitwo *sc;	register int serviced = 0;	for (sc = &sc_softc[0]; sc < &sc_softc[NSC]; sc++) {		if (sc->sc_reg && INTPENDING(sc->sc_reg)) {			serviced += scintr(sc);		}	}	return (serviced);}/* * Handle a scsi bus interrupt. */intscintr(sc)register struct scsitwo *sc;{	register struct scsi_cmd *sp = sc->sc_que;	if (sp == 0 || !sc->sc_reg || !(INTPENDING(sc->sc_reg))) {		sc_printf(sc, "spurious interrupt\n");		return (0);	}	DPRINTF2 ("scintr: ICR=0x%b\n", sc->sc_reg->icr, scbits);	/*	 * End of Data phase? Check for bus error first...	 */	if (sc->sc_reg->icr & ICR_BUS_ERROR) {		sc_printf(sc, "Dma BUS Error on address 0x%x\n", sp->cmd_data);		sc_abort_cmd(sc);		return (1);	} else if (sp->cmd_dmacount && (sp->cmd_flags & CFLAG_DMAVALID)) {		int resid, reqamt, xfer_amt;		resid = (u_short) (~sc->sc_reg->dma_count);		reqamt = sp->cmd_dmacount;		if (sc->sc_reg->icr & ICR_ODD_LENGTH) {			if (sp->cmd_flags & CFLAG_DMASEND) {				resid++;			} else if (reqamt) {				sc_flush(sc, (u_long)				    (sp->cmd_data + reqamt - resid));				resid--;			}		}		if (xfer_amt = reqamt - resid) {			DPRINTF1 ("xferred %d\n", xfer_amt);			sp->cmd_data += xfer_amt;			sp->cmd_subseg.d_count += xfer_amt;			sp->cmd_pkt.pkt_state |= STATE_XFERRED_DATA;		}	}	/*	 * Now, get status and/or message...	 */	while (sc->sc_reg->icr & (ICR_BUSY|ICR_REQUEST)) {		register u_short pbits;		while (((pbits = sc->sc_reg->icr) & ICR_REQUEST) == 0) {			if ((pbits & ICR_BUSY) == 0) {				sc_printf(sc, "Target %d dropped BUSY\n",				    Tgt(sp));				sc_abort_cmd(sc);				return (1);			}		}		switch (pbits & ICR_BITS) {		case ICR_STATUS:			*sp->cmd_scbp = sc->sc_reg->cmd_stat;			sp->cmd_pkt.pkt_state |= STATE_GOT_STATUS;			break;		case ICR_MESSAGE_IN:		{			static char *bad =				"Bad Message '0x%x' from Target %d, Lun %d\n";			switch (sc->sc_msgin = sc->sc_reg->cmd_stat) {			case MSG_COMMAND_COMPLETE:			case MSG_LINK_CMPLT:			case MSG_LINK_CMPLT_FLAG:				sp->cmd_pkt.pkt_reason = CMD_CMPLT;				sc_finish(sc);				break;			default:				sc_printf(sc, bad, sc->sc_msgin,					Tgt(sp), Lun(sp));				sc_abort_cmd(sc);				break;			}			return (1);			break;		}		default:			sc_printf(sc, "Bad phase: ICR=0x%b\n", pbits, scbits);			sc_abort_cmd(sc);			return (1);			break;		}	}	return (1);}/* * Flush the last byte of an odd length transfer */static voidsc_flush(sc, offset)register struct scsitwo *sc;register u_long offset;{	register u_int pv;	u_char *mapaddr;	if (MBI_MR(offset) < dvmasize) {		DVMA[offset] = sc->sc_reg->data;		return;	}#ifdef	sun3x	pv = btop (VME24D16_BASE + (offset & VME24D16_MASK));#else	sun3x	pv = PGT_VME_D16 | VME24_BASE | btop(offset & VME24_MASK);#endif	sun3x	mapaddr = (u_char *) ((u_long) kmxtob(sc_kment) |	    (u_long) MBI_OFFSET(offset));	segkmem_mapin(&kseg, (addr_t) (((int)mapaddr) & PAGEMASK),	    (u_int) mmu_ptob(1), PROT_READ | PROT_WRITE, pv, 0);	*mapaddr = sc->sc_reg->data;	segkmem_mapout(&kseg,	    (addr_t) (((int)mapaddr) & PAGEMASK), (u_int) mmu_ptob(1));	segkmem_mapout(&kseg, (addr_t) mapaddr, (u_int) mmu_btop(1));}/* * Miscellaneous functions */static voidsc_abort_cmd(sc)struct scsitwo *sc;{	sc->sc_que->cmd_pkt.pkt_reason = CMD_RESET;	screset(sc, 1);	sc_finish(sc);}/* * Wait for a condition to be (de)asserted on the scsi bus. * Returns 0, if successful, else -1; */static intsc_wait(icrp, wait_count, cond)	register u_short *icrp;	register int wait_count;{	register int i;	register u_short icr;	for (i = 0; i < wait_count; i++) {		icr = *icrp;		if ((icr & cond) == cond) {			return (0);		} else if (icr & ICR_BUS_ERROR) {			break;		} else			DELAY(10);	}	return (-1);}/* * Put data byte onto the scsi bus if phase match. * Returns:	1  if successful (phase matched) *		0  if incorrect phase, but REQ is present *		-1 if no REQ present */staticsc_putbyte(sc, bits, data)register struct scsitwo *sc;register u_short bits;register u_char data;{	register u_short icr;	if (sc_wait((u_short *)&sc->sc_reg->icr, SC_WAIT_COUNT, ICR_REQUEST)) {		DPRINTF ("sc_putbyte: no REQ\n");		return (-1);	}	icr = sc->sc_reg->icr;	if ((icr & ICR_BITS) != bits) {		DPRINTF2 ("sc_putbyte: ICR=0x%b\n", icr, scbits);		return (0);	}	sc->sc_reg->cmd_stat = data;	return (1);}/* * Reset SCSI control logic and bus. */static voidscreset(sc, msg_enable)struct scsitwo *sc;int msg_enable;{	if (msg_enable) {		sc_printf(sc, "Resetting SCSI bus\n");	}	sc->sc_reg->icr = ICR_RESET;	DELAY(50);	sc->sc_reg->icr = 0;	/* give reset scsi devices time to recover (> 2 Sec) */	DELAY(SC_RESET_DELAY);}/*ARGSUSED*/static voidsc_watch(arg)caddr_t arg;{	register s;	register struct scsitwo *sc;	register struct scsi_cmd *sp;	for (sc = &sc_softc[0]; sc < &sc_softc[NSC]; sc++) {		if (sc->sc_reg) {			s = splr(sc->sc_tran.tran_spl);			sp = sc->sc_que;			if (sp && (sp->cmd_flags & CFLAG_WATCH)) {				if (sp->cmd_timeout == 0) {					/*					 * A pending interrupt					 * defers the sentence					 * of death.					 */					if (INTPENDING(sc->sc_reg)) {						sp->cmd_timeout++;						(void) splx(s);						continue;					}					sc_printf(sc, "command timeout\n");					sp->cmd_pkt.pkt_reason = CMD_TIMEOUT;					sc_reset(sc, 0);					sc_finish(sc);					(void) splx(s);					continue;				} else {					sp->cmd_timeout -= 1;				}			}			(void) splx(s);		}	}	timeout(sc_watch, (caddr_t) 0, hz);}/*VARARGS*/static voidsc_printf(sc, fmt, a, b, c, d, e, f, g, h)struct scsitwo *sc;char *fmt;int a, b, c, d, e, f, g, h;{	printf("%s%d: ", CNAME, CNUM);	printf(fmt, a, b, c, d, e, f, g, h);}#endif	(NSC > 0)

⌨️ 快捷键说明

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