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

📄 ar.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	char sccsid[] = "@(#)ar.c	1.1 92/07/30	Copyr 1986 Sun Micro";#endif/* * Copyright (c) 1986 by Sun Microsystems, Inc. *//* * Standalone Driver for Archive Intelligent Streaming Tape */#include <stand/saio.h>#include <stand/param.h>#include <sundev/arreg.h>#include <stand/ardef.h>#define	min(a,b)	((a) < (b) ? (a) : (b))int ardebug = 0;#define Dprintf  if (ardebug) printf/* Trace all writes to control reg */#define DebugTrace Dprintf(ar_ctrl_hdr, *(long*)(2+(char*)araddr))/* Define assorted debugging strings to save repeating them N times */#ifdef DEBUGchar ar_bits[] = ARCH_LONG_CTRL_BITS;char ar_ctrl_hdr[] = "ar* Bits: %x\n";char ar_set_hdr[] = "ar* CMD: %x\n";#endif DEBUGchar ar_stat_bits[] = ARCH_BITS;/* * Standard I/O addresses. */#define NARADDR	2u_long araddrs[] = { 0x200, 0x208};/* * What resources we need to run */struct devinfo arinfo = {	sizeof (struct ardevice), 	/* I/O regs */	0,				/* no DMA */	sizeof (struct ar_softc),	/* work area */	NARADDR,	araddrs,	MAP_MBIO,	DEV_BSIZE,			/* transfer size */};/* * What facilities we export to the world */int	aropen(), arclose(), arstrategy();extern int	xxboot(), xxprobe();struct boottab ardriver = {	"ar",	xxprobe, xxboot, aropen, arclose, arstrategy,	"ar: Multibus Archive tape controller", &arinfo,}; /* * Translation between generic tape commands and initial states of * the Archive state machine. */enum ARstates ar_cmds[] = {	/* CLOSE */	CLOSEinit,	/* REWIND */	REWinit,	/* STATUS */	RDSTinit,	/* READ */	READinit,	/* WRITE */	WRinit,	/* WEOF */	WFMinit,	/* ERASE */	ERASEinit,	/* SELECT */	SELinit,	/* DELSELECT */	DESELinit,	/* TENSE */	TENSEinit,	/* SKIPFILE */	RFMinit,	/* CMD OK? */	CMDOKinit,};#define SPININIT 1000000/* * Initialize a controller */aropen(sip)	register struct saioreq *sip;{	register struct ar_softc *sc;	register int count;	register struct ardevice *araddr;	int skip;		sc = (struct ar_softc *)sip->si_devdata;	araddr = sc->sc_addr = (struct ardevice *)sip->si_devaddr;	sc->sc_lastiow = 0;	sc->sc_state = IDLEstate;/*	sc->sc_status = 0;  Doesn't work, so leave it alone. */	sc->sc_size = 0;	sc->sc_bufptr = (char *) 0x1ff001;	/* very funny buf addr *//*	sc->sc_attached had better already be 1. */	sc->sc_initted = 0;			/* until later */	sc->sc_opened = 0;			/* until later */	sc->sc_drive = 0;	sc->sc_histate = 0;/*	sc->sc_addr had better already be initialized. */	sc->sc_qidle = 1;	sc->sc_eoflag = 0;	sc->sc_cmdok = 0;	sc->sc_selecteddev = -1;/* When adding new fields to softc, be sure to initialize them here. *//* FIXME, should initialize buffer headers here too */	araddr->arunwedge = 1;		/* Take it out of burst mode wedge */	araddr->arburst = 0;	araddr->arreq = 0;	araddr->arxfer = 0;	araddr->arcatch = 0;	araddr->arexcie = 0;	araddr->arrdyie = 0;	/*	 * If tape is up from previous system operation,	 * take it down gently.	 */	if (araddr->aronline) {Dprintf("ar*init tape online\n");		araddr->aronline = 0;	/* Writes TM (if writing) & rewinds */	}	count = SPININIT;	while (!araddr->arrdy && !araddr->arexc && count)		count--;if (count == 0) Dprintf("ar: Timeout waiting for Ready at %x\n", araddr);if (araddr->arrdy) Dprintf("ar*init arrdy on before reset\n");if (araddr->arexc) Dprintf("ar*init arexc on before reset\n");	/* Tape is ready or exceptional.  Reset it for good measure. */#ifdef PRFDprintf("ar*init about to arreset\n");#endif PRF	araddr->arreset = 1;#ifdef PRFDprintf("ar*init asserted arreset\n");#endif PRF	DELAY(25);	/* at least 13 usec */	araddr->arreset = 0;#ifdef PRFDprintf("ar*init Reset complete\n");#endif PRF	count = SPININIT;	while (!araddr->arexc && count)		count--;	if (count == 0) {Dprintf("ar: Timeout waiting for Exception after reset\n");		return (-1);	}	/* Now read back status from the reset. */	sc->sc_initted = 1;	/* Must do first so interrupt OK */	sc->sc_opened = 1;	/* Must do first so interrupt OK */	araddr->aronline = 1;	/* Must do first so RDST microcode doesn't				   play games with arrdy line.  See comments				   in open(). */	if (arcmd(sc, AR_STATUS)) {Dprintf("ar*init Error from command STATUS\n");		araddr->aronline = 0;		sc->sc_initted = 0;	/* Try again on next open */		sc->sc_opened = 0;	/* Try again on next open */		return (-1);	}	/*	 * FIXME, this is a kludge.  open() won't select the drive unless	 * the in-core status claims we are at BOT, since the tape drive	 * will reject the command if indeed a tape was in use and is not	 * at BOT.  However, tapes at BOT after a Reset do not necessarily	 * indicate BOT in their status.  We should probably do a rewind	 * here instead, if the tape exists.	 */	sc->sc_status.BOT = 1;	/* Pretend we're at BOT for open() */	/*	 * There is a problem in the Archive in that after each command,	 * it goes thru a cleanup routine.  If aronline is not asserted,	 * this cleanup routine drops arrdy while it rewinds the tape	 * to BOT.  It deasserts arrdy for 90 us even if the tape is	 * already at BOT.  This causes us problems because we get a arrdy	 * interrupt and then discover that arrdy is gone.	 *	 * The problem has been circumvented at the low level by checking	 * for arrdy in the interrupt routine, and looping until it (or	 * arexc) comes on.  We attempt to fix the problem here, to avoid	 * looping at SPL(), by having aronline always on when we are doing	 * anything.	 *	 * The problem seems especially a problem for us on Select and Read	 * Status commands. (That's because those are the only commands we	 * do with aronline deasserted.)	 *	 * This info was obtained from Lou Domshy, Mgr. of Product Mgmt and	 * Applications Engineering(?) at the Archive factory, 714-641-0279,	 * on 1 December 1982, by John Gilmore of Sun Microsystems.	 */	araddr->aronline = 1;		/* Let ctrlr know we are doing a series */	/*	 * First select the drive we're interested in.	 *	 * Since the select command doesn't work when we aren't at BOT,	 * we just have to hope the same drive is still selected as last	 * time.  FIXME.  We should record this info in softc and keep it	 * up to date.  FIXME: also, I'm not happy about using status.BOT	 * here, even tho it should always be up to date. -- JCGnu 22Nov82	 */	sc->sc_cmdok = 0;	(void) arcmd(sc, AR_CMDOK);	/* See if OK to issue cmds */	/*	 * Now get its status and check on a few things.	 */	if (sc->sc_cmdok) {		if (arcmd(sc, AR_STATUS)) {	/* interrupted */Dprintf("ar*open command STATUS error\n");			goto err;		}		if (sc->sc_status.NoDrive) {			printf("ar: no drive\n");			goto err;		}			if (sc->sc_status.NoCart) {			printf("ar: no cartridge in drive\n");			goto err;		}	}	if ((sip->si_flgs&F_WRITE) && sc->sc_status.WriteProt) {		printf("ar: cartridge is write protected\n");		goto err;	}	sc->sc_lastiow = 0;	skip = sip->si_boff;	while (skip--) {		arcmd(sc, AR_SKIPFILE);		arcmd(sc, AR_STATUS);	}	sc->sc_eoflag = 0;Dprintf("ar*open exiting\n");	return (0);err:	arcmd(sc, AR_DESELECT);	araddr->aronline = 0;	sc->sc_opened = 0;	return (-1);}/* * Close tape device. * * If tape was open for writing or last operation was * a write, then write two EOF's and backspace over the last one. * Unless this is a non-rewinding special file, rewind the tape. * Make the tape available to others. */arclose(sip)	struct saioreq *sip;{	register struct ar_softc *sc = (struct ar_softc *)sip->si_devdata;	register struct ardevice *araddr = sc->sc_addr;	/*	 * Write file mark and rewind, by dropping aronline.	 * FIXME.  These 3 commands should be moved into AR_CLOSE	 * in order that the user program can continue while the	 * tape is rewinding.	 */	arcmd(sc, AR_CLOSE);	/* Shut down things */	araddr->aronline = 1;		/* After rewind, set aronline */	/* See comments in open() about aronline and read status cmds */	/* FIXME, this might screw low level code if it affects arrdy */	arcmd(sc, AR_STATUS);	/* Read block counts */	arcmd(sc, AR_DESELECT);	/* Turn LED off */	sc->sc_selecteddev = -1;	sc->sc_eoflag = 0;	/* Not at eof after rewind */	sc->sc_opened = 0;	/* Available to be opened again */Dprintf("ar*close exiting\n");}arstrategy(sip, rw)	register struct saioreq *sip;	int rw;{	register struct ar_softc *sc = (struct ar_softc *)sip->si_devdata;	int func = (rw == WRITE) ? AR_WRITE : AR_READ;	if (sc->sc_eoflag) {		sc->sc_eoflag = 0;		return (0);	}	sc->sc_size = sip->si_cc;	sc->sc_bufptr = sip->si_ma;	if (arcmd(sc, func))		return (-1);	return (sip->si_cc);}/* * Begin execution of a device command for the device pointed to by * sc.  The command begins execution in state newstate. * * This is HARDWARE oriented software.  It doesn't know or care of * state of buffers, etc.  Its result reflects what the hardware is * doing, not what the software is doing. * * The device is assumed to be in one of the FIN or IDLE states: *	IDLEstate, FINstate, READfin, READidle, WRfin, or WRidle. * This is a requirement, since various fields in sc have already * been set up for us, and the use of those fields would conflict * with their use by the interrupt routine if we weren't idle or fin. * * Our result is: *	0	if the operation completed normally *	1	if the operation completed abnormally * */arcmd(sc, cmd)	register struct ar_softc *sc;{

⌨️ 快捷键说明

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