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

📄 wt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1991, 1993 *	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. * *	@(#)wt.c	8.1 (Berkeley) 6/11/93 *//* * * Copyright (c) 1989 Carnegie-Mellon University. * All rights reserved. * * Authors: Robert Baron *  * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. *  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. *  * Carnegie Mellon requests users of this software to return to * *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU *  School of Computer Science *  Carnegie Mellon University *  Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */#include "wt.h"#if NWT > 0/*  * HISTORY * $Log:	wt.c,v $ * Revision 2.2.1.3  90/01/08  13:29:38  rvb * 	Add Intel copyright. * 	[90/01/08            rvb] *  * Revision 2.2.1.2  89/12/21  18:00:09  rvb * 	Change WTPRI to make the streamer tape read/write * 	interruptible. 		[lin] *  * Revision 2.2.1.1  89/11/10  09:49:49  rvb * 	ORC likes their streamer port at 0x288. * 	[89/11/08            rvb] *  * Revision 2.2  89/09/25  12:33:02  rvb * 	Driver was provided by Intel 9/18/89. * 	[89/09/23            rvb] *  *//* * *  Copyright 1988, 1989 by Intel Corporation * *	Support Bell Tech QIC-02 and WANGTEK QIC-36 or QIC-02 */#include <sys/param.h>#include <sys/buf.h>#include <sys/file.h>#include <sys/proc.h>#include <sys/user.h>#include <i386/isa/wtreg.h>#ifdef	ORCunsigned wtport = 0x288;	/* base I/O port of controller	*/#else	ORCunsigned wtport = 0x300;	/* base I/O port of controller	*/#endif	ORC				/* standard = 0x300		*/				/* alternate = 0x338		*/unsigned wtchan = 1;		/* DMA channel number		*/				/* stardard = 1			*/				/* hardware permits 1, 2 or 3.	*/		                /* (Avoid DMA 2: used by disks) */int	first_wtopen_ever = 1;#define	ERROR 		1	/* return from tape routines */#define	SUCCESS		0	/* return from tape routines */int	wci = 0;int	exflag = 0;int	bytes = 0;static	unsigned char eqdma = 0x8;static	unsigned char pagereg = 0x83;static	unsigned char dmareg = 2;static	unsigned char dma_write = 0x49;static	unsigned char dma_read = 0x45;static	unsigned char dma_done = 2;static	unsigned char mode = 0;static	unsigned char mbits;	/* map bits into each other */static	long bufptr;static	unsigned numbytes;/*_wci		dw	0	; interrupt chain finished normally_exflag		dw	0	; exception variable_bytes		dw	0	; current byteseqdma		db	8h	; enable dma command: ch1,ch2=8h, ch3=10hpagereg		db	83h	; ch1=83h, ch2=81h, ch3=82hdmareg		db	2	; ch1=2, ch2=4, ch3=6dma_write	db	49h	; write dma command: 48h+_wtchandma_read	db	45h	; read dma command: 44h+_wtchandma_done	db	2	; dma done flag: 1<<_wtchanmode		db	0	; dma operation modelbufptr		dw	0	; buffer pointer to data buffers, low wordhbufptr		dw	0	; buffer pointer to data buffers, high wordnumbytes	dw	0	; number of bytes to read or write (new)*/#define PAGESIZ		4096#define HZ		60/* tape controller ports */#define STATPORT	wtport#define CTLPORT		STATPORT#define CMDPORT		(wtport+1)#define DATAPORT	CMDPORT/* defines for reading out status from wangtek tape controller */#define READY   	0x01    /* ready bit define        */#define EXCEP		0x02	/* exception bit define    */#define STAT		(READY|EXCEP)#define	RESETMASK	0x7#define	RESETVAL	(RESETMASK & ~EXCEP)/* tape controller control bits (CTLPORT) */#define	ONLINE	0x01#define	RESET	0x02#define	REQUEST	0x04		/* request command */#define	CMDOFF	0xC0/* QIC-02 commands (CMDPORT) */#define	RDDATA	0x80		/* read data */#define	READFM	0xA0		/* read file mark */#define	WRTDATA	0x40		/* write data */#define	WRITEFM	0x60		/* write file mark */#define	RDSTAT	0xC0		/* read status command */#define	REWIND	0x21		/* rewind command (position+bot) *//* 8237 DMA controller regs */#define	STATUSREG	0x8#define MASKREG		0xA#define MODEREG		0xB#define CLEARFF		0xC/* streamer tape block size */#define BLKSIZE	512/* Tape characteristics */#define	NBPS		512	/* 512-byte blocks */#define	ERROR 		1	/* return from tape routines */#define	SUCCESS		0	/* return from tape routines *//* Minor devs */#define	TP_REWCLOSE(d)	((minor(d)&04) == 0) /* Rewind tape on close if read/write */#define	TP_DENS(dev)	((minor(dev) >> 3) & 03) /* set density */#define TPHOG(d)	0	/* use Hogproc during tape I/O	*//* defines for wtflags */#define	TPINUSE	0x0001		/* tape is already open */#define	TPREAD	0x0002		/* tape is only open for reading */#define	TPWRITE	0x0004		/* tape is only open for writing */#define	TPSTART 0x0008		/* tape must be rewound and reset */#define	TPDEAD	0x0010		/* tape drive does not work or driver error */#define	TPSESS	0x0020		/* no more reads or writes allowed in session */				/* for example, when tape has to be changed */#define	TPSTOP	0x0040		/* Stop command outstanding */#define	TPREW	0x0080		/* Rewind command outstanding, see wtdsl2() */#define	TPVOL	0x0100		/* Read file mark, or hit end of tape */#define	TPWO	0x0200		/* write command outstanding */#define	TPRO	0x0400		/* read command outstanding */#define TPWANY	0x0800		/* write command requested */#define TPRANY	0x1000		/* read command requested */#define	TPWP	0x2000		/* write protect error seen */unsigned int	wtflags = TPSTART;	/* state of tape drive */struct	buf	rwtbuf;		/* header for raw i/o */struct  proc	*myproc;	/* process which opened tape driver */char wtimeron;			/* wtimer() active flag */char wtio;			/* dma (i/o) active flag */char isrlock;			/* isr() flag */struct proc * Hogproc;	/* no Hogproc on Microport */#define	ftoseg(x)	((unsigned) (x >> 16))struct	wtstatus {	ushort	wt_err;		/* code for error encountered */	ushort	wt_ercnt;	/* number of error blocks */	ushort	wt_urcnt;	/* number of underruns */}	wterror;/* defines for wtstatus.wt_err */#define	TP_POR		0x100	/* Power on/reset occurred */#define	TP_RES1		0x200	/* Reserved for end of media */#define	TP_RES2		0x400	/* Reserved for bus parity */#define	TP_BOM		0x800	/* Beginning of media */#define	TP_MBD		0x1000	/* Marginal block detected */#define	TP_NDT		0x2000	/* No data detected */#define	TP_ILL		0x4000	/* Illegal command */#define	TP_ST1		0x8000	/* Status byte 1 bits */#define	TP_FIL		0x01	/* File mark detected */#define	TP_BNL		0x02	/* Bad block not located */#define	TP_UDA		0x04	/* Unrecoverable data error */#define	TP_EOM		0x08	/* End of media */#define	TP_WRP		0x10	/* Write protected cartridge */#define	TP_USL		0x20	/* Unselected drive */#define	TP_CNI		0x40	/* Cartridge not in place */#define	TP_ST0		0x80	/* Status byte 0 bits *//* Grounds for reporting I/O error to user */#define	TP_ERR0		(TP_BNL|TP_UDA|TP_WRP|TP_CNI|TP_FIL|TP_EOM|TP_USL)#define	TP_ERR1		(TP_MBD|TP_NDT|TP_ILL)/* TP_ILL should never happen! *//*#define	TP_ERR0		0x7f#define	TP_ERR1		0x7700*//* defines for reading out status from wangtek tape controller */#define READY   	0x01    /* ready bit define        */#define EXCEP		0x02	/* exception bit define    *//* sleep priority */#define WTPRI	(PZERO+10)char	pagebuf[NBPS];		/* buffer of size NBPS */unsigned long	pageaddr;	/* physical addr of pagebuf */				/* pageaddr is used with DMA controller */time_t Hogtime;			/* lbolt when Hog timer started */extern time_t	lbolt;#define	debug	printf/* * Strategy routine. * * Arguments: *  Pointer to buffer structure * Function: *  Start transfer. * * It would be nice to have this multiple-threaded. * There is a version of dump from Berkeley that works with multiple processes * trading off with disk & tape I/O. */intwtstrategy(bp)register struct buf *bp;{	unsigned ucnt1, ucnt2, finished;	unsigned long adr1, adr2;	int	bad;	adr1 = kvtop(bp->b_un.b_addr);#ifdef DEBUG	debug("bpaddr %x\n", adr1);#endif	ucnt1 = bp->b_bcount;	ucnt2 = 0;	adr2 = 0;#ifdef DEBUG	debug("WTstart: adr1 %lx cnt %x\n", adr1, ucnt1);#endif	if (ftoseg(adr1) != ftoseg(adr1 + (unsigned) ucnt1 - 1))	{		adr2 = (adr1 & 0xffff0000L) + 0x10000L;		ucnt2 = (adr1 + ucnt1) - adr2;		ucnt1 -= ucnt2;	}	/* at file marks and end of tape, we just return '0 bytes available' */	if (wtflags & TPVOL) {		bp->b_resid = bp->b_bcount;		goto xit;	}	if ((Hogproc == (struct proc *) 0) && TPHOG(bp->b_dev))	{#ifdef DEBUG		printf("setting Hogproc\n");#endif		Hogtime = 0;		Hogproc = myproc;	}	if (bp->b_flags & B_READ) {		bad = 0;		/* For now, we assume that all data will be copied out */		/* If read command outstanding, just skip down */		if (!(wtflags & TPRO)) {			if (ERROR == wtsense(TP_WRP))	/* clear status */				goto errxit;#ifdef DEBUG			debug("WTread: Start read\n");#endif			if (!(wtflags & TPREAD) || (wtflags & TPWANY) ||			    (rstart() == ERROR))  {#ifdef DEBUG				debug("Tpstart: read init error\n"); /* */#endif				goto errxit;			}			wtflags |= TPRO|TPRANY;		}		finished = 0;		/* Take a deep breath */		if (ucnt1) {			if ((rtape(adr1, ucnt1) == ERROR) &&					(wtsense(TP_WRP) == ERROR))				goto endio;			/* wait for it */			bad = pollrdy();			finished = bytes;			if (bad)				goto endio;		}		/* if a second I/O region, start it */		if (ucnt2) {			if ((rtape(adr2, ucnt2) == ERROR) &&					(wtsense(TP_WRP) == ERROR))				ucnt2 = 0;	/* don't poll for me */			}		/* if second i/o pending wait for it */		if (ucnt2) {			pollrdy();			/* whether pollrdy is ok or not */			finished += bytes;		}	} else {		if (wtflags & TPWP)	/* write protected */			goto errxit;		/* If write command outstanding, just skip down */		if (!(wtflags & TPWO)) {			if (ERROR == wtsense(0))	/* clear status */			{#ifdef DEBUG				debug("TPstart: sense 0\n");#endif				goto errxit;			}			if (!(wtflags & TPWRITE) || (wtflags & TPRANY) ||			    (wstart() == ERROR))  {#ifdef DEBUG				debug("Tpstart: write init error\n"); /* */#endif				wtsense(0);errxit:				bp->b_flags |= B_ERROR;				bp->b_resid = bp->b_bcount;				goto xit;			}			wtflags |= TPWO|TPWANY;		} 		/* and hold your nose */		if (ucnt1 && ((wtape(adr1, ucnt1) == ERROR)				&& (wtsense(0) == ERROR)))			finished = bytes;		else if (ucnt2 &&			(((ucnt1 && pollrdy()) ||				(wtape(adr2, ucnt2) == ERROR)) &&				(wtsense(0) == ERROR)))			finished = ucnt1 + NBPS + bytes;		/* All writes and/or copyins were fine! */		else			finished = bp->b_bcount;		bad = pollrdy();	}	endio:	if(bad == EIO) bad = 0;	wterror.wt_err = 0;	if (exflag && wtsense((bp->b_flags & B_READ) ? TP_WRP : 0)) {		if ((wterror.wt_err & TP_ST0) 			&& (wterror.wt_err & (TP_FIL|TP_EOM))) {#ifdef DEBUG			debug("WTsta: Hit end of tape\n"); /* */#endif			wtflags |= TPVOL;			if (wterror.wt_err & TP_FIL) {				if (wtflags & TPRO)					/* interrupter is bogus */					rstart();  /* restart read command */				else					wtflags &= ~TPWO;				finished += NBPS; 			}		/* Reading file marks or writing end of tape return 0 bytes */		} else	{			bp->b_flags |= B_ERROR;			wtflags &= ~(TPWO|TPRO);		}	}	if(bad) {		bp->b_flags |= B_ERROR;		bp->b_error = bad;	}	bp->b_resid = bp->b_bcount - finished;xit:	biodone(bp);	if (wtimeron)		Hogtime = lbolt;	else if (Hogproc == myproc)		Hogproc = (struct proc *) 0;}/* * simulate an interrupt periodically while I/O is going * this is necessary in case interrupts get eaten due to * multiple devices on a single IRQ line */wtimer(){	/* If I/O going and not in isr(), simulate interrupt	 * If no I/O for at least 1 second, stop being a Hog	 * If I/O done and not a Hog, turn off wtimer()	 */	if (wtio && !isrlock)		isr();	if ((Hogproc == myproc) && Hogtime && (lbolt-Hogtime > HZ))		Hogproc = (struct proc *) 0;	if (wtio || (Hogproc == myproc))		timeout(wtimer, (caddr_t) 0, HZ);	else		wtimeron = 0;}wtrawio(bp)struct buf	*bp;{	wtstrategy(bp);	biowait(bp);	return(0);}wt_minphys(bp)struct buf	*bp;{	if (bp->b_bcount > PAGESIZ)		bp->b_bcount = PAGESIZ;}/* * raw read routine */wtread(dev, uio)struct uio	*uio;{	if (wtflags & TPSESS) {		return(EIO);	}	physio(wtrawio, &rwtbuf, dev, B_READ, wt_minphys, uio);	return(0);}/* * raw write routine */wtwrite(dev, uio)struct uio	*uio;{	if (wtflags & TPSESS) {		return(EIO);	}	physio(wtrawio, &rwtbuf, dev, B_WRITE, wt_minphys, uio);	return(0);}/* * ioctl routine *  for user level QIC commands only */wtioctl(dev, cmd, arg, mode)int dev, cmd;unsigned long arg;int mode;{	if (cmd == WTQICMD)	{		if ((qicmd((int)arg) == ERROR) || (rdyexc(HZ) == ERROR))		{			wtsense(0);			return(EIO);		}		return(0);	}	return(EINVAL);}/* * open routine * called on every device open */wtopen(dev, flag)int	dev, flag;{	if (first_wtopen_ever) {		wtinit();		first_wtopen_ever = 0;	}#ifdef DEBUG	printf("wtopen ...\n");#endif	if (!pageaddr) {		return(ENXIO);	}	if (wtflags & (TPINUSE)) {		return(ENXIO);	}	if (wtflags & (TPDEAD)) {		return(EIO);	}	/* If a rewind from the last session is going on, wait */	while(wtflags & TPREW) {#ifdef DEBUG		debug("Waiting for rew to finish\n");#endif		delay(1000000);	/* delay one second */	}	/* Only do reset and select when tape light is off, and tape is rewound.	 * This allows multiple volumes. */	if (wtflags & TPSTART) { 		if (t_reset() != SUCCESS) {			return(ENXIO);		}#ifdef DEBUG		debug("reset done. calling wtsense\n");#endif		if (wtsense(TP_WRP) == ERROR) {			return (EIO);		}#ifdef DEBUG		debug("wtsense done\n");#endif		wtflags &= ~TPSTART;		}	wtflags = TPINUSE;	if (flag & FREAD)		wtflags |= TPREAD;	if (flag & FWRITE)		wtflags |= TPWRITE;	rwtbuf.b_flags = 0;	myproc = curproc;		/* for comparison */	switch(TP_DENS(dev)) {

⌨️ 快捷键说明

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