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

📄 ik.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		dp->b_actl->av_forw = bp;		dp->b_actl = bp;	} else		dp->b_actf = dp->b_actl = bp;	if (!dp->b_active)		ikstart(dp);	(void) spl0();}/* * Start the next command on the controller's queue. */ikstart(dp)	register struct buf *dp;{	register struct buf *bp;	register struct ikdevice *ik;	register struct ik_softc *sc;	u_short bc, csr;	u_int addr;	int unit;loop:	/*	 * Pull a request off the controller queue	 */	if ((bp = dp->b_actf) == NULL) {		dp->b_active = 0;		return;	}	/*	 * Mark controller busy and process this request.	 */	dp->b_active = 1;	unit = IKUNIT(bp->b_dev);	sc = &ik_softc[unit];	ik = (struct ikdevice *)ikinfo[unit]->ui_addr;	switch ((int)bp->b_command) {	case PS_ATTACH:		/* logical unit attach */	case PS_DETACH:		/* logical unit detach */	case PS_LOOKUP:		/* name lookup */	case PS_RDPHY:		/* physical i/o read */	case PS_WRPHY:		/* physical i/o write */	case PS_WRPHY_SYNC:	/* physical i/o write w/ sync */		/*		 * Handshake command and, optionally,		 * byte count and byte swap flag.		 */		if (sc->is_error = diowrite(ik, (u_short)bp->b_command))			goto bad;		if (bp->b_command < PS_DETACH) {			if (sc->is_error = diowrite(ik, (u_short)bp->b_bcount))				goto bad;			if (sc->is_error = diowrite(ik, (u_short)0 /* !swab */))				goto bad;		}		/*		 * Set timeout and wait for an attention interrupt.		 */		sc->is_timeout = iktimeout;		return;	case PS_DMAOUT:		/* dma data host->PS300 */		bc = bp->b_bcount;		csr = IKCSR_CYCLE;		break;	case PS_DMAIN:		/* dma data PS300->host */		bc = bp->b_bcount;		csr = IKCSR_CYCLE|IKCSR_FNC1;		break;	default:		log(LOG_ERR, "ik%d: bad cmd %x\n", unit, bp->b_command);		sc->is_error = PSERROR_BADCMD;		goto bad;	}	/* initiate dma transfer */	addr = vtoph((struct proc *)0, (unsigned)sc->is_buf);	ik->ik_bahi = addr >> 17;	ik->ik_balo = (addr >> 1) & 0xffff;	ik->ik_wc = ((bc + 1) >> 1) - 1;	/* round & convert */	ik->ik_pulse = IKPULSE_RATTF|IKPULSE_RDMAF;	sc->is_timeout = iktimeout;	ik->ik_csr = IKCSR_IENA|IKCSR_GO|csr;	return;bad:	bp->b_flags |= B_ERROR;	dp->b_actf = bp->av_forw;		/* remove from queue */	biodone(bp);	goto loop;}#define FETCHWORD(i) { \	v = dioread(ik); \	if (v == -1) { \		sc->is_error = PSERROR_NAMETIMO; \		goto bad; \	} \	sc->is_nameaddr.w[i] = v; \}/* * Process a device interrupt. */ikintr(ikon)	int ikon;{	register struct ikdevice *ik;	register struct buf *bp, *dp;	struct ik_softc *sc;	register u_short data;	int v;	/* should go by controller, but for now... */	if (ikinfo[ikon] == 0)		return;	ik = (struct ikdevice *)ikinfo[ikon]->ui_addr;	/*	 * Discard all non-attention interrupts.  The	 * interrupts we're throwing away should all be	 * associated with DMA completion.	 */	data = ik->ik_data;	if ((ik->ik_csr&(IKCSR_ATTF|IKCSR_STATC)) != IKCSR_ATTF) {		ik->ik_pulse = IKPULSE_RATTF|IKPULSE_RDMAF|IKPULSE_SIENA;		return;	}	/*	 * Fetch attention code immediately.	 */	ik->ik_csr = IKCSR_RATTF|IKCSR_RDMAF|IKCSR_FNC1;	ik->ik_pulse = IKPULSE_FNC2;	/*	 * Get device and block structures, and a pointer	 * to the vba_device for the device.  We receive an	 * unsolicited interrupt whenever the PS300 is power	 * cycled (so ignore it in that case).	 */	dp = &iktab[ikon];	if ((bp = dp->b_actf) == NULL) {		if (PS_CODE(data) != PS_RESET)		/* power failure */			log(LOG_WARNING, "ik%d: spurious interrupt, code %x\n",			    ikon, data);		goto enable;	}	sc = &ik_softc[IKUNIT(bp->b_dev)];	sc->is_timeout = 0;			/* disable timer */	switch (PS_CODE(data)) {	case PS_LOOKUP:				/* name lookup */		if (data == PS_LOOKUP) {	/* dma name */			bp->b_command = PS_DMAOUT;			goto opcont;		}		if (data == PS_DMAOK(PS_LOOKUP)) {			/* reenable interrupt and wait for address */			sc->is_timeout = iktimeout;			goto enable;		}		/*		 * Address should be present, extract it one		 * word at a time from the PS300 (yech).		 */		if (data != PS_ADROK(PS_LOOKUP))			goto bad;		FETCHWORD(0);		FETCHWORD(1);		goto opdone;	case PS_WRPHY_SYNC:			/* physical i/o write w/ sync */		if (data == PS_WRPHY_SYNC) {	/* start dma transfer */			bp->b_command = PS_DMAOUT;			goto opcont;		}		if (data != PS_DMAOK(PS_WRPHY_SYNC))			goto bad;		goto opdone;	case PS_WRPHY:				/* physical i/o write */		if (data == PS_WRPHY) { /* start dma transfer */			bp->b_command = PS_DMAOUT;			goto opcont;		}		if (data != PS_DMAOK(PS_WRPHY))			goto bad;		goto opdone;	case PS_ATTACH:				/* attach unit */	case PS_DETACH:				/* detach unit */	case PS_ABORT:				/* abort code from ps300 */		if (data != bp->b_command)			goto bad;		goto opdone;	case PS_RDPHY:				/* physical i/o read */		if (data == PS_RDPHY) {		/* dma address list */			bp->b_command = PS_DMAOUT;			goto opcont;		}		if (data == PS_ADROK(PS_RDPHY)) {			/* collect read byte count and start dma */			bp->b_bcount = dioread(ik);			if (bp->b_bcount == -1)				goto bad;			bp->b_command = PS_DMAIN;			goto opcont;		}		if (data == PS_DMAOK(PS_RDPHY))			goto opdone;		goto bad;	}bad:	sc->is_error = data;	bp->b_flags |= B_ERROR;opdone:	dp->b_actf = bp->av_forw;		/* remove from queue */	biodone(bp);opcont:	ikstart(dp);enable:	ik->ik_pulse = IKPULSE_SIENA;		/* explicitly reenable */}/* * Watchdog timer. */iktimer(unit)	int unit;{	register struct ik_softc *sc = &ik_softc[unit];	if (sc->is_timeout && --sc->is_timeout == 0) {		register struct buf *dp, *bp;		int s;		log(LOG_ERR, "ik%d: timeout\n", unit);		s = splik();		/* should abort current command */		dp = &iktab[unit];		if (bp = dp->b_actf) {			sc->is_error = PSERROR_CMDTIMO;			bp->b_flags |= B_ERROR;			dp->b_actf = bp->av_forw;	/* remove from queue */			biodone(bp);			ikstart(dp);		}		splx(s);	}	timeout(iktimer, (caddr_t)unit, hz);}/* * Handshake read from DR300. */dioread(ik)	register struct ikdevice *ik;{	register int t;	u_short data;	for (t = ikdiotimo; t > 0; t--)		if ((ik->ik_csr&(IKCSR_ATTF|IKCSR_STATC)) == IKCSR_ATTF) {			data = ik->ik_data;			ik->ik_csr = IKCSR_RATTF|IKCSR_RDMAF|IKCSR_FNC1;			ik->ik_pulse = IKPULSE_FNC2;			return (data);		}	return (-1);}/* * Handshake write to DR300.  * * Interrupts are enabled before completing the work * so the caller should either be at splik or be * prepared to take the interrupt immediately. */diowrite(ik, v)	register struct ikdevice *ik;	u_short v;{	register int t;	register u_short csr;top:	/*	 * Deposit data and generate dr300 attention	 */	ik->ik_data = v;	ik->ik_csr = IKCSR_RDMAF|IKCSR_RATTF;	ik->ik_pulse = IKPULSE_FNC2;	for (t = ikdiotimo; t > 0; t--) {		csr = ik->ik_csr;#define IKCSR_DONE	(IKCSR_STATA|IKCSR_STATC)		if ((csr&IKCSR_DONE) == IKCSR_DONE) {			/* 			 * Done, complete handshake by notifying dr300.			 */			ik->ik_csr = IKCSR_IENA;	/* ~IKCSR_FNC1 */			ik->ik_pulse = IKPULSE_FNC2;			return (0);		}		/* beware of potential deadlock with dioread */		if ((csr&(IKCSR_ATTF|IKCSR_STATC)) == IKCSR_ATTF)			goto top;	}	ik->ik_csr = IKCSR_IENA;	return (PSERROR_DIOTIMO);}/*ARGSUSED*/ikioctl(dev, cmd, data, flag)	dev_t dev;	int cmd;	caddr_t data;	int flag;{	int error = 0, unit = IKUNIT(dev), s;	register struct ik_softc *sc = &ik_softc[unit];	switch (cmd) {	case PSIOGETERROR:		/* get error code for last operation */		*(int *)data = sc->is_error;		break;	case PSIOLOOKUP: {		/* PS300 name lookup */		register struct pslookup *lp = (struct pslookup *)data;		register struct buf *bp;		if (lp->pl_len > PS_MAXNAMELEN)			return (EINVAL);		bp = &rikbuf[unit];		s = splbio();		while (bp->b_flags&B_BUSY) {			bp->b_flags |= B_WANTED;			sleep((caddr_t)bp, PRIBIO+1);		}		splx(s);		bp->b_flags = B_BUSY | B_WRITE;		error = copyin(lp->pl_name, (caddr_t)sc->is_buf,		    (unsigned)lp->pl_len);		if (error == 0) {			if (lp->pl_len&1)				sc->is_buf[lp->pl_len] = '\0';			error = ikcommand(dev, PS_LOOKUP, lp->pl_len);		}		s = splbio();		if (bp->b_flags&B_WANTED)			wakeup((caddr_t)bp);		splx(s);		bp->b_flags &= ~(B_BUSY|B_WANTED);		lp->pl_addr = sc->is_nameaddr.l;		break;	}	default:		return (ENOTTY);	}	return (error);}#endif

⌨️ 快捷键说明

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