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

📄 tmscp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/*- * Copyright (c) 1991 *	The Regents of the University of California.  All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * *	@(#)tmscp.c	7.17 (Berkeley) 1/21/94 *//* * sccsid = "@(#)tmscp.c	1.24	(ULTRIX)	1/21/86"; *//************************************************************************ *									* *        Licensed from Digital Equipment Corporation 			* *                       Copyright (c) 					* *               Digital Equipment Corporation				* *                   Maynard, Massachusetts 				* *                         1985, 1986 					* *                    All rights reserved. 				* *									* *        The Information in this software is subject to change 	* *   without notice and should not be construed as a commitment 	* *   by  Digital  Equipment  Corporation.   Digital   makes  no 	* *   representations about the suitability of this software for 	* *   any purpose.  It is supplied "As Is" without expressed  or 	* *   implied  warranty. 						* *									* *        If the Regents of the University of California or its 	* *   licensees modify the software in a manner creating  		* *   diriviative copyright rights, appropriate copyright  		* *   legends may be placed on  the drivative work in addition  		* *   to that set forth above. 						* *									* ************************************************************************ *  * tmscp.c - TMSCP (TK50/TU81) tape device driver *  * Modification History: * * 06-Jan-86 - afd *	Changed the probe routine to use DELAY (not TODR).  This now *	works for MicroVAXen as well.  This eliminates the busy-wait *	for MicroVAXen so a dead TK50 controller will not hang autoconf. * * 06-Dec-85 - afd *	Fixed a bug in density selection.  The "set unit characteristics" *	command to select density, was clearing the "unit flags" field *	where the CACHE bit was for TU81-E.  Now the unit's "format" and *	"unitflgs" are saved in tms_info struct.  And are used on STUNT *	commands. * * 19-Oct-85 - afd *	Added support to the open routine to allow drives to be opened *	for low density (800 or 1600 bpi) use.  When the slave routine *	initiates a "get-unit-char" cmd, the format menu for the unit *	is saved in the tms_info structure. The format menu is used in the *	start routine to select the proper low density. * * 02-Oct-85 - afd *	When a tmscp-type controller is initializing, it is possible for *	the sa reg to become 0 between states.  Thus the init code in *	the interrupt routine had to be modified to reflect this. * * 21-Sep-85 - afd *	The TK50 declares a serious exception when a tape mark is encountered. *	This causes problems to dd (& other UN*X utilities).  So a flag *	is set in the rsp() routine when a tape mark is encountered.  If *	this flag is set, the start() routine appends the Clear Serious *	Exception modifier to the next command. * * 03-Sep-85 -- jaw *	messed up previous edit.. * * 29-Aug-85 - jaw *	fixed bugs in 8200 and 750 buffered datapath handling. * * 06-Aug-85 - afd *   1. When repositioning records or files, the count of items skipped *	does NOT HAVE to be returned by controllers (& the TU81 doesn't). *	So tmscprsp() had to be modified to stop reporting *	residual count errors on reposition commands. * *   2. Fixed bug in the open routine which allowed multiple opens. * * 18-Jul-85 - afd *   1. Need to return status when mt status (or corresponding ioctl) is done. *	Save resid, flags, endcode & status in tmscprsp() routine (except on *	clear serious exception no-op).  Return these fields when status *	ioctl is done (in tmscpcommand()).  How they are returned: *		mt_resid = resid *		mt_dsreg = flags|endcode *		mt_erreg = status * *   2. Added latent support for enabling/disabling caching.  This is *	handled along with all other ioctl commands. * *   3. Need to issue a no-op on unrecognized ioctl in tmscpstart(), since *	we have already commited to issuing a command at that point. * *   4. In tmscprsp() routine if encode is 0200 (invalid command issued); *	We need to: Unlink the buffer from the I/O wait queue, *	and signal iodone, so the higher level command can exit! *	Just as if it were a valid command. * * 11-jul-85 -- jaw *	fix bua/bda map registers. * * 19-Jun-85 -- jaw *	VAX8200 name change. * * 06-Jun-85 - jaw *	fixes for 8200. * * 9-Apr-85 - afd *	Added timeout code to the probe routine, so if the controller *	fails to init in 10 seconds we return failed status. * * 13-Mar-85 -jaw *	Changes for support of the VAX8200 were merged in. * * 27-Feb-85 -tresvik *	Changes for support of the VAX8600 were merged in. * */#include "tms.h"#if NTMSCP > 0#include "sys/param.h"#include "sys/systm.h"#include "sys/buf.h"#include "sys/conf.h"#include "sys/errno.h"#include "sys/file.h"#include "sys/map.h"#include "sys/vm.h"#include "sys/ioctl.h"#include "sys/syslog.h"#include "sys/mtio.h"#include "sys/cmap.h"#include "sys/uio.h"#include "sys/tprintf.h"#include "../include/pte.h"#include "../include/cpu.h"#include "../include/mtpr.h"#include "ubareg.h"#include "ubavar.h"#define TENSEC	(1000)#define	TMS_PRI	LOG_INFO#define NRSPL2  3               /* log2 number of response packets */#define NCMDL2  3               /* log2 number of command packets */#define NRSP    (1<<NRSPL2)#define NCMD    (1<<NCMDL2)#include "tmscpreg.h"#include "../vax/tmscp.h"/* Software state per controller */struct tmscp_softc {	short   sc_state;       /* state of controller */	short   sc_mapped;      /* Unibus map allocated for tmscp struct? */	int     sc_ubainfo;     /* Unibus mapping info */	struct	tmscp *sc_tmscp;   /* Unibus address of tmscp struct */	int     sc_ivec;        /* interrupt vector address */	short   sc_credits;     /* transfer credits */	short   sc_lastcmd;     /* pointer into command ring */	short   sc_lastrsp;     /* pointer into response ring */	short   sc_ipl;		/* interrupt priority (Q-bus) */} tmscp_softc[NTMSCP];struct tmscp {	struct tmscpca	tmscp_ca;         /* communications area */	struct mscp	tmscp_rsp[NRSP];  /* response packets */	struct mscp	tmscp_cmd[NCMD];  /* command packets */} tmscp[NTMSCP];/* * Per drive-unit info */struct tms_info {	daddr_t		tms_dsize;	/* Max user size from online pkt */	unsigned	tms_type;	/* Drive type int field  */	int		tms_resid;	/* residual from last xfer */	u_char		tms_endcode;	/* last command endcode */	u_char		tms_flags;	/* last command end flags */	unsigned	tms_status;	/* Command status from last command */	char		tms_openf;	/* lock against multiple opens */	char		tms_lastiow;	/* last op was a write */	char		tms_serex;	/* set when serious exception occurs */	char		tms_clserex;	/* set when serex being cleared by no-op */	short		tms_fmtmenu;	/* the unit's format (density) menu */	short		tms_unitflgs;	/* unit flag parameters */	short		tms_format;	/* the unit's current format (density) */	tpr_t 		tms_tpr;	/* tprintf handle */} tms_info[NTMS];struct uba_ctlr *tmscpminfo[NTMSCP];struct uba_device *tmsdinfo[NTMS];/*  * ifdef other tmscp devices here if they allow more than 1 unit/controller */struct uba_device *tmscpip[NTMSCP][1];struct buf ctmscpbuf[NTMSCP];		/* internal cmd buffer (for ioctls) */struct buf tmsutab[NTMS];		/* Drive queue */struct buf tmscpwtab[NTMSCP];		/* I/O wait queue, per controller */int    tmscpmicro[NTMSCP];		/* to store microcode level */short  utoctlr[NTMS];			/* Slave unit to controller mapping */					/* filled in by the slave routine *//* Bits in minor device */#define	TMSUNIT(dev)	(minor(dev)&03)#define	T_NOREWIND	04#define	T_HIDENSITY	010/* Slave unit to controller mapping */#define TMSCPCTLR(dev)	(utoctlr[TMSUNIT(dev)])/* * Internal (ioctl) command codes (these must also be declared in the * tmscpioctl routine).  These correspond to ioctls in mtio.h */#define TMS_WRITM	0		/* write tape mark */#define TMS_FSF		1		/* forward space file */#define TMS_BSF		2		/* backward space file */#define TMS_FSR		3		/* forward space record */#define TMS_BSR		4		/* backward space record */#define TMS_REW		5		/* rewind tape */#define TMS_OFFL	6		/* rewind tape & mark unit offline */#define TMS_SENSE	7		/* noop - do a get unit status */#define TMS_CACHE	8		/* enable cache */#define TMS_NOCACHE	9		/* disable cache *//* These go last: after all real mt cmds, just bump the numbers up */#define TMS_CSE		10		/* clear serious exception */#define TMS_LOWDENSITY	11		/* set unit to low density */#define TMS_HIDENSITY	12		/* set unit to high density *//* * Controller states */#define S_IDLE  0               /* hasn't been initialized */#define S_STEP1 1               /* doing step 1 init */#define S_STEP2 2               /* doing step 2 init */#define S_STEP3 3               /* doing step 3 init */#define S_SCHAR 4               /* doing "set controller characteristics" */#define S_RUN   5               /* running */int     tmscperror = 0;		/* causes hex dump of packets */int	tmscp_cp_wait = 0;	/* Something to wait on for command */				/* packets and or credits. */int	wakeup();extern	int	hz;		/* Should find the right include */#ifdef	DEBUG#define printd if (tmscpdebug) printfint tmscpdebug = 1;#define	printd10 if(tmscpdebug >= 10) printf#endif int     tmscpprobe(), tmscpslave(), tmscpattach(), tmscpintr();struct  mscp *tmscpgetcp();#define DRVNAME "tms"#define CTRLNAME "tmscp"u_short tmscpstd[] = { 0174500, 0 };struct  uba_driver tmscpdriver ={ tmscpprobe, tmscpslave, tmscpattach, 0, tmscpstd, DRVNAME, tmsdinfo, CTRLNAME, tmscpminfo, 0};#define b_qsize         b_resid         /* queue size per drive, in tmsutab */#define b_ubinfo        b_resid         /* Unibus mapping info, per buffer *//*************************************************************************/#define DELAYTEN 1000/* * Unfortunately qbgetpri can't be used because the TK50 doesn't flip the * TMSCP_STEP2 flag in the tmscpsa register until after the pending interrupt * has been acknowledged by the cpu. If you are at spl6(), the TMSCP_STEP2 * flag never gets set and you return (0). */tmscpprobe(reg, ctlr)	caddr_t reg;		/* address of the IP register */	int ctlr;		/* index of controller in the tmscp_softc array */{	register int br, cvec;	/* MUST be 1st (r11 & r10): IPL and intr vec */	register struct tmscp_softc *sc = &tmscp_softc[ctlr];				/* ptr to software controller structure */	struct tmscpdevice *tmscpaddr; /* ptr to tmscpdevice struct (IP & SA) */	int count;		/* for probe delay time out */#	ifdef lint	br = 0; cvec = br; br = cvec; reg = reg;	tmscpreset(0); tmscpintr(0);#	endif	tmscpaddr = (struct tmscpdevice *) reg;	/* 	 * Set host-settable interrupt vector.	 * Assign 0 to the ip register to start the tmscp-device initialization.	 * The device is not really initialized at this point, this is just to	 * find out if the device exists.	 */	sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4);	tmscpaddr->tmscpip = 0;	count=0;	while(count < DELAYTEN)		{	/* wait for at most 10 secs */		if((tmscpaddr->tmscpsa & TMSCP_STEP1) != 0)			break;		DELAY(10000);		count=count+1;		}	if (count == DELAYTEN)		return(0);			tmscpaddr->tmscpsa = TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4);	count=0;	while(count < DELAYTEN)		{		if((tmscpaddr->tmscpsa & TMSCP_STEP2) != 0)			break;		DELAY(10000);		count = count+1;		}	if (count == DELAYTEN)		return(0);#ifdef QBA	sc->sc_ipl = br = 0x15;#endif	return(sizeof (struct tmscpdevice));}/* * Try to find a slave (a drive) on the controller. * If the controller is not in the run state, call init to initialize it. */tmscpslave (ui, reg)	struct uba_device *ui;	/* ptr to the uba device structure */	caddr_t reg;		/* addr of the device controller */{	register struct uba_ctlr *um = tmscpminfo[ui->ui_ctlr];	register struct tmscp_softc *sc = &tmscp_softc[ui->ui_ctlr];	register struct tms_info *tms = &tms_info[ui->ui_unit];	struct   tmscpdevice *tmscpaddr;	/* ptr to IP & SA */	struct   mscp *mp;	int	 i;			/* Something to write into to start */					/* the tmscp polling */#	ifdef lint	reg = reg;#	endif	tmscpaddr = (struct tmscpdevice *)um->um_addr;	/* 	 * If its not in the run state, start the initialization process	 * (tmscpintr will complete it);  if the initialization doesn't start;	 * then return.	 */	if(sc->sc_state != S_RUN)		{#		ifdef DEBUG		printd("tmscpslave: ctlr not running: calling init \n");#		endif			if(!tmscpinit(ui->ui_ctlr))	    		return(0);		}	/*	 * Wait for the controller to come into the run state or go idle.	 * If it goes idle return.	 */#	ifdef DEBUG	i=1;#	endif		while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE)#		ifdef DEBUG		if (tmscpaddr->tmscpsa & TMSCP_ERR && i)	    		{	    		printd("tmscp-device: fatal error (%o)\n", tmscpaddr->tmscpsa&0xffff);	    		i=0;	   		 }#		endif			;	/* wait */	if(sc->sc_state == S_IDLE)		{	/* The tmscp device failed to initialize */		printf("tmscp controller failed to init\n");		return(0);		}	/* The controller is up so see if the drive is there */	if(0 == (mp = tmscpgetcp(um)))		{		printf("tmscp can't get command packet\n");		return(0);		}	/* Need to determine the drive type for generic driver */	mp->mscp_opcode = M_OP_GTUNT;	/* This should give us the device type */	mp->mscp_unit = ui->ui_slave;	mp->mscp_cmdref = (long) ui->ui_slave;	tms->tms_status = 0;	/* set to zero */	tmscpip[ui->ui_ctlr][ui->ui_slave] = ui;	*((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT;/* maybe we should poll*/	i = tmscpaddr->tmscpip;#ifdef lint	i = i;#endif	while(!tms->tms_status)		;				/* Wait for some status */#	ifdef DEBUG	printd("tmscpslave: status = %o\n",tms->tms_status & M_ST_MASK);#	endif	tmscpip[ui->ui_ctlr][ui->ui_slave] = 0;	if(!tms->tms_type)			/* packet from a GTUNT */		return(0);			/* Failed No such drive */	else		return(1);			/* Got it and it is there */}/*  * Set ui flags to zero to show device is not online & set tmscpip. * Unit to Controller mapping is set up here. * Open routine will issue the online command, later. */tmscpattach (ui)	register struct uba_device *ui;		/* ptr to unibus dev struct */{	ui->ui_flags = 0;	tmscpip[ui->ui_ctlr][ui->ui_slave] = ui;#	ifdef DEBUG	/* 	 * Check to see if the drive is available.	 * If not then just print debug.	 */	if(tms_info[ui->ui_unit].tms_status != M_ST_AVLBL)		printd("tmscpattach: unavailable \n");#	endif		utoctlr[ui->ui_unit] = ui->ui_ctlr;}/* * TMSCP interrupt routine. */tmscpintr (d)	int d;		/* index to the controller */{	register struct uba_ctlr *um = tmscpminfo[d];	register struct tmscpdevice *tmscpaddr = (struct tmscpdevice *)um->um_addr;	struct buf *bp;	register int i;	register struct tmscp_softc *sc = &tmscp_softc[d];	register struct tmscp *tm = &tmscp[d];	struct tmscp *ttm;	struct mscp *mp;#	ifdef DEBUG	printd10("tmscpintr: state %d, tmscpsa %o\n", sc->sc_state, tmscpaddr->tmscpsa);#	endif	#ifdef QBA	splx(sc->sc_ipl);#endif	/*	 * How the interrupt is handled depends on the state of the controller.	 */	switch (sc->sc_state) {	case S_IDLE:		printf("tmscp%d: random interrupt ignored\n", d);		return;	/* Controller was in step 1 last, see if its gone to step 2 */	case S_STEP1:#		define STEP1MASK 0174377#		define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2)		for (i = 0; i < 150; i++)			{			if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD)				{ /* still in step 1 (wait 1/100 sec) */				DELAY(10000);#				ifdef DEBUG				printd("still in step 1, delaying\n");#				endif DEBUG				}			else				break;			}		if (i > 149)			{			sc->sc_state = S_IDLE;			printf("failed to initialize, in step1: sa 0x%x", tmscpaddr->tmscpsa);			wakeup((caddr_t)um);			return;

⌨️ 快捷键说明

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