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

📄 ik.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1986 The Regents of the University of California. * All rights reserved. * * 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. * *	@(#)ik.c	7.7 (Berkeley) 12/16/90 */#include "ik.h"#if NIK > 0/* * PS300/IKON DR-11W Device Driver. */#include "sys/param.h"#include "sys/buf.h"#include "sys/cmap.h"#include "sys/conf.h"#include "sys/dkstat.h"#include "sys/map.h"#include "sys/systm.h"#include "sys/user.h"#include "sys/vmmac.h"#include "sys/proc.h"#include "sys/kernel.h"#include "sys/syslog.h"#include "../include/mtpr.h"#include "../include/pte.h"#include "../vba/vbavar.h"#include "../vba/ikreg.h"#include "../vba/psreg.h"#include "../vba/psproto.h"int	ikprobe(), ikattach(), iktimer();struct	vba_device *ikinfo[NIK];long	ikstd[] = { 0 };struct	vba_driver ikdriver = { ikprobe, 0, ikattach, 0, ikstd, "ik", ikinfo };#define splik()		spl4()/* * Devices are organized in pairs with the odd valued * device being used for ``diagnostic'' purposes.  That * is diagnostic devices don't get auto-attach'd and * detach'd on open-close. */#define IKUNIT(dev)	(minor(dev) >> 1)#define IKDIAG(dev)	(minor(dev) & 01)	/* is a diagnostic unit */struct	ik_softc {	uid_t	is_uid;		/* uid of open processes */	u_short is_timeout;	/* current timeout (seconds) */	u_short is_error;	/* internal error codes */	u_short is_flags;#define IKF_ATTACHED	0x1	/* unit is attached (not used yet) */	union {		u_short w[2];		u_long	l;	} is_nameaddr;		/* address of last symbol lookup */	caddr_t is_buf[PS_MAXDMA];/* i/o buffer XXX */} ik_softc[NIK];struct	buf iktab[NIK];		/* unit command queue headers */struct	buf rikbuf[NIK];	/* buffers for read/write operations */struct	buf cikbuf[NIK];	/* buffers for control operations *//* buf overlay definitions */#define b_command	b_residint	ikdiotimo = PS_DIOTIMO; /* dio polling timeout */int	iktimeout = PS_TIMEOUT; /* attention/dma timeout (in hz) */ikprobe(reg, vi)	caddr_t reg;	struct vba_device *vi;{	register int br, cvec;		/* r12, r11 */	register struct ikdevice *ik;#ifdef lint	br = 0; cvec = br; br = cvec;	ikintr(0);#endif	if (badaddr(reg, 2))		return (0);	ik = (struct ikdevice *)reg;	ik->ik_vec = --vi->ui_hd->vh_lastiv;	/*	 * Use extended non-privileged address modifier	 * to avoid address overlap with 24-bit devices.	 */	ik->ik_mod = 0xf1;			/* address modifier */	/*	 * Try and reset the PS300.  Since this	 * won't work if it's powered off, we	 * can't use sucess/failure to decide	 * if the device is present.	 */	br = 0;	(void) psreset(ik, IKCSR_IENA);	if (br == 0)				/* XXX */		br = 0x18, cvec = ik->ik_vec;	/* XXX */	return (sizeof (struct ikdevice));}/* * Perform a ``hard'' reset. */psreset(ik, iena)	register struct ikdevice *ik;{	ik->ik_csr = IKCSR_MCLR|iena;	DELAY(10000);	ik->ik_csr = IKCSR_FNC3|iena;	if (!iena)		return (dioread(ik) == PS_RESET);	return (1);}ikattach(vi)	struct vba_device *vi;{	ik_softc[vi->ui_unit].is_uid = -1;}/* * Open a PS300 and attach.  We allow multiple * processes with the same uid to share a unit. *//*ARGSUSED*/ikopen(dev, flag)	dev_t dev;	int flag;{	register int unit = IKUNIT(dev);	register struct ik_softc *sc;	struct vba_device *vi;	struct ikdevice *ik;	int reset;	if (unit >= NIK || (vi = ikinfo[unit]) == 0 || vi->ui_alive == 0)		return (ENXIO);	sc = &ik_softc[unit];	if (sc->is_uid != (uid_t)-1 && sc->is_uid != u.u_uid)		return (EBUSY);	if (sc->is_uid == (uid_t)-1) {		sc->is_timeout = 0;		timeout(iktimer, (caddr_t)unit, hz);		/*		 * Perform PS300 attach for first process.		 */		if (!IKDIAG(dev)) {			reset = 0;		again:			if (ikcommand(dev, PS_ATTACH, 1)) {				/*				 * If attach fails, perform a hard				 * reset once, then retry the command.				 */				ik = (struct ikdevice *)ikinfo[unit]->ui_addr;				if (!reset++ && psreset(ik, 0))					goto again;				untimeout(iktimer, (caddr_t)unit);				return (EIO);			}		}		sc->is_uid = u.u_uid;	}	return (0);}/*ARGSUSED*/ikclose(dev, flag)	dev_t dev;	int flag;{	int unit = IKUNIT(dev);	register struct ik_softc *sc = &ik_softc[unit];	if (!IKDIAG(dev))		(void) ikcommand(dev, PS_DETACH, 1);	/* auto detach */	sc->is_uid = -1;	untimeout(iktimer, (caddr_t)unit);	return (0);}ikread(dev, uio)	dev_t dev;	struct uio *uio;{	return (ikrw(dev, uio, B_READ));}ikwrite(dev, uio)	dev_t dev;	struct uio *uio;{	return (ikrw(dev, uio, B_WRITE));}/* * Take read/write request and perform physical i/o * transaction with PS300.  This involves constructing * a physical i/o request vector based on the uio * vector, performing the dma, and, finally, moving * the data to it's final destination (because of CCI * VERSAbus bogosities). */ikrw(dev, uio, rw)	dev_t dev;	register struct uio *uio;	int rw;{	int error, unit = IKUNIT(dev), s, wrcmd;	register struct buf *bp;	register struct iovec *iov;	register struct psalist *ap;	struct ik_softc *sc = &ik_softc[unit];	if (unit >= NIK)		return (ENXIO);	bp = &rikbuf[unit];	error = 0, iov = uio->uio_iov, wrcmd = PS_WRPHY;	for (; !error && uio->uio_iovcnt; iov++, uio->uio_iovcnt--) { 		/*		 * Hack way to set PS300 address w/o doing an lseek		 * and specify write physical w/ refresh synchronization.		 */		if (iov->iov_len == 0) {			if ((int)iov->iov_base&PSIO_SYNC)				wrcmd = PS_WRPHY_SYNC;			uio->uio_offset = (int)iov->iov_base & ~PSIO_SYNC;			continue;		}		if (iov->iov_len > PS_MAXDMA) {			sc->is_error = PSERROR_INVALBC, error = EINVAL;			continue;		}		if ((int)uio->uio_offset&01) {			sc->is_error = PSERROR_BADADDR, error = EINVAL;			continue;		}		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 | rw;		/*		 * Construct address descriptor in buffer.		 */		ap = (struct psalist *)sc->is_buf;		ap->nblocks = 1;		/* work-around dr300 word swapping */		ap->addr[0] = uio->uio_offset & 0xffff;		ap->addr[1] = uio->uio_offset >> 16;		ap->wc = (iov->iov_len + 1) >> 1;		if (rw == B_WRITE) {			error = copyin(iov->iov_base, (caddr_t)&ap[1],			    (unsigned)iov->iov_len);			if (!error)				error = ikcommand(dev, wrcmd,				    iov->iov_len + sizeof (*ap));		} else {			caddr_t cp;			int len;			error = ikcommand(dev, PS_RDPHY, sizeof (*ap));			cp = (caddr_t)&ap[1], len = iov->iov_len;			for (; len > 0; len -= NBPG, cp += NBPG)				mtpr(P1DC, cp);			if (!error)				error = copyout((caddr_t)&ap[1], iov->iov_base,				    (unsigned)iov->iov_len);		}		(void) splbio();		if (bp->b_flags&B_WANTED)			wakeup((caddr_t)bp);		splx(s);		uio->uio_resid -= iov->iov_len;		uio->uio_offset += iov->iov_len;		bp->b_flags &= ~(B_BUSY|B_WANTED);	}	return (error);}/* * Perform a PS300 command. */ikcommand(dev, com, count)	dev_t dev;	int com, count;{	register struct buf *bp;	register int s;	int error;	bp = &cikbuf[IKUNIT(dev)];	s = splik();	while (bp->b_flags&B_BUSY) {		if (bp->b_flags&B_DONE)			break;		bp->b_flags |= B_WANTED;		sleep((caddr_t)bp, PRIBIO);	}	bp->b_flags = B_BUSY|B_READ;	splx(s);	bp->b_dev = dev;	bp->b_command = com;	bp->b_bcount = count;	ikstrategy(bp);	error = biowait(bp);	if (bp->b_flags&B_WANTED)		wakeup((caddr_t)bp);	bp->b_flags &= B_ERROR;	return (error);}/* * Physio strategy routine */ikstrategy(bp)	register struct buf *bp;{	register struct buf *dp;	/*	 * Put request at end of controller queue.	 */	dp = &iktab[IKUNIT(bp->b_dev)];	bp->av_forw = NULL;	(void) splik();	if (dp->b_actf != NULL) {

⌨️ 快捷键说明

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