diff options
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/conf/GENERIC | 6 | ||||
-rw-r--r-- | sys/i386/conf/LINT | 4 | ||||
-rw-r--r-- | sys/i386/conf/NOTES | 4 | ||||
-rw-r--r-- | sys/i386/conf/files.i386 | 3 | ||||
-rw-r--r-- | sys/i386/isa/fd.c | 84 | ||||
-rw-r--r-- | sys/i386/isa/ft.c | 2580 | ||||
-rw-r--r-- | sys/i386/isa/ftreg.h | 90 |
7 files changed, 6 insertions, 2765 deletions
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index b0a077b6e659..5d16fd162f71 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -11,7 +11,7 @@ # device lines is present in the ./LINT configuration file. If you are # in doubt as to the purpose or necessity of a line, check first in LINT. # -# $Id: GENERIC,v 1.137 1998/12/27 13:06:40 phk Exp $ +# $Id: GENERIC,v 1.138 1998/12/27 13:12:59 phk Exp $ machine "i386" cpu "I386_CPU" @@ -58,10 +58,6 @@ controller pci0 controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 -# Unless you know very well what you're doing, leave ft0 at drive 2, or -# remove the line entirely if you don't need it. Trying to configure -# it on another unit might cause surprises, see PR kern/7176. -tape ft0 at fdc0 drive 2 options "CMD640" # work around CMD640 chip deficiency controller wdc0 at isa? port "IO_WD1" bio irq 14 diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index 02cca8b4b0ff..01cd637fd4a3 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.515 1998/12/27 12:52:45 phk Exp $ +# $Id: LINT,v 1.516 1998/12/27 13:06:40 phk Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -1021,8 +1021,6 @@ options FDC_PRINT_BOGUS_CHIPTYPE disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 -tape ft0 at fdc0 drive 2 - # # Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 02cca8b4b0ff..01cd637fd4a3 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.515 1998/12/27 12:52:45 phk Exp $ +# $Id: LINT,v 1.516 1998/12/27 13:06:40 phk Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -1021,8 +1021,6 @@ options FDC_PRINT_BOGUS_CHIPTYPE disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 -tape ft0 at fdc0 drive 2 - # # Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386 index 249a28542c05..9ce5364497db 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.210 1998/12/27 12:52:46 phk Exp $ +# $Id: files.i386,v 1.211 1998/12/27 13:06:41 phk Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -108,7 +108,6 @@ i386/isa/diskslice_machdep.c standard i386/isa/elink.c optional ep device-driver i386/isa/elink.c optional ie device-driver i386/isa/fd.c optional fd device-driver -i386/isa/ft.c optional ft device-driver i386/isa/gpib.c optional gp device-driver i386/isa/asc.c optional asc device-driver i386/isa/gsc.c optional gsc device-driver diff --git a/sys/i386/isa/fd.c b/sys/i386/isa/fd.c index e644f783957a..5380d54151d4 100644 --- a/sys/i386/isa/fd.c +++ b/sys/i386/isa/fd.c @@ -47,14 +47,10 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.128 1998/12/12 08:16:01 imp Exp $ + * $Id: fd.c,v 1.129 1998/12/14 16:29:58 bde Exp $ * */ -#include "ft.h" -#if NFT < 1 -#undef NFDC -#endif #include "fd.h" #include "opt_devfs.h" #include "opt_fdc.h" @@ -80,10 +76,6 @@ #include <i386/isa/fdc.h> #include <i386/isa/rtc.h> #include <machine/stdarg.h> -#if NFT > 0 -#include <sys/ftape.h> -#include <i386/isa/ftreg.h> -#endif #ifdef DEVFS #include <sys/devfsext.h> #endif /* DEVFS */ @@ -198,17 +190,6 @@ static struct fd_data { * fdsu is the floppy drive unit number on that controller. (sub-unit) * \***********************************************************************/ -#if NFT > 0 -int ftopen(dev_t, int); -int ftintr(ftu_t ftu); -int ftclose(dev_t, int); -void ftstrategy(struct buf *); -int ftioctl(dev_t, unsigned long, caddr_t, int, struct proc *); -int ftdump(dev_t); -int ftsize(dev_t); -int ftattach(struct isa_device *, struct isa_device *, int); -#endif - #ifdef FDC_YE #include "card.h" static int yeattach(struct isa_device *); @@ -650,9 +631,6 @@ fdattach(struct isa_device *dev) fdc_p fdc = fdc_data + fdcu; fd_p fd; int fdsu, st0, st3, i; -#if NFT > 0 - int unithasfd; -#endif struct isa_device *fdup; int ic_type = 0; #ifdef DEVFS @@ -679,7 +657,7 @@ fdattach(struct isa_device *dev) continue; fdu = fdup->id_unit; fd = &fd_data[fdu]; - if (fdu >= (NFD+NFT)) + if (fdu >= (NFD)) continue; fdsu = fdup->id_physid; /* look up what bios thinks we have */ @@ -696,26 +674,8 @@ fdattach(struct isa_device *dev) } /* is there a unit? */ if ((fdt == RTCFDT_NONE) -#if NFT > 0 - || (fdsu >= DRVS_PER_CTLR)) { -#else ) { fd->type = NO_TYPE; -#endif -#if NFT > 0 - /* If BIOS says no floppy, or > 2nd device */ - /* Probe for and attach a floppy tape. */ - /* Tell FT if there was already a disk */ - /* with this unit number found. */ - - unithasfd = 0; - if (fdu < NFD && fd->type != NO_TYPE) - unithasfd = 1; - if (ftattach(dev, fdup, unithasfd)) - continue; - if (fdsu < DRVS_PER_CTLR) - fd->type = NO_TYPE; -#endif continue; } @@ -1264,11 +1224,6 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p) int type = FDTYPE(minor(dev)); fdc_p fdc; -#if NFT > 0 - /* check for a tape open */ - if (type & F_TAPE_TYPE) - return(ftopen(dev, flags)); -#endif /* check bounds */ if (fdu >= NFD) return(ENXIO); @@ -1342,12 +1297,6 @@ fdclose(dev_t dev, int flags, int mode, struct proc *p) { fdu_t fdu = FDUNIT(minor(dev)); -#if NFT > 0 - int type = FDTYPE(minor(dev)); - - if (type & F_TAPE_TYPE) - return ftclose(dev, flags); -#endif fd_data[fdu].flags &= ~FD_OPEN; fd_data[fdu].options &= ~FDOPT_NORETRY; @@ -1397,20 +1346,6 @@ fdstrategy(struct buf *bp) }; #endif -#if NFT > 0 - if (FDTYPE(minor(bp->b_dev)) & F_TAPE_TYPE) { - /* ft tapes do not (yet) support strategy i/o */ - bp->b_error = ENODEV; - bp->b_flags |= B_ERROR; - goto bad; - } - /* check for controller already busy with tape */ - if (fdc->flags & FDC_TAPE_BUSY) { - bp->b_error = EBUSY; - bp->b_flags |= B_ERROR; - goto bad; - } -#endif fdblk = 128 << (fd->ft->secsize); if (!(bp->b_flags & B_FORMAT)) { if ((fdu >= NFD) || (bp->b_blkno < 0)) { @@ -1544,13 +1479,6 @@ static void fdintr(fdcu_t fdcu) { fdc_p fdc = fdc_data + fdcu; -#if NFT > 0 - fdu_t fdu = fdc->fdu; - - if (fdc->flags & FDC_TAPE_BUSY) - (ftintr(fdu)); - else -#endif while(fdstate(fdcu, fdc)) ; } @@ -2251,14 +2179,6 @@ fdioctl(dev, cmd, addr, flag, p) char buffer[DEV_BSIZE]; int error = 0; -#if NFT > 0 - int type = FDTYPE(minor(dev)); - - /* check for a tape ioctl */ - if (type & F_TAPE_TYPE) - return ftioctl(dev, cmd, addr, flag, p); -#endif - fdblk = 128 << fd->ft->secsize; switch (cmd) diff --git a/sys/i386/isa/ft.c b/sys/i386/isa/ft.c deleted file mode 100644 index 097bbb6a0c3f..000000000000 --- a/sys/i386/isa/ft.c +++ /dev/null @@ -1,2580 +0,0 @@ -/* - * Copyright (c) 1993, 1994 Steve Gerakines - * - * This is freely redistributable software. You may do anything you - * wish with it, so long as the above notice stays intact. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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. - * - * ft.c - QIC-40/80 floppy tape driver - * $Id: ft.c,v 1.38 1998/07/15 09:59:31 bde Exp $ - * - * 01/19/95 ++sg - * Cleaned up recalibrate/seek code at attach time for FreeBSD 2.x. - * - * 06/07/94 v0.9 ++sg - * Tape stuck on segment problem should be gone. Re-wrote buffering - * scheme. Added support for drives that do not automatically perform - * seek load point. Can handle more wakeup types now and should correctly - * report most manufacturer names. Fixed places where unit 0 was being - * sent to the fdc instead of the actual unit number. Added ioctl support - * for an in-core badmap. - * - * 01/26/94 v0.3b - Jim Babb - * Got rid of the hard coded device selection. Moved (some of) the - * static variables into a structure for support of multiple devices. - * ( still has a way to go for 2 controllers - but closer ) - * Changed the interface with fd.c so we no longer 'steal' its - * driver routine vectors. - * - * 10/30/93 v0.3 - * Fixed a couple more bugs. Reading was sometimes looping when an - * an error such as address-mark-missing was encountered. Both - * reading and writing was having more backup-and-retries than was - * necessary. Added support to get hardware info. Updated for use - * with FreeBSD. - * - * 09/15/93 v0.2 pl01 - * Fixed a bunch of bugs: extra isa_dmadone() in async_write() (shouldn't - * matter), fixed double buffering in async_req(), changed tape_end() in - * set_fdcmode() to reduce unexpected interrupts, changed end of track - * processing in async_req(), protected more of ftreq_rw() with an - * splbio(). Changed some of the ftreq_*() functions so that they wait - * for inactivity and then go, instead of aborting immediately. - * - * 08/07/93 v0.2 release - * Shifted from ftstrat to ioctl support for I/O. Streaming is now much - * more reliable. Added internal support for error correction, QIC-40, - * and variable length tapes. Random access of segments greatly - * improved. Formatting and verification support is close but still - * incomplete. - * - * 06/03/93 v0.1 Alpha release - * Hopefully the last re-write. Many bugs fixed, many remain. - */ - -#include "ft.h" -#if NFT > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/disklabel.h> /* temp. for dkunit() in fdc.h */ -#include <sys/malloc.h> -#include <sys/buf.h> -#include <sys/ftape.h> -#include <sys/kernel.h> - -#include <machine/clock.h> - -#include <i386/isa/isa_device.h> -#ifdef PC98 -#include <pc98/pc98/fdreg.h> -#else -#include <i386/isa/fdreg.h> -#endif -#include <i386/isa/fdc.h> -#include <i386/isa/ftreg.h> - -extern int ftintr __P((ftu_t ftu)); - -/* Enable or disable debugging messages. */ -#define FTDBGALL 0 /* 1 if you want everything */ -/*#define DPRT(a) printf a */ -#define DPRT(a) - -/* Constants private to the driver */ -#define FTPRI (PRIBIO) /* sleep priority */ -#define FTNBUFF 9 /* 8 for buffering, 1 for header */ - -/* The following items are needed from the fd driver. */ -extern int in_fdc(int); /* read fdc registers */ -extern int out_fdc(int, int); /* write fdc registers */ - -/* Flags in isadev struct */ -#define FT_PROBE 0x1 /* allow for "dangerous" tape probes */ - -/* Type of tape attached */ -/* use numbers that don't interfere with the possible floppy types */ -#define NO_TYPE 0 /* (same as NO_TYPE in fd.c) */ - -/* F_TAPE_TYPE must match value in fd.c */ -#define F_TAPE_TYPE 0x020 /* bit for ft->types to indicate tape */ -#define FT_NONE (F_TAPE_TYPE | 0) /* no method required */ -#define FT_MOUNTAIN (F_TAPE_TYPE | 1) /* mountain */ -#define FT_COLORADO (F_TAPE_TYPE | 2) /* colorado */ -#define FT_INSIGHT (F_TAPE_TYPE | 3) /* insight */ - -/* Mode FDC is currently in: tape or disk */ -enum { FDC_TAPE_MODE, FDC_DISK_MODE }; - -/* Command we are awaiting completion of */ -enum { FTCMD_NONE, FTCMD_RESET, FTCMD_RECAL, FTCMD_SEEK, FTCMD_READID }; - -/* Tape interrupt status of current request */ -enum { FTSTS_NONE, FTSTS_SNOOZE, FTSTS_INTERRUPT, FTSTS_TIMEOUT }; - -/* Tape I/O status */ -enum { - FTIO_READY, /* No I/O activity */ - FTIO_READING, /* Currently reading blocks */ - FTIO_RDAHEAD, /* Currently reading ahead */ - FTIO_WRITING /* Buffers are being written */ -}; - -/* Current tape mode */ -enum { - FTM_PRIMARY, /* Primary mode */ - FTM_VERIFY, /* Verify mode */ - FTM_FORMAT, /* Format mode */ - FTM_DIAG1, /* Diagnostic mode 1 */ - FTM_DIAG2 /* Diagnostic mode 2 */ -}; - -/* Tape geometries table */ -static QIC_Geom ftgtbl[] = { - { 0, 0, "Unformatted", "Unknown", 0, 0, 0, 0, 0 }, /* XXX */ - { 1, 1, "QIC-40", "205/550", 20, 68, 2176, 128, 21760 }, - { 1, 2, "QIC-40", "307.5/550", 20, 102, 3264, 128, 32640 }, - { 1, 3, "QIC-40", "295/900", 0, 0, 0, 0, 0 }, /* ??? */ - { 1, 4, "QIC-40", "1100/550", 20, 365, 11680, 128, 32512 }, - { 1, 5, "QIC-40", "1100/900", 0, 0, 0, 0, 0 }, /* ??? */ - { 2, 1, "QIC-80", "205/550", 28, 100, 3200, 128, 19200 }, - { 2, 2, "QIC-80", "307.5/550", 28, 150, 4800, 128, 19200 }, - { 2, 3, "QIC-80", "295/900", 0, 0, 0, 0, 0 }, /* ??? */ - { 2, 4, "QIC-80", "1100/550", 28, 537, 17184, 128, 32512 }, - { 2, 5, "QIC-80", "1100/900", 0, 0, 0, 0, 0 }, /* ??? */ - { 3, 1, "QIC-500", "205/550", 0, 0, 0, 0, 0 }, /* ??? */ - { 3, 2, "QIC-500", "307.5/550", 0, 0, 0, 0, 0 }, /* ??? */ - { 3, 3, "QIC-500", "295/900", 0, 0, 0, 0, 0 }, /* ??? */ - { 3, 4, "QIC-500", "1100/550", 0, 0, 0, 0, 0 }, /* ??? */ - { 3, 5, "QIC-500", "1100/900", 0, 0, 0, 0, 0 } /* ??? */ -}; -#define NGEOM (sizeof(ftgtbl) / sizeof(QIC_Geom)) - -static QIC_Geom *ftg = NULL; /* Current tape's geometry */ - -/* - * things relating to asynchronous commands - */ -static int awr_state; /* state of async write */ -static int ard_state; /* state of async read */ -static int arq_state; /* state of async request */ -static int async_retries; /* retries, one per invocation */ -static int async_func; /* function to perform */ -static int async_state; /* state current function is at */ -static int async_arg0; /* up to 3 arguments for async cmds */ -static int async_arg1; /**/ -static int async_arg2; /**/ -static int async_ret; /* return value */ -static struct _astk { - int over_func; - int over_state; - int over_retries; - int over_arg0; - int over_arg1; - int over_arg2; -} astk[10]; -static struct _astk *astk_ptr = &astk[0]; /* Pointer to stack position */ - -/* List of valid async (interrupt driven) tape support functions. */ -enum { - ACMD_NONE, /* no command */ - ACMD_SEEK, /* command seek */ - ACMD_STATUS, /* report status */ - ACMD_STATE, /* wait for state bits to be true */ - ACMD_SEEKSTS, /* perform command and wait for status */ - ACMD_READID, /* read id */ - ACMD_RUNBLK /* ready tape for I/O on the given block */ -}; - -/* Call another asyncronous command from within async_cmd(). */ -#define CALL_ACMD(r,f,a,b,c) \ - astk_ptr->over_retries = async_retries; \ - astk_ptr->over_func = async_func; \ - astk_ptr->over_state = (r); \ - astk_ptr->over_arg0 = async_arg0; \ - astk_ptr->over_arg1 = async_arg1; \ - astk_ptr->over_arg2 = async_arg2; \ - async_func = (f); async_state = 0; async_retries = 0; \ - async_arg0=(a); async_arg1=(b); async_arg2=(c); \ - astk_ptr++; \ - goto restate - -/* Perform an asyncronous command from outside async_cmd(). */ -#define ACMD_FUNC(r,f,a,b,c) over_async = (r); astk_ptr = &astk[0]; \ - async_func = (f); async_state = 0; async_retries = 0; \ - async_arg0=(a); async_arg1=(b); async_arg2=(c); \ - async_cmd(ftu); \ - return - -/* Various wait channels */ -static char *wc_buff_avail = "bavail"; -static char *wc_buff_done = "bdone"; -static char *wc_iosts_change = "iochg"; -static char *wc_long_delay = "ldelay"; -static char *wc_intr_wait = "intrw"; -#define ftsleep(wc,to) tsleep((caddr_t)(wc),FTPRI,(wc),(to)) - -/***********************************************************************\ -* Per controller structure. * -\***********************************************************************/ -extern struct fdc_data fdc_data[NFDC]; - -/***********************************************************************\ -* Per tape drive structure. * -\***********************************************************************/ -static struct ft_data { - struct fdc_data *fdc; /* pointer to controller structure */ - int ftsu; /* this units number on this controller */ - int type; /* Drive type (Mountain, Colorado) */ -/* QIC_Geom *ftg; */ /* pointer to Current tape's geometry */ - int flags; - int cmd_wait; /* Command we are awaiting completion of */ - int sts_wait; /* Tape interrupt status of current request */ - int io_sts; /* Tape I/O status */ - int mode; - int pcn; /* present cylinder number */ - int attaching; /* true when ft is attaching */ - unsigned char *xptr; /* pointer to buffer blk to xfer */ - int xcnt; /* transfer count */ - int xblk; /* block number to transfer */ - int xseg; /* segment being transferred */ - SegReq *segh; /* Current I/O request */ - SegReq *segt; /* Tail of queued I/O requests */ - SegReq *doneh; /* Completed I/O request queue */ - SegReq *donet; /* Completed I/O request tail */ - SegReq *segfree; /* Free segments */ - SegReq *hdr; /* Current tape header */ - int nsegq; /* Segments on request queue */ - int ndoneq; /* Segments on completed queue */ - int nfreelist; /* Segments on free list */ - - /* the next 3 should be defines in 'flags' */ - int active; /* TRUE if transfer is active */ - int rdonly; /* TRUE if tape is read-only */ - int newcart; /* TRUE if new cartridge detected */ - int laststs; /* last reported status code */ - int lastcfg; /* last reported QIC config */ - int lasterr; /* last QIC error code */ - int lastpos; /* last known segment number */ - int moving; /* TRUE if tape is moving */ - int rid[7]; /* read_id return values */ - struct callout_handle tohandle; -} *ft_data[NFT]; - -/***********************************************************************\ -* Throughout this file the following conventions will be used: * -* ft is a pointer to the ft_data struct for the drive in question * -* fdc is a pointer to the fdc_data struct for the controller * -* ftu is the tape drive unit number * -* fdcu is the floppy controller unit number * -* ftsu is the tape drive unit number on that controller. (sub-unit) * -\***********************************************************************/ - - - -#define id_physid id_scsiid /* this biotab field doubles as a field */ - /* for the physical unit number on the controller */ - -int ftopen(dev_t, int); -int ftclose(dev_t, int); -int ftioctl(dev_t, unsigned long, caddr_t, int, struct proc *); -int ftattach(struct isa_device *, struct isa_device *, int); -static timeout_t ft_timeout; -static void async_cmd(ftu_t); -static void async_req(ftu_t, int); -static void async_read(ftu_t, int); -static void async_write(ftu_t, int); -static void tape_start(ftu_t, int); -static void tape_end(ftu_t); -static void tape_inactive(ftu_t); -static int tape_cmd(ftu_t, int); -static int tape_status(ftu_t); -static int qic_status(ftu_t, int, int); -static int ftreq_rewind(ftu_t); -static int ftreq_hwinfo(ftu_t, QIC_HWInfo *); - -/*****************************************************************************/ - - -/* - * Allocate a segment I/O buffer from the free list. - */ -static SegReq * -segio_alloc(ft_p ft) -{ - SegReq *r; - - /* Grab first item from free list */ - if ((r = ft->segfree) != NULL) { - ft->segfree = ft->segfree->next; - ft->nfreelist--; - } - DPRT(("segio_alloc: nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); - return(r); -} - - -/* - * Queue a segment I/O request. - */ -static void -segio_queue(ft_p ft, SegReq *sp) -{ - /* Put request on in process queue. */ - if (ft->segt == NULL) - ft->segh = sp; - else - ft->segt->next = sp; - sp->next = NULL; - ft->segt = sp; - ft->nsegq++; - DPRT(("segio_queue: nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); -} - - -/* - * Segment I/O completed, place on correct queue. - */ -static void -segio_done(ft_p ft, SegReq *sp) -{ - /* First remove from current I/O queue */ - ft->segh = sp->next; - if (ft->segh == NULL) ft->segt = NULL; - ft->nsegq--; - - if (sp->reqtype == FTIO_WRITING) { - /* Place on free list */ - sp->next = ft->segfree; - ft->segfree = sp; - ft->nfreelist++; - wakeup((caddr_t)wc_buff_avail); - DPRT(("segio_done: (w) nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); - } else { - /* Put on completed I/O queue */ - if (ft->donet == NULL) - ft->doneh = sp; - else - ft->donet->next = sp; - sp->next = NULL; - ft->donet = sp; - ft->ndoneq++; - wakeup((caddr_t)wc_buff_done); - DPRT(("segio_done: (r) nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); - } -} - - -/* - * Take I/O request from finished queue to free queue. - */ -static void -segio_free(ft_p ft, SegReq *sp) -{ - /* First remove from done queue */ - ft->doneh = sp->next; - if (ft->doneh == NULL) ft->donet = NULL; - ft->ndoneq--; - - /* Place on free list */ - sp->next = ft->segfree; - ft->segfree = sp; - ft->nfreelist++; - wakeup((caddr_t)wc_buff_avail); - DPRT(("segio_free: nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); -} - -/* - * Probe/attach floppy tapes. - */ -int -ftattach(isadev, fdup, unithasfd) - struct isa_device *isadev, *fdup; - int unithasfd; -{ - fdcu_t fdcu = isadev->id_unit; /* fdc active unit */ - fdc_p fdc = fdc_data + fdcu; /* pointer to controller structure */ - ftu_t ftu = fdup->id_unit; - ft_p ft; - ftsu_t ftsu = fdup->id_physid; - QIC_HWInfo hw; - char *manu; - - if (ftu >= NFT) return 0; - ft = ft_data[ftu] = malloc(sizeof *ft, M_DEVBUF, M_WAITOK); - bzero(ft, sizeof *ft); - callout_handle_init(&ft->tohandle); - - /* Probe for tape */ - ft->attaching = 1; - ft->type = NO_TYPE; - ft->fdc = fdc; - ft->ftsu = ftsu; - - /* - * FT_NONE - no method, just do it - */ - tape_start(ftu, 0); - if (tape_status(ftu) >= 0) { - ft->type = FT_NONE; - ftreq_hwinfo(ftu, &hw); - goto out; - } - - /* - * FT_COLORADO - colorado style - */ - tape_start(ftu, 0); - tape_cmd(ftu, QC_COL_ENABLE1); - tape_cmd(ftu, QC_COL_ENABLE2 + ftu); - if (tape_status(ftu) >= 0) { - ft->type = FT_COLORADO; - ftreq_hwinfo(ftu, &hw); - tape_cmd(ftu, QC_COL_DISABLE); - goto out; - } - - /* - * FT_MOUNTAIN - mountain style - */ - tape_start(ftu, 0); - tape_cmd(ftu, QC_MTN_ENABLE1); - tape_cmd(ftu, QC_MTN_ENABLE2); - if (tape_status(ftu) >= 0) { - ft->type = FT_MOUNTAIN; - ftreq_hwinfo(ftu, &hw); - tape_cmd(ftu, QC_MTN_DISABLE); - goto out; - } - - if(isadev->id_flags & FT_PROBE) { - /* - * Insight probe is dangerous, since it requires the motor being - * enabled and therefore risks attached floppy disk drives to jam. - * Probe only if explicitly requested by a flag 0x1 from config - */ - - /* - * FT_INSIGHT - insight style - * - * Since insight requires turning the drive motor on, we will not - * perform this probe if a floppy drive was already found with the - * the given unit and controller. - */ - if (unithasfd) goto out; - tape_start(ftu, 1); - if (tape_status(ftu) >= 0) { - ft->type = FT_INSIGHT; - ftreq_hwinfo(ftu, &hw); - goto out; - } - } - -out: - tape_end(ftu); - if (ft->type != NO_TYPE) { - fdc->flags |= FDC_HASFTAPE; - switch(hw.hw_make) { - case 0x0000: - if (ft->type == FT_COLORADO) { - manu = "Colorado"; - } else if (ft->type == FT_INSIGHT) { - manu = "Insight"; - } else if (ft->type == FT_MOUNTAIN && hw.hw_model == 0x05) { - manu = "Archive"; - } else if (ft->type == FT_MOUNTAIN) { - manu = "Mountain"; - } else { - manu = "Unknown"; - } - break; - case 0x0001: - manu = "Colorado"; - break; - case 0x0005: - if (hw.hw_model >= 0x09) { - manu = "Conner"; - } else { - manu = "Archive"; - } - break; - case 0x0006: - manu = "Mountain"; - break; - case 0x0007: - manu = "Wangtek"; - break; - case 0x0222: - manu = "IOMega"; - break; - default: - manu = "Unknown"; - break; - } - printf("ft%d: %s tape\n", fdup->id_unit, manu); - } - ft->attaching = 0; - return(ft->type); -} - - -/* - * Perform common commands asynchronously. - */ -static void -async_cmd(ftu_t ftu) { - ft_p ft = ft_data[ftu]; - fdcu_t fdcu = ft->fdc->fdcu; - int cmd, i, st0, st3, pcn; - static int bitn, retval, retpos, nbits, newcn; - static int wanttrk, wantblk, wantdir; - static int curtrk, curblk, curdir, curdiff; - static int errcnt = 0; - -restate: -#if FTDBGALL - DPRT(("async_cmd state: func: %d state: %d\n", async_func, async_state)); -#endif - switch(async_func) { - case ACMD_SEEK: - /* - * Arguments: - * 0 - command to perform - */ - switch (async_state) { - case 0: - cmd = async_arg0; -#if FTDBGALL - DPRT(("===>async_seek cmd = %d\n", cmd)); -#endif - newcn = (cmd <= ft->pcn) ? ft->pcn - cmd : ft->pcn + cmd; - async_state = 1; - i = 0; - if (out_fdc(fdcu, NE7CMD_SEEK) < 0) i = 1; - if (!i && out_fdc(fdcu, ftu) < 0) i = 1; - if (!i && out_fdc(fdcu, newcn) < 0) i = 1; - if (i) { - if (++async_retries >= 10) { - DPRT(("ft%d: async_cmd command seek failed!!\n", ftu)); - goto complete; - } - DPRT(("ft%d: async_cmd command seek retry...\n",ftu)); - async_state = 0; - goto restate; - } - break; - case 1: - out_fdc(fdcu, NE7CMD_SENSEI); - st0 = in_fdc(fdcu); - pcn = in_fdc(fdcu); - if (st0 < 0 || pcn < 0 || newcn != pcn) { - if (++async_retries >= 10) { - DPRT(("ft%d: async_cmd seek retries exceeded\n",ftu)); - goto complete; - } - DPRT(("ft%d: async_cmd command bad st0=$%02x pcn=$%02x\n", - ftu, st0, pcn)); - async_state = 0; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); - break; - } - if (st0 & 0x20) { /* seek done */ - ft->pcn = pcn; - } -#if FTDBGALL - else - DPRT(("ft%d: async_seek error st0 = $%02x pcn = %d\n", - ftu, st0, pcn)); -#endif - if (async_arg1) goto complete; - async_state = 2; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/50); - break; - case 2: - goto complete; - /* NOTREACHED */ - } - break; - - case ACMD_STATUS: - /* - * Arguments: - * 0 - command to issue report from - * 1 - number of bits - * modifies: bitn, retval, st3 - */ - switch (async_state) { - case 0: - bitn = 0; - retval = 0; - cmd = async_arg0; - nbits = async_arg1; - DPRT(("async_status got cmd = %d nbits = %d\n", cmd,nbits)); - CALL_ACMD(5, ACMD_SEEK, QC_NEXTBIT, 0, 0); - /* NOTREACHED */ - case 1: - out_fdc(fdcu, NE7CMD_SENSED); - out_fdc(fdcu, ftu); - st3 = in_fdc(fdcu); - if (st3 < 0) { - DPRT(("ft%d: async_status timed out on bit %d r=$%02x\n", - ftu,bitn,retval)); - async_ret = -1; - goto complete; - } - if ((st3 & 0x10) != 0) retval |= (1 << bitn); - bitn++; - if (bitn >= (nbits+2)) { - if ((retval & 1) && (retval & (1 << (nbits+1)))) { - async_ret = (retval & ~(1<<(nbits+1))) >> 1; - if (async_arg0 == QC_STATUS && async_arg2 == 0 && - (async_ret & (QS_ERROR|QS_NEWCART))) { - async_state = 2; - goto restate; - } - DPRT(("async status got $%04x ($%04x)\n", async_ret,retval)); - } else { - DPRT(("ft%d: async_status failed: retval=$%04x nbits=%d\n", - ftu, retval,nbits)); - async_ret = -2; - } - goto complete; - } - CALL_ACMD(1, ACMD_SEEK, QC_NEXTBIT, 0, 0); - /* NOTREACHED */ - case 2: - if (async_ret & QS_NEWCART) ft->newcart = 1; - CALL_ACMD(3, ACMD_STATUS, QC_ERRCODE, 16, 1); - case 3: - ft->lasterr = async_ret; - if ((ft->lasterr & QS_NEWCART) == 0 && ft->lasterr) { - DPRT(("ft%d: QIC error %d occurred on cmd %d\n", - ftu, ft->lasterr & 0xff, ft->lasterr >> 8)); - } - cmd = async_arg0; - nbits = async_arg1; - CALL_ACMD(4, ACMD_STATUS, QC_STATUS, 8, 1); - case 4: - goto complete; - case 5: - CALL_ACMD(6, ACMD_SEEK, QC_NEXTBIT, 0, 0); - case 6: - CALL_ACMD(7, ACMD_SEEK, QC_NEXTBIT, 0, 0); - case 7: - CALL_ACMD(8, ACMD_SEEK, QC_NEXTBIT, 0, 0); - case 8: - cmd = async_arg0; - CALL_ACMD(1, ACMD_SEEK, cmd, 0, 0); - } - break; - - case ACMD_STATE: - /* - * Arguments: - * 0 - status bits to check - */ - switch(async_state) { - case 0: - CALL_ACMD(1, ACMD_STATUS, QC_STATUS, 8, 0); - case 1: - if ((async_ret & async_arg0) != 0) goto complete; - async_state = 0; - if (++async_retries == 360) { /* 90 secs. */ - DPRT(("ft%d: acmd_state exceeded retry count\n", ftu)); - goto complete; - } - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/4); - break; - } - break; - - case ACMD_SEEKSTS: - /* - * Arguments: - * 0 - command to perform - * 1 - status bits to check - * 2 - (optional) seconds to wait until completion - */ - switch(async_state) { - case 0: - cmd = async_arg0; - async_retries = (async_arg2) ? (async_arg2 * 4) : 10; - CALL_ACMD(1, ACMD_SEEK, cmd, 0, 0); - case 1: - CALL_ACMD(2, ACMD_STATUS, QC_STATUS, 8, 0); - case 2: - if ((async_ret & async_arg1) != 0) goto complete; - if (--async_retries == 0) { - DPRT(("ft%d: acmd_seeksts retries exceeded\n", ftu)); - goto complete; - } - async_state = 1; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/4); - break; - } - break; - - case ACMD_READID: - /* - * Arguments: (none) - */ - switch(async_state) { - case 0: - if (!ft->moving) { - CALL_ACMD(4, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); - /* NOTREACHED */ - } - async_state = 1; - out_fdc(fdcu, 0x4a); /* READ_ID */ - out_fdc(fdcu, ftu); - break; - case 1: - for (i = 0; i < 7; i++) ft->rid[i] = in_fdc(fdcu); - async_ret = (ft->rid[3]*ftg->g_fdtrk) + - (ft->rid[4]*ftg->g_fdside) + ft->rid[5] - 1; - DPRT(("readid st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d\n", - ft->rid[0], ft->rid[1], ft->rid[2], ft->rid[3], - ft->rid[4], ft->rid[5], async_ret)); - if ((ft->rid[0] & 0xc0) != 0 || async_ret < 0) { - /* - * Method for retry: - * errcnt == 1 regular retry - * 2 microstep head 1 - * 3 microstep head 2 - * 4 microstep head back to 0 - * 5 fail - */ - if (++errcnt >= 5) { - DPRT(("ft%d: acmd_readid errcnt exceeded\n", fdcu)); - async_ret = -2; - errcnt = 0; - goto complete; - } - if (errcnt == 1) { - ft->moving = 0; - CALL_ACMD(4, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); - } else { - ft->moving = 0; - CALL_ACMD(4, ACMD_SEEKSTS, QC_STPAUSE, QS_READY, 0); - } - DPRT(("readid retry %d...\n", errcnt)); - async_state = 0; - goto restate; - } - if ((async_ret % ftg->g_blktrk) == (ftg->g_blktrk-1)) { - DPRT(("acmd_readid detected last block on track\n")); - retpos = async_ret; - CALL_ACMD(2, ACMD_STATE, QS_BOT|QS_EOT, 0, 0); - /* NOTREACHED */ - } - ft->lastpos = async_ret; - errcnt = 0; - goto complete; - /* NOTREACHED */ - case 2: - CALL_ACMD(3, ACMD_STATE, QS_READY, 0, 0); - case 3: - ft->moving = 0; - async_ret = retpos+1; - goto complete; - case 4: - CALL_ACMD(5, ACMD_SEEK, QC_FORWARD, 0, 0); - case 5: - ft->moving = 1; - async_state = 0; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ - break; - } - break; - - case ACMD_RUNBLK: - /* - * Arguments: - * 0 - block number I/O will be performed on - * - * modifies: curpos - */ - switch (async_state) { - case 0: - wanttrk = async_arg0 / ftg->g_blktrk; - wantblk = async_arg0 % ftg->g_blktrk; - wantdir = wanttrk & 1; - ft->moving = 0; - CALL_ACMD(1, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); - case 1: - curtrk = wanttrk; - curdir = curtrk & 1; - DPRT(("Changing to track %d\n", wanttrk)); - CALL_ACMD(2, ACMD_SEEK, QC_SEEKTRACK, 0, 0); - case 2: - cmd = wanttrk+2; - CALL_ACMD(3, ACMD_SEEKSTS, cmd, QS_READY, 0); - case 3: - CALL_ACMD(4, ACMD_STATUS, QC_STATUS, 8, 0); - case 4: - ft->laststs = async_ret; - if (wantblk == 0) { - curblk = 0; - cmd = (wantdir) ? QC_SEEKEND : QC_SEEKSTART; - CALL_ACMD(6, ACMD_SEEKSTS, cmd, QS_READY, 90); - } - if (ft->laststs & QS_BOT) { - DPRT(("Tape is at BOT\n")); - curblk = (wantdir) ? 4800 : 0; - async_state = 6; - goto restate; - } - if (ft->laststs & QS_EOT) { - DPRT(("Tape is at EOT\n")); - curblk = (wantdir) ? 0 : 4800; - async_state = 6; - goto restate; - } - CALL_ACMD(5, ACMD_READID, 0, 0, 0); - case 5: - if (async_ret < 0) { - ft->moving = 0; - ft->lastpos = -2; - if (async_ret == -2) { - CALL_ACMD(9, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); - } - CALL_ACMD(1, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); - } - curtrk = (async_ret+1) / ftg->g_blktrk; - curblk = (async_ret+1) % ftg->g_blktrk; - DPRT(("gotid: curtrk=%d wanttrk=%d curblk=%d wantblk=%d\n", - curtrk, wanttrk, curblk, wantblk)); - if (curtrk != wanttrk) { /* oops! */ - DPRT(("oops!! wrong track!\n")); - CALL_ACMD(1, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); - } - async_state = 6; - goto restate; - case 6: - DPRT(("curtrk = %d nextblk = %d\n", curtrk, curblk)); - if (curblk == wantblk) { - ft->lastpos = curblk - 1; - async_ret = ft->lastpos; - if (ft->moving) goto complete; - CALL_ACMD(7, ACMD_STATE, QS_READY, 0, 0); - } - if (curblk > wantblk) { /* passed it */ - ft->moving = 0; - CALL_ACMD(10, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); - } - if ((wantblk - curblk) <= 256) { /* approaching it */ - CALL_ACMD(5, ACMD_READID, 0, 0, 0); - } - /* way up ahead */ - ft->moving = 0; - CALL_ACMD(14, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); - break; - case 7: - ft->moving = 1; - CALL_ACMD(8, ACMD_SEEK, QC_FORWARD, 0, 0); - break; - case 8: - async_state = 9; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ - break; - case 9: - goto complete; - case 10: - curdiff = ((curblk - wantblk) / QCV_BLKSEG) + 2; - if (curdiff >= ftg->g_segtrk) curdiff = ftg->g_segtrk - 1; - DPRT(("pos %d past %d, reverse %d\n", curblk, wantblk, curdiff)); - CALL_ACMD(11, ACMD_SEEK, QC_SEEKREV, 0, 0); - case 11: - DPRT(("reverse 1 done\n")); - CALL_ACMD(12, ACMD_SEEK, (curdiff & 0xf)+2, 0, 0); - case 12: - DPRT(("reverse 2 done\n")); - CALL_ACMD(13, ACMD_SEEKSTS, ((curdiff>>4)&0xf)+2, QS_READY, 90); - case 13: - CALL_ACMD(5, ACMD_READID, 0, 0, 0); - case 14: - curdiff = ((wantblk - curblk) / QCV_BLKSEG) - 2; - if (curdiff < 0) curdiff = 0; - DPRT(("pos %d before %d, forward %d\n", curblk, wantblk, curdiff)); - CALL_ACMD(15, ACMD_SEEK, QC_SEEKFWD, 0, 0); - case 15: - DPRT(("forward 1 done\n")); - CALL_ACMD(16, ACMD_SEEK, (curdiff & 0xf)+2, 0, 0); - case 16: - DPRT(("forward 2 done\n")); - CALL_ACMD(13, ACMD_SEEKSTS, ((curdiff>>4)&0xf)+2, QS_READY, 90); - } - break; - } - - return; - -complete: - if (astk_ptr != &astk[0]) { - astk_ptr--; - async_retries = astk_ptr->over_retries; - async_func = astk_ptr->over_func; - async_state = astk_ptr->over_state; - async_arg0 = astk_ptr->over_arg0; - async_arg1 = astk_ptr->over_arg1; - async_arg2 = astk_ptr->over_arg2; - goto restate; - } - async_func = ACMD_NONE; - async_state = 0; - switch (ft->io_sts) { - case FTIO_READY: - async_req(ftu, 2); - break; - case FTIO_READING: - case FTIO_RDAHEAD: - async_read(ftu, 2); - break; - case FTIO_WRITING: - async_write(ftu, 2); - break; - default: - DPRT(("ft%d: bad async_cmd ending I/O state!\n", ftu)); - break; - } -} - - -/* - * Entry point for the async request processor. - */ -static void -async_req(ftu_t ftu, int from) -{ - ft_p ft = ft_data[ftu]; - SegReq *sp; - static int over_async, lastreq; - int cmd; - - if (from == 2) arq_state = over_async; - -restate: - switch (arq_state) { - case 0: /* Process segment */ - sp = ft->segh; - ft->io_sts = (sp == NULL) ? FTIO_READY : sp->reqtype; - - if (ft->io_sts == FTIO_WRITING) - async_write(ftu, from); - else - async_read(ftu, from); - if (ft->io_sts != FTIO_READY) return; - - /* Pull buffer from current I/O queue */ - if (sp != NULL) { - lastreq = sp->reqtype; - segio_done(ft, sp); - - /* If I/O cancelled, clear finished queue. */ - if (sp->reqcan) { - while (ft->doneh != NULL) - segio_free(ft, ft->doneh); - lastreq = FTIO_READY; - } - } else - lastreq = FTIO_READY; - - /* Detect end of track */ - if (((ft->xblk / QCV_BLKSEG) % ftg->g_segtrk) == 0) { - ACMD_FUNC(2, ACMD_STATE, QS_BOT|QS_EOT, 0, 0); - } - arq_state = 1; - goto restate; - - case 1: /* Next request */ - /* If we have another request queued, start it running. */ - if (ft->segh != NULL) { - sp = ft->segh; - sp->reqcrc = 0; - arq_state = ard_state = awr_state = 0; - ft->xblk = sp->reqblk; - ft->xseg = sp->reqseg; - ft->xcnt = 0; - ft->xptr = sp->buff; - DPRT(("I/O reqblk = %d\n", ft->xblk)); - goto restate; - } - - /* If the last request was reading, do read ahead. */ - if ((lastreq == FTIO_READING || lastreq == FTIO_RDAHEAD) && - (sp = segio_alloc(ft)) != NULL) { - sp->reqtype = FTIO_RDAHEAD; - sp->reqblk = ft->xblk; - sp->reqseg = ft->xseg+1; - sp->reqcrc = 0; - sp->reqcan = 0; - segio_queue(ft, sp); - bzero(sp->buff, QCV_SEGSIZE); - arq_state = ard_state = awr_state = 0; - ft->xblk = sp->reqblk; - ft->xseg = sp->reqseg; - ft->xcnt = 0; - ft->xptr = sp->buff; - DPRT(("Processing readahead reqblk = %d\n", ft->xblk)); - goto restate; - } - - if (ft->moving) { - DPRT(("No more I/O.. Stopping.\n")); - ft->moving = 0; - ACMD_FUNC(7, ACMD_SEEKSTS, QC_PAUSE, QS_READY, 0); - break; - } - arq_state = 7; - goto restate; - - case 2: /* End of track */ - ft->moving = 0; - ACMD_FUNC(3, ACMD_STATE, QS_READY, 0, 0); - break; - - case 3: - DPRT(("async_req seek head to track %d\n", ft->xblk / ftg->g_blktrk)); - ACMD_FUNC(4, ACMD_SEEK, QC_SEEKTRACK, 0, 0); - break; - - case 4: - cmd = (ft->xblk / ftg->g_blktrk) + 2; - if (ft->segh != NULL) { - ACMD_FUNC(5, ACMD_SEEKSTS, cmd, QS_READY, 0); - } else { - ACMD_FUNC(7, ACMD_SEEKSTS, cmd, QS_READY, 0); - } - break; - - case 5: - ft->moving = 1; - ACMD_FUNC(6, ACMD_SEEK, QC_FORWARD, 0, 0); - break; - - case 6: - arq_state = 1; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ - break; - - case 7: - /* Time to rest. */ - ft->active = 0; - ft->lastpos = -2; - - /* wakeup those who want an i/o chg */ - wakeup((caddr_t)wc_iosts_change); - break; - } -} - - -/* - * Entry for async read. - */ -static void -async_read(ftu_t ftu, int from) -{ - ft_p ft = ft_data[ftu]; - fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ - int i, rddta[7]; - int where; - static int over_async; - static int retries = 0; - - if (from == 2) ard_state = over_async; - -restate: -#if FTDBGALL - DPRT(("async_read: state: %d from = %d\n", ard_state, from)); -#endif - switch (ard_state) { - case 0: /* Start off */ - /* If tape is not at desired position, stop and locate */ - if (ft->lastpos != (ft->xblk-1)) { - DPRT(("ft%d: position unknown: lastpos:%d ft->xblk:%d\n", - ftu, ft->lastpos, ft->xblk)); - ACMD_FUNC(1, ACMD_RUNBLK, ft->xblk, 0, 0); - } - - /* Tape is in position but stopped. */ - if (!ft->moving) { - DPRT(("async_read ******STARTING TAPE\n")); - ACMD_FUNC(3, ACMD_STATE, QS_READY, 0, 0); - } - ard_state = 1; - goto restate; - - case 1: /* Start DMA */ - /* Tape is now moving and in position-- start DMA now! */ - isa_dmastart(B_READ, ft->xptr, QCV_BLKSIZE, 2); - out_fdc(fdcu, 0x66); /* read */ - out_fdc(fdcu, ftu); /* unit */ - out_fdc(fdcu, (ft->xblk % ftg->g_fdside) / ftg->g_fdtrk); /* cylinder */ - out_fdc(fdcu, ft->xblk / ftg->g_fdside); /* head */ - out_fdc(fdcu, (ft->xblk % ftg->g_fdtrk) + 1); /* sector */ - out_fdc(fdcu, 0x03); /* 1K sectors */ - out_fdc(fdcu, (ft->xblk % ftg->g_fdtrk) + 1); /* count */ - out_fdc(fdcu, 0x74); /* gap length */ - out_fdc(fdcu, 0xff); /* transfer size */ - ard_state = 2; - break; - - case 2: /* DMA completed */ - /* Transfer complete, get status */ - for (i = 0; i < 7; i++) rddta[i] = in_fdc(fdcu); - isa_dmadone(B_READ, ft->xptr, QCV_BLKSIZE, 2); - -#if FTDBGALL - /* Compute where the controller thinks we are */ - where = (rddta[3]*ftg->g_fdtrk) + (rddta[4]*ftg->g_fdside) - + rddta[5]-1; - DPRT(("xfer done: st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d want:%d\n", - rddta[0], rddta[1], rddta[2], rddta[3], rddta[4], rddta[5], - where, ft->xblk)); -#endif - - /* Check for errors */ - if ((rddta[0] & 0xc0) != 0x00) { -#if !FTDBGALL - where = (rddta[3]*ftg->g_fdtrk) + (rddta[4]*ftg->g_fdside) - + rddta[5]-1; - DPRT(("xd: st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d want:%d\n", - rddta[0], rddta[1], rddta[2], rddta[3], rddta[4], rddta[5], - where, ft->xblk)); -#endif - if ((rddta[1] & 0x04) == 0x04 && retries < 2) { - /* Probably wrong position */ - DPRT(("async_read: doing retry %d\n", retries)); - ft->lastpos = ft->xblk; - ard_state = 0; - retries++; - goto restate; - } else { - /* CRC/Address-mark/Data-mark, et. al. */ - DPRT(("ft%d: CRC error on block %d\n", fdcu, ft->xblk)); - ft->segh->reqcrc |= (1 << ft->xcnt); - } - } - - /* Otherwise, transfer completed okay. */ - retries = 0; - ft->lastpos = ft->xblk; - ft->xblk++; - ft->xcnt++; - ft->xptr += QCV_BLKSIZE; - if (ft->xcnt < QCV_BLKSEG && ft->segh->reqcan == 0) { - ard_state = 0; - goto restate; - } - DPRT(("Read done.. Cancel = %d\n", ft->segh->reqcan)); - ft->io_sts = FTIO_READY; - break; - - case 3: - ft->moving = 1; - ACMD_FUNC(4, ACMD_SEEK, QC_FORWARD, 0, 0); - break; - - case 4: - ard_state = 1; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ - break; - - default: - DPRT(("ft%d: bad async_read state %d!!\n", ftu, ard_state)); - break; - } -} - - -/* - * Entry for async write. If from is 0, this came from the interrupt - * routine, if it's 1 then it was a timeout, if it's 2, then an - * async_cmd completed. - */ -static void -async_write(ftu_t ftu, int from) -{ - ft_p ft = ft_data[ftu]; - fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ - int i, rddta[7]; - int where; - static int over_async; - static int retries = 0; - - if (from == 2) awr_state = over_async; - -restate: -#if FTDBGALL - DPRT(("async_write: state: %d from = %d\n", awr_state, from)); -#endif - switch (awr_state) { - case 0: /* Start off */ - /* If tape is not at desired position, stop and locate */ - if (ft->lastpos != (ft->xblk-1)) { - DPRT(("ft%d: position unknown: lastpos:%d ft->xblk:%d\n", - ftu, ft->lastpos, ft->xblk)); - ACMD_FUNC(1, ACMD_RUNBLK, ft->xblk, 0, 0); - } - - /* Tape is in position but stopped. */ - if (!ft->moving) { - DPRT(("async_write ******STARTING TAPE\n")); - ACMD_FUNC(3, ACMD_STATE, QS_READY, 0, 0); - } - awr_state = 1; - goto restate; - - case 1: /* Start DMA */ - /* Tape is now moving and in position-- start DMA now! */ - isa_dmastart(B_WRITE, ft->xptr, QCV_BLKSIZE, 2); - out_fdc(fdcu, 0x45); /* write */ - out_fdc(fdcu, ftu); /* unit */ - out_fdc(fdcu, (ft->xblk % ftg->g_fdside) / ftg->g_fdtrk); /* cyl */ - out_fdc(fdcu, ft->xblk / ftg->g_fdside); /* head */ - out_fdc(fdcu, (ft->xblk % ftg->g_fdtrk) + 1); /* sector */ - out_fdc(fdcu, 0x03); /* 1K sectors */ - out_fdc(fdcu, (ft->xblk % ftg->g_fdtrk) + 1); /* count */ - out_fdc(fdcu, 0x74); /* gap length */ - out_fdc(fdcu, 0xff); /* transfer size */ - awr_state = 2; - break; - - case 2: /* DMA completed */ - /* Transfer complete, get status */ - for (i = 0; i < 7; i++) rddta[i] = in_fdc(fdcu); - isa_dmadone(B_WRITE, ft->xptr, QCV_BLKSIZE, 2); - -#if FTDBGALL - /* Compute where the controller thinks we are */ - where = (rddta[3]*ftg->g_fdtrk) + (rddta[4]*ftg->g_fdside) + rddta[5]-1; - DPRT(("xfer done: st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d want:%d\n", - rddta[0], rddta[1], rddta[2], rddta[3], rddta[4], rddta[5], - where, ft->xblk)); -#endif - - /* Check for errors */ - if ((rddta[0] & 0xc0) != 0x00) { -#if !FTDBGALL - where = (rddta[3]*ftg->g_fdtrk) + (rddta[4]*ftg->g_fdside) - + rddta[5]-1; - DPRT(("xfer done: st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d want:%d\n", - rddta[0], rddta[1], rddta[2], rddta[3], rddta[4], rddta[5], - where, ft->xblk)); -#endif - if (retries < 3) { - /* Something happened -- try again */ - DPRT(("async_write: doing retry %d\n", retries)); - ft->lastpos = ft->xblk; - awr_state = 0; - retries++; - goto restate; - } else { - /* - * Retries failed. Note the unrecoverable error. - * Marking the block as bad is useless right now. - */ - printf("ft%d: unrecoverable write error on block %d\n", - ftu, ft->xblk); - ft->segh->reqcrc |= (1 << ft->xcnt); - } - } - - /* Otherwise, transfer completed okay. */ - retries = 0; - ft->lastpos = ft->xblk; - ft->xblk++; - ft->xcnt++; - ft->xptr += QCV_BLKSIZE; - if (ft->xcnt < QCV_BLKSEG) { - awr_state = 0; /* next block */ - goto restate; - } -#if FTDBGALL - DPRT(("Write done.\n")); -#endif - ft->io_sts = FTIO_READY; - break; - - case 3: - ft->moving = 1; - ACMD_FUNC(4, ACMD_SEEK, QC_FORWARD, 0, 0); - break; - - case 4: - awr_state = 1; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ - break; - - default: - DPRT(("ft%d: bad async_write state %d!!\n", ftu, awr_state)); - break; - } -} - - -/* - * Interrupt handler for active tape. Bounced off of fdintr(). - */ -int -ftintr(ftu_t ftu) -{ - int st0, pcn, i; - ft_p ft = ft_data[ftu]; - fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ - int s = splbio(); - - st0 = 0; - pcn = 0; - - /* I/O segment transfer completed */ - if (ft->active) { - if (async_func != ACMD_NONE) { - async_cmd(ftu); - splx(s); - return(1); - } -#if FTDBGALL - DPRT(("Got request interrupt\n")); -#endif - async_req(ftu, 0); - splx(s); - return(1); - } - - /* Get interrupt status */ - if (ft->cmd_wait != FTCMD_READID) { - out_fdc(fdcu, NE7CMD_SENSEI); - st0 = in_fdc(fdcu); - pcn = in_fdc(fdcu); - } - - if (ft->cmd_wait == FTCMD_NONE || ft->sts_wait != FTSTS_SNOOZE) { -huh_what: - printf("ft%d: unexpected interrupt; st0 = $%02x pcn = %d\n", - ftu, st0, pcn); - splx(s); - return(1); - } - - switch (ft->cmd_wait) { - case FTCMD_RESET: - ft->sts_wait = FTSTS_INTERRUPT; - wakeup((caddr_t)wc_intr_wait); - break; - case FTCMD_RECAL: - case FTCMD_SEEK: - if (st0 & 0x20) { /* seek done */ - ft->sts_wait = FTSTS_INTERRUPT; - ft->pcn = pcn; - wakeup((caddr_t)wc_intr_wait); - } -#if FTDBGALL - else - DPRT(("ft%d: seek error st0 = $%02x pcn = %d\n", - ftu, st0, pcn)); -#endif - break; - case FTCMD_READID: - for (i = 0; i < 7; i++) ft->rid[i] = in_fdc(fdcu); - ft->sts_wait = FTSTS_INTERRUPT; - wakeup((caddr_t)wc_intr_wait); - break; - - default: - goto huh_what; - } - - splx(s); - return(1); -} - - -/* - * Interrupt timeout routine. - */ -static void -ft_timeout(void *arg1) -{ - int s; - ftu_t ftu = (ftu_t)arg1; - ft_p ft = ft_data[ftu]; - - s = splbio(); - if (ft->active) { - if (async_func != ACMD_NONE) { - async_cmd(ftu); - splx(s); - return; - } - async_req(ftu, 1); - } else { - ft->sts_wait = FTSTS_TIMEOUT; - wakeup((caddr_t)wc_intr_wait); - } - splx(s); -} - - -/* - * Wait for a particular interrupt to occur. ftintr() will wake us up - * if it sees what we want. Otherwise, time out and return error. - * Should always disable ints before trigger is sent and calling here. - */ -static int -ftintr_wait(ftu_t ftu, int cmd, int ticks) -{ - int retries, st0, pcn; - ft_p ft = ft_data[ftu]; - fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ - - ft->cmd_wait = cmd; - ft->sts_wait = FTSTS_SNOOZE; - - /* At attach time, we can't rely on having interrupts serviced */ - if (ft->attaching) { - switch (cmd) { - case FTCMD_RESET: - DELAY(100); - ft->sts_wait = FTSTS_INTERRUPT; - goto intrdone; - case FTCMD_RECAL: - case FTCMD_SEEK: - for (retries = 0; retries < 10000; retries++) { - DELAY(150); - out_fdc(fdcu, NE7CMD_SENSEI); - st0 = in_fdc(fdcu); - if ((st0 & 0xc0) == 0x80) continue; - pcn = in_fdc(fdcu); - if (st0 & 0x20) { - ft->sts_wait = FTSTS_INTERRUPT; - ft->pcn = pcn; - goto intrdone; - } - } - break; - } - ft->sts_wait = FTSTS_TIMEOUT; - goto intrdone; - } - - ftsleep(wc_intr_wait, ticks); - -intrdone: - if (ft->sts_wait == FTSTS_TIMEOUT) { /* timeout */ -#if FTDBGALL - if (ft->cmd_wait != FTCMD_RESET) - DPRT(("ft%d: timeout on command %d\n", ftu, ft->cmd_wait)); -#endif - ft->cmd_wait = FTCMD_NONE; - ft->sts_wait = FTSTS_NONE; - return(1); - } - - /* got interrupt */ - if (ft->attaching == 0 && ticks) - untimeout(ft_timeout, (caddr_t)ftu, ft->tohandle); - ft->cmd_wait = FTCMD_NONE; - ft->sts_wait = FTSTS_NONE; - return(0); -} - - -/* - * Recalibrate tape drive. Parameter totape is true, if we should - * recalibrate to tape drive settings. - */ -static int -tape_recal(ftu_t ftu, int totape) -{ - int s; - ft_p ft = ft_data[ftu]; - fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ - - DPRT(("tape_recal start\n")); - -#ifdef PC98 - outb(0xbe, FDP_FDDEXC | FDP_PORTEXC); -#endif - out_fdc(fdcu, NE7CMD_SPECIFY); -#ifdef PC98 - out_fdc(fdcu, (totape) ? 0xEF : 0xCF); - out_fdc(fdcu, 0x02); -#else - out_fdc(fdcu, (totape) ? 0xAD : 0xDF); - out_fdc(fdcu, 0x02); -#endif - - s = splbio(); - out_fdc(fdcu, NE7CMD_RECAL); - out_fdc(fdcu, ftu); - - if (ftintr_wait(ftu, FTCMD_RECAL, hz)) { - splx(s); - DPRT(("ft%d: recalibrate timeout\n", ftu)); - return(1); - } - splx(s); - - out_fdc(fdcu, NE7CMD_SPECIFY); -#ifdef PC98 - out_fdc(fdcu, (totape) ? 0xEF : 0xCF); - out_fdc(fdcu, 0x02); -#else - out_fdc(fdcu, (totape) ? 0xFD : 0xDF); - out_fdc(fdcu, 0x02); -#endif - - DPRT(("tape_recal end\n")); - return(0); -} - -/* - * Wait for a particular tape status to be met. If all is TRUE, then - * all states must be met, otherwise any state can be met. - */ -static int -tape_state(ftu_t ftu, int all, int mask, int seconds) -{ - int r, tries, maxtries; - - maxtries = (seconds) ? (4 * seconds) : 1; - for (tries = 0; tries < maxtries; tries++) { - r = tape_status(ftu); - if (r >= 0) { - if (all && (r & mask) == mask) return(r); - if ((r & mask) != 0) return(r); - } - if (seconds) ftsleep(wc_long_delay, hz/4); - } - DPRT(("ft%d: tape_state failed on mask=$%02x maxtries=%d\n", - ftu, mask, maxtries)); - return(-1); -} - - -/* - * Send a QIC command to tape drive, wait for completion. - */ -static int -tape_cmd(ftu_t ftu, int cmd) -{ - int newcn; - int retries = 0; - int s; - ft_p ft = ft_data[ftu]; - fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ - - DPRT(("===> tape_cmd: %d\n",cmd)); - newcn = (cmd <= ft->pcn) ? ft->pcn - cmd : ft->pcn + cmd; - -retry: - - /* Perform seek */ - s = splbio(); - out_fdc(fdcu, NE7CMD_SEEK); - out_fdc(fdcu, ftu); - out_fdc(fdcu, newcn); - - if (ftintr_wait(ftu, FTCMD_SEEK, hz)) { - DPRT(("ft%d: tape_cmd seek timeout\n", ftu)); -redo: - splx(s); - if (++retries < 5) goto retry; - DPRT(("ft%d: tape_cmd seek failed!\n", ftu)); - return(1); - } - splx(s); - - if (ft->pcn != newcn) { - DPRT(("ft%d: bad seek in tape_cmd; pcn = %d newcn = %d\n", - ftu, ft->pcn, newcn)); - goto redo; - } - DELAY(2500); - return(0); -} - - -/* - * Return status of tape drive - */ -static int -tape_status(ftu_t ftu) -{ - int r, err, tries; - ft_p ft = ft_data[ftu]; - int max = (ft->attaching) ? 2 : 3; - - for (r = -1, tries = 0; r < 0 && tries < max; tries++) - r = qic_status(ftu, QC_STATUS, 8); - if (tries == max) return(-1); - -recheck: - DPRT(("tape_status got $%04x\n",r)); - ft->laststs = r; - - if (r & (QS_ERROR|QS_NEWCART)) { - err = qic_status(ftu, QC_ERRCODE, 16); - ft->lasterr = err; - if (r & QS_NEWCART) { - ft->newcart = 1; - /* If tape not referenced, do a seek load point. */ - if ((r & QS_FMTOK) == 0 && !ft->attaching) { - tape_cmd(ftu, QC_SEEKLP); - do { - ftsleep(wc_long_delay, hz); - } while ((r = qic_status(ftu, QC_STATUS, 8)) < 0 || - (r & (QS_READY|QS_CART)) == QS_CART); - goto recheck; - } - } else if (err && !ft->attaching) { - DPRT(("ft%d: QIC error %d occurred on cmd %d\n", - ftu, err & 0xff, err >> 8)); - } - r = qic_status(ftu, QC_STATUS, 8); - ft->laststs = r; - DPRT(("tape_status got error code $%04x new sts = $%02x\n",err,r)); - } - - ft->rdonly = (r & QS_RDONLY); - return(r); -} - - -/* - * Transfer control to tape drive. - */ -static void -tape_start(ftu_t ftu, int motor) -{ - ft_p ft = ft_data[ftu]; - fdc_p fdc = ft->fdc; - int s, mbits; -#ifndef PC98 - static int mbmotor[] = { FDO_MOEN0, FDO_MOEN1, FDO_MOEN2, FDO_MOEN3 }; -#endif - - s = splbio(); - DPRT(("tape_start start\n")); - - /* reset, dma disable */ -#ifdef PC98 - outb(fdc->baseport+FDOUT, FDO_RST | FDO_FRY | FDO_AIE | FDO_MTON); -#else - outb(fdc->baseport+FDOUT, 0x00); -#endif - (void)ftintr_wait(ftu, FTCMD_RESET, hz/10); - - /* raise reset, enable DMA, motor on if needed */ -#ifdef PC98 - outb(fdc->baseport+FDOUT, FDO_DMAE | FDO_MTON); -#else - mbits = ftu & 3; - if (motor && ftu < 4) - mbits |= mbmotor[ftu]; - - outb(fdc->baseport+FDOUT, FDO_FRST | FDO_FDMAEN | mbits); -#endif - (void)ftintr_wait(ftu, FTCMD_RESET, hz/10); - - splx(s); - - tape_recal(ftu, 1); - - /* set transfer speed */ -#ifndef PC98 - outb(fdc->baseport+FDCTL, FDC_500KBPS); - DELAY(10); -#endif - - DPRT(("tape_start end\n")); -} - - -/* - * Transfer control back to floppy disks. - */ -static void -tape_end(ftu_t ftu) -{ - ft_p ft = ft_data[ftu]; - fdc_p fdc = ft->fdc; - int s; - - DPRT(("tape_end start\n")); - tape_recal(ftu, 0); - - s = splbio(); - - /* reset, dma disable */ -#ifdef PC98 - outb(fdc->baseport+FDOUT, FDO_RST | FDO_FRY | FDO_AIE | FDO_MTON); -#else - outb(fdc->baseport+FDOUT, 0x00); -#endif - (void)ftintr_wait(ftu, FTCMD_RESET, hz/10); - - /* raise reset, enable DMA */ -#ifdef PC98 - outb(fdc->baseport+FDOUT, FDO_DMAE | FDO_MTON); -#else - outb(fdc->baseport+FDOUT, FDO_FRST | FDO_FDMAEN); -#endif - (void)ftintr_wait(ftu, FTCMD_RESET, hz/10); - - splx(s); - - /* set transfer speed */ -#ifndef PC98 - outb(fdc->baseport+FDCTL, FDC_500KBPS); - DELAY(10); -#endif - fdc->flags &= ~FDC_TAPE_BUSY; - - DPRT(("tape_end end\n")); -} - - -/* - * Wait for the driver to go inactive, cancel readahead if necessary. - */ -static void -tape_inactive(ftu_t ftu) -{ - ft_p ft = ft_data[ftu]; - int s = splbio(); - - if (ft->segh != NULL) { - if (ft->segh->reqtype == FTIO_RDAHEAD) { - /* cancel read-ahead */ - ft->segh->reqcan = 1; - } else if (ft->segh->reqtype == FTIO_WRITING && !ft->active) { - /* flush out any remaining writes */ - DPRT(("Flushing write I/O chain\n")); - arq_state = ard_state = awr_state = 0; - ft->xblk = ft->segh->reqblk; - ft->xseg = ft->segh->reqseg; - ft->xcnt = 0; - ft->xptr = ft->segh->buff; - ft->active = 1; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, 1); - } - } - while (ft->active) ftsleep(wc_iosts_change, 0); - splx(s); -} - - -/* - * Get the geometry of the tape currently in the drive. - */ -static int -ftgetgeom(ftu_t ftu) -{ - int r, i, tries; - int cfg, qic80, ext; - int sts, fmt, len; - ft_p ft = ft_data[ftu]; - - r = tape_status(ftu); - - /* XXX fix me when format mode is finished */ - if (r < 0 || (r & QS_CART) == 0 || (r & QS_FMTOK) == 0) { - DPRT(("ftgetgeom: no cart or not formatted 0x%04x\n",r)); - ftg = NULL; - ft->newcart = 1; - return(0); - } - - /* Report drive configuration */ - for (cfg = -1, tries = 0; cfg < 0 && tries < 3; tries++) - cfg = qic_status(ftu, QC_CONFIG, 8); - if (tries == 3) { - DPRT(("ftgetgeom report config failed\n")); - ftg = NULL; - return(-1); - } - DPRT(("ftgetgeom report config got $%04x\n", cfg)); - ft->lastcfg = cfg; - - qic80 = cfg & QCF_QIC80; - ext = cfg & QCF_EXTRA; - -/* - * XXX - This doesn't seem to work on my Colorado Jumbo 250... - * if it works on your drive, I'd sure like to hear about it. - */ -#if 0 - /* Report drive status */ - for (sts = -1, tries = 0; sts < 0 && tries < 3; tries++) - sts = qic_status(ftu, QC_TSTATUS, 8); - if (tries == 3) { - DPRT(("ftgetgeom report tape status failed\n")); - ftg = NULL; - return(-1); - } - DPRT(("ftgetgeom report tape status got $%04x\n", sts)); -#else - /* - * XXX - Forge a fake tape status based upon the returned - * configuration, since the above command or code is broken - * for my drive and probably other older drives. - */ - sts = 0; - sts = (qic80) ? QTS_QIC80 : QTS_QIC40; - sts |= (ext) ? QTS_LEN2 : QTS_LEN1; -#endif - - fmt = sts & QTS_FMMASK; - len = (sts & QTS_LNMASK) >> 4; - - if (fmt > QCV_NFMT) { - ftg = NULL; - printf("ft%d: unsupported tape format\n", ftu); - return(-1); - } - if (len > QCV_NLEN) { - ftg = NULL; - printf("ft%d: unsupported tape length\n", ftu); - return(-1); - } - - /* Look up geometry in the table */ - for (i = 1; i < NGEOM; i++) - if (ftgtbl[i].g_fmtno == fmt && ftgtbl[i].g_lenno == len) break; - if (i == NGEOM) { - printf("ft%d: unknown tape geometry\n", ftu); - ftg = NULL; - return(-1); - } - ftg = &ftgtbl[i]; - if (!ftg->g_trktape) { - printf("ft%d: unsupported format %s w/len %s\n", - ftu, ftg->g_fmtdesc, ftg->g_lendesc); - ftg = NULL; - return(-1); - } - DPRT(("Tape format is %s, length is %s\n", ftg->g_fmtdesc, ftg->g_lendesc)); - ft->newcart = 0; - return(0); -} - - -/* - * Switch between tape/floppy. This will send the tape enable/disable - * codes for this drive's manufacturer. - */ -static int -set_fdcmode(dev_t dev, int newmode) -{ - ftu_t ftu = FDUNIT(minor(dev)); - ft_p ft = ft_data[ftu]; - fdc_p fdc = ft->fdc; - static int havebufs = 0; - int i; - SegReq *sp, *rsp; - - if (newmode == FDC_TAPE_MODE) { - /* Wake up the tape drive */ - switch (ft->type) { - case NO_TYPE: - fdc->flags &= ~FDC_TAPE_BUSY; - return(ENXIO); - case FT_NONE: - tape_start(ftu, 0); - break; - case FT_COLORADO: - tape_start(ftu, 0); - if (tape_cmd(ftu, QC_COL_ENABLE1)) { - tape_end(ftu); - return(EIO); - } - if (tape_cmd(ftu, QC_COL_ENABLE2 + ftu)) { - tape_end(ftu); - return(EIO); - } - break; - case FT_MOUNTAIN: - tape_start(ftu, 0); - if (tape_cmd(ftu, QC_MTN_ENABLE1)) { - tape_end(ftu); - return(EIO); - } - if (tape_cmd(ftu, QC_MTN_ENABLE2)) { - tape_end(ftu); - return(EIO); - } - break; - case FT_INSIGHT: - tape_start(ftu, 1); - break; - default: - DPRT(("ft%d: bad tape type\n", ftu)); - return(ENXIO); - } - if (tape_status(ftu) < 0) { - if (ft->type == FT_COLORADO) - tape_cmd(ftu, QC_COL_DISABLE); - else if (ft->type == FT_MOUNTAIN) - tape_cmd(ftu, QC_MTN_DISABLE); - tape_end(ftu); - return(EIO); - } - - /* Grab buffers from memory. */ - if (!havebufs) { - ft->segh = ft->segt = NULL; - ft->doneh = ft->donet = NULL; - ft->segfree = NULL; - ft->hdr = NULL; - ft->nsegq = ft->ndoneq = ft->nfreelist = 0; - for (i = 0; i < FTNBUFF; i++) { - sp = malloc(sizeof(SegReq), M_DEVBUF, M_WAITOK); - if (sp == NULL) { - printf("ft%d: not enough memory for buffers\n", ftu); - for (sp=ft->segfree; sp != NULL; sp=sp->next) - free(sp, M_DEVBUF); - if (ft->type == FT_COLORADO) - tape_cmd(ftu, QC_COL_DISABLE); - else if (ft->type == FT_MOUNTAIN) - tape_cmd(ftu, QC_MTN_DISABLE); - tape_end(ftu); - return(ENOMEM); - } - sp->reqtype = FTIO_READY; - sp->next = ft->segfree; - ft->segfree = sp; - ft->nfreelist++; - } - /* take one buffer for header */ - ft->hdr = ft->segfree; - ft->segfree = ft->segfree->next; - ft->nfreelist--; - havebufs = 1; - } - ft->io_sts = FTIO_READY; /* tape drive is ready */ - ft->active = 0; /* interrupt driver not active */ - ft->moving = 0; /* tape not moving */ - ft->rdonly = 0; /* tape read only */ - ft->newcart = 0; /* new cartridge flag */ - ft->lastpos = -1; /* tape is rewound */ - async_func = ACMD_NONE; /* No async function */ - tape_state(ftu, 0, QS_READY, 60); - tape_cmd(ftu, QC_RATE); - tape_cmd(ftu, QCF_RT500+2); /* 500K bps */ - tape_state(ftu, 0, QS_READY, 60); - ft->mode = FTM_PRIMARY; - tape_cmd(ftu, QC_PRIMARY); /* Make sure we're in primary mode */ - tape_state(ftu, 0, QS_READY, 60); - ftg = NULL; /* No geometry yet */ - ftgetgeom(ftu); /* Get tape geometry */ - ftreq_rewind(ftu); /* Make sure tape is rewound */ - } else { - if (ft->type == FT_COLORADO) - tape_cmd(ftu, QC_COL_DISABLE); - else if (ft->type == FT_MOUNTAIN) - tape_cmd(ftu, QC_MTN_DISABLE); - tape_end(ftu); - ft->newcart = 0; /* clear new cartridge */ - if (ft->hdr != NULL) free(ft->hdr, M_DEVBUF); - if (havebufs) { - for (sp = ft->segfree; sp != NULL;) { - rsp = sp; sp = sp->next; - free(rsp, M_DEVBUF); - } - for (sp = ft->segh; sp != NULL;) { - rsp = sp; sp = sp->next; - free(rsp, M_DEVBUF); - } - for (sp = ft->doneh; sp != NULL;) { - rsp = sp; sp = sp->next; - free(rsp, M_DEVBUF); - } - } - havebufs = 0; - } - return(0); -} - - -/* - * Perform a QIC status function. - */ -static int -qic_status(ftu_t ftu, int cmd, int nbits) -{ - int st3, r, i; - ft_p ft = ft_data[ftu]; - fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ - - if (tape_cmd(ftu, cmd)) { - DPRT(("ft%d: QIC status timeout\n", ftu)); - return(-1); - } - - /* Sense drive status */ - out_fdc(fdcu, NE7CMD_SENSED); - out_fdc(fdcu, ftu); - st3 = in_fdc(fdcu); - - if ((st3 & 0x10) == 0) { /* track 0 */ - DPRT(("qic_status has dead drive... st3 = $%02x\n", st3)); - return(-1); - } - - for (i = r = 0; i <= nbits; i++) { - if (tape_cmd(ftu, QC_NEXTBIT)) { - DPRT(("ft%d: QIC status bit timed out on %d\n", ftu, i)); - return(-1); - } - - out_fdc(fdcu, NE7CMD_SENSED); - out_fdc(fdcu, ftu); - st3 = in_fdc(fdcu); - if (st3 < 0) { - DPRT(("ft%d: controller timed out on bit %d r=$%02x\n", - ftu, i, r)); - return(-1); - } - - r >>= 1; - if (i < nbits) - r |= ((st3 & 0x10) ? 1 : 0) << nbits; - else if ((st3 & 0x10) == 0) { - DPRT(("ft%d: qic status stop bit missing at %d, st3=$%02x r=$%04x\n", - ftu,i,st3,r)); - return(-1); - } - } - - DPRT(("qic_status returned $%02x\n", r)); - return(r); -} - - -/* - * Open tape drive for use. Bounced off of Fdopen if tape minor is - * detected. - */ -int -ftopen(dev_t dev, int arg2) { - ftu_t ftu = FDUNIT(minor(dev)); - fdc_p fdc; - - /* check bounds */ - if (ftu >= NFT) - return(ENXIO); - if (!ft_data[ftu]) - return(ENXIO); - fdc = ft_data[ftu]->fdc; - if ((fdc == NULL) || (ft_data[ftu]->type == NO_TYPE)) - return(ENXIO); - /* check for controller already busy with tape */ - if (fdc->flags & FDC_TAPE_BUSY) - return(EBUSY); - /* make sure we found a tape when probed */ - if (!(fdc->flags & FDC_HASFTAPE)) - return(ENODEV); - fdc->fdu = ftu; - fdc->flags |= FDC_TAPE_BUSY; - return(set_fdcmode(dev, FDC_TAPE_MODE)); /* try to switch to tape */ -} - - -/* - * Close tape and return floppy controller to disk mode. - */ -int -ftclose(dev_t dev, int flags) -{ - ftu_t ftu = FDUNIT(minor(dev)); - ft_p ft = ft_data[ftu]; - - - /* Wait for any remaining I/O activity to complete. */ - tape_inactive(ftu); - - ft->mode = FTM_PRIMARY; - tape_cmd(ftu, QC_PRIMARY); - tape_state(ftu, 0, QS_READY, 60); - ftreq_rewind(ftu); - return(set_fdcmode(dev, FDC_DISK_MODE)); /* Otherwise, close tape */ -} - -/* - * Read or write a segment. - */ -static int -ftreq_rw(ftu_t ftu, unsigned long cmd, QIC_Segment *sr, struct proc *p) -{ - int r, i; - SegReq *sp; - int s; - long blk, bad, seg; - unsigned char *cp, *cp2; - ft_p ft = ft_data[ftu]; - - if (!ft->active && ft->segh == NULL) { - r = tape_status(ftu); - if ((r & QS_CART) == 0) - return(ENXIO); /* No cartridge */ - if ((r & QS_FMTOK) == 0) - return(ENXIO); /* Not formatted */ - tape_state(ftu, 0, QS_READY, 90); - } - - if (ftg == NULL || ft->newcart) { - tape_inactive(ftu); - tape_state(ftu, 0, QS_READY, 90); - if (ftgetgeom(ftu) < 0) - return(ENXIO); - } - - /* Write not allowed on a read-only tape. */ - if (cmd == QIOWRITE && ft->rdonly) - return(EROFS); - - /* Quick check of request and buffer. */ - if (sr == NULL || sr->sg_data == NULL) - return(EINVAL); - - /* Make sure requested track and segment is in range. */ - if (sr->sg_trk >= ftg->g_trktape || sr->sg_seg >= ftg->g_segtrk) - return(EINVAL); - - blk = sr->sg_trk * ftg->g_blktrk + sr->sg_seg * QCV_BLKSEG; - seg = sr->sg_trk * ftg->g_segtrk + sr->sg_seg; - - s = splbio(); - if (cmd == QIOREAD) { - /* - * See if the driver is reading ahead. - */ - if (ft->doneh != NULL || - (ft->segh != NULL && ft->segh->reqtype == FTIO_RDAHEAD)) { - /* - * Eat the completion queue and see if the request - * is already there. - */ - while (ft->doneh != NULL) { - if (blk == ft->doneh->reqblk) { - sp = ft->doneh; - sp->reqtype = FTIO_READING; - sp->reqbad = sr->sg_badmap; - goto rddone; - } - segio_free(ft, ft->doneh); - } - - /* - * Not on the completed queue, in progress maybe? - */ - if (ft->segh != NULL && ft->segh->reqtype == FTIO_RDAHEAD && - blk == ft->segh->reqblk) { - sp = ft->segh; - sp->reqtype = FTIO_READING; - sp->reqbad = sr->sg_badmap; - goto rdwait; - } - } - - /* Wait until we're ready. */ - tape_inactive(ftu); - - /* Set up a new read request. */ - sp = segio_alloc(ft); - sp->reqcrc = 0; - sp->reqbad = sr->sg_badmap; - sp->reqblk = blk; - sp->reqseg = seg; - sp->reqcan = 0; - sp->reqtype = FTIO_READING; - segio_queue(ft, sp); - - /* Start the read request off. */ - DPRT(("Starting read I/O chain\n")); - arq_state = ard_state = awr_state = 0; - ft->xblk = sp->reqblk; - ft->xseg = sp->reqseg; - ft->xcnt = 0; - ft->xptr = sp->buff; - ft->active = 1; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, 1); - -rdwait: - ftsleep(wc_buff_done, 0); - -rddone: - bad = sp->reqbad; - sr->sg_crcmap = sp->reqcrc & ~bad; - - /* Copy out segment and discard bad mapped blocks. */ - cp = sp->buff; cp2 = sr->sg_data; - for (i = 0; i < QCV_BLKSEG; cp += QCV_BLKSIZE, i++) { - if (bad & (1 << i)) continue; - copyout(cp, cp2, QCV_BLKSIZE); - cp2 += QCV_BLKSIZE; - } - segio_free(ft, sp); - } else { - if (ft->segh != NULL && ft->segh->reqtype != FTIO_WRITING) - tape_inactive(ftu); - - /* Allocate a buffer and start tape if we're running low. */ - sp = segio_alloc(ft); - if (!ft->active && (sp == NULL || ft->nfreelist <= 1)) { - DPRT(("Starting write I/O chain\n")); - arq_state = ard_state = awr_state = 0; - ft->xblk = ft->segh->reqblk; - ft->xseg = ft->segh->reqseg; - ft->xcnt = 0; - ft->xptr = ft->segh->buff; - ft->active = 1; - ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, 1); - } - - /* Sleep until a buffer becomes available. */ - while (sp == NULL) { - ftsleep(wc_buff_avail, 0); - sp = segio_alloc(ft); - } - - /* Copy in segment and expand bad blocks. */ - bad = sr->sg_badmap; - cp = sr->sg_data; cp2 = sp->buff; - for (i = 0; i < QCV_BLKSEG; cp2 += QCV_BLKSIZE, i++) { - if (bad & (1 << i)) continue; - copyin(cp, cp2, QCV_BLKSIZE); - cp += QCV_BLKSIZE; - } - sp->reqblk = blk; - sp->reqseg = seg; - sp->reqcan = 0; - sp->reqtype = FTIO_WRITING; - segio_queue(ft, sp); - } - splx(s); - return(0); -} - - -/* - * Rewind to beginning of tape - */ -static int -ftreq_rewind(ftu_t ftu) -{ - ft_p ft = ft_data[ftu]; - - tape_inactive(ftu); - tape_cmd(ftu, QC_STOP); - tape_state(ftu, 0, QS_READY, 90); - tape_cmd(ftu, QC_SEEKSTART); - tape_state(ftu, 0, QS_READY, 90); - tape_cmd(ftu, QC_SEEKTRACK); - tape_cmd(ftu, 2); - tape_state(ftu, 0, QS_READY, 90); - ft->lastpos = -1; - ft->moving = 0; - return(0); -} - - -/* - * Move to logical beginning or end of track - */ -static int -ftreq_trkpos(ftu_t ftu, int req) -{ - int curtrk, r, cmd; - ft_p ft = ft_data[ftu]; - - tape_inactive(ftu); - tape_cmd(ftu, QC_STOP); - tape_state(ftu, 0, QS_READY, 90); - - r = tape_status(ftu); - if ((r & QS_CART) == 0) return(ENXIO); /* No cartridge */ - if ((r & QS_FMTOK) == 0) return(ENXIO); /* Not formatted */ - - if (ftg == NULL || ft->newcart) { - if (ftgetgeom(ftu) < 0) return(ENXIO); - } - - curtrk = (ft->lastpos < 0) ? 0 : ft->lastpos / ftg->g_blktrk; - if (req == QIOBOT) - cmd = (curtrk & 1) ? QC_SEEKEND : QC_SEEKSTART; - else - cmd = (curtrk & 1) ? QC_SEEKSTART : QC_SEEKEND; - tape_cmd(ftu, cmd); - tape_state(ftu, 0, QS_READY, 90); - return(0); -} - - -/* - * Seek tape head to a particular track. - */ -static int -ftreq_trkset(ftu_t ftu, int *trk) -{ - int r; - ft_p ft = ft_data[ftu]; - - tape_inactive(ftu); - tape_cmd(ftu, QC_STOP); - tape_state(ftu, 0, QS_READY, 90); - - r = tape_status(ftu); - if ((r & QS_CART) == 0) return(ENXIO); /* No cartridge */ - if ((r & QS_FMTOK) == 0) return(ENXIO); /* Not formatted */ - if (ftg == NULL || ft->newcart) { - if (ftgetgeom(ftu) < 0) return(ENXIO); - } - - tape_cmd(ftu, QC_SEEKTRACK); - tape_cmd(ftu, *trk + 2); - tape_state(ftu, 0, QS_READY, 90); - return(0); -} - - -/* - * Start tape moving forward. - */ -static int -ftreq_lfwd(ftu_t ftu) -{ - ft_p ft = ft_data[ftu]; - - tape_inactive(ftu); - tape_cmd(ftu, QC_STOP); - tape_state(ftu, 0, QS_READY, 90); - tape_cmd(ftu, QC_FORWARD); - ft->moving = 1; - return(0); -} - - -/* - * Stop the tape - */ -static int -ftreq_stop(ftu_t ftu) -{ - ft_p ft = ft_data[ftu]; - - tape_inactive(ftu); - tape_cmd(ftu, QC_STOP); - tape_state(ftu, 0, QS_READY, 90); - ft->moving = 0; - return(0); -} - - -/* - * Set the particular mode the drive should be in. - */ -static int -ftreq_setmode(ftu_t ftu, int cmd) -{ - int r; - ft_p ft = ft_data[ftu]; - - tape_inactive(ftu); - r = tape_status(ftu); - - switch(cmd) { - case QIOPRIMARY: - ft->mode = FTM_PRIMARY; - tape_cmd(ftu, QC_PRIMARY); - break; - case QIOFORMAT: - if (r & QS_RDONLY) return(ENXIO); - if ((r & QS_BOT) == 0) return(ENXIO); - tape_cmd(ftu, QC_FORMAT); - break; - case QIOVERIFY: - if ((r & QS_FMTOK) == 0) return(ENXIO); /* Not formatted */ - tape_cmd(ftu, QC_VERIFY); - break; - } - tape_state(ftu, 0, QS_READY, 60); - return(0); -} - - -/* - * Return drive status bits - */ -static int -ftreq_status(ftu_t ftu, unsigned long cmd, int *sts, struct proc *p) -{ - ft_p ft = ft_data[ftu]; - - if (ft->active) - *sts = ft->laststs & ~QS_READY; - else - *sts = tape_status(ftu); - return(0); -} - - -/* - * Return drive configuration bits - */ -static int -ftreq_config(ftu_t ftu, unsigned long cmd, int *cfg, struct proc *p) -{ - int r, tries; - ft_p ft = ft_data[ftu]; - - if (ft->active) - r = ft->lastcfg; - else { - for (r = -1, tries = 0; r < 0 && tries < 3; tries++) - r = qic_status(ftu, QC_CONFIG, 8); - if (tries == 3) return(ENXIO); - } - *cfg = r; - return(0); -} - - -/* - * Return current tape's geometry. - */ -static int -ftreq_geom(ftu_t ftu, QIC_Geom *g) -{ - tape_inactive(ftu); - if (ftg == NULL && ftgetgeom(ftu) < 0) return(ENXIO); - bcopy(ftg, g, sizeof(QIC_Geom)); - return(0); -} - - -/* - * Return drive hardware information - */ -static int -ftreq_hwinfo(ftu_t ftu, QIC_HWInfo *hwp) -{ - int tries; - int rom, vend; - - tape_inactive(ftu); - bzero(hwp, sizeof(QIC_HWInfo)); - - for (rom = -1, tries = 0; rom < 0 && tries < 3; tries++) - rom = qic_status(ftu, QC_VERSION, 8); - if (rom > 0) { - hwp->hw_rombeta = (rom >> 7) & 0x01; - hwp->hw_romid = rom & 0x7f; - } - - for (vend = -1, tries = 0; vend < 0 && tries < 3; tries++) - vend = qic_status(ftu, QC_VENDORID, 16); - if (vend > 0) { - hwp->hw_make = (vend >> 6) & 0x3ff; - hwp->hw_model = vend & 0x3f; - } - - return(0); -} - - -/* - * Receive or Send the in-core header segment. - */ -static int -ftreq_hdr(ftu_t ftu, unsigned long cmd, QIC_Segment *sp) -{ - ft_p ft = ft_data[ftu]; - QIC_Header *h = (QIC_Header *)ft->hdr->buff; - - if (sp == NULL || sp->sg_data == NULL) return(EINVAL); - if (cmd == QIOSENDHDR) { - copyin(sp->sg_data, ft->hdr->buff, QCV_SEGSIZE); - } else { - if (h->qh_sig != QCV_HDRMAGIC) return(EIO); - copyout(ft->hdr->buff, sp->sg_data, QCV_SEGSIZE); - } - return(0); -} - -/* - * I/O functions. - */ -int -ftioctl(dev_t dev, unsigned long cmd, caddr_t data, int flag, struct proc *p) -{ - ftu_t ftu = FDUNIT(minor(dev)); - - switch(cmd) { - case QIOREAD: /* Request reading a segment from tape. */ - case QIOWRITE: /* Request writing a segment to tape. */ - return(ftreq_rw(ftu, cmd, (QIC_Segment *)data, p)); - - case QIOREWIND: /* Rewind tape. */ - return(ftreq_rewind(ftu)); - - case QIOBOT: /* Seek to logical beginning of track. */ - case QIOEOT: /* Seek to logical end of track. */ - return(ftreq_trkpos(ftu, cmd)); - - case QIOTRACK: /* Seek tape head to specified track. */ - return(ftreq_trkset(ftu, (int *)data)); - - case QIOSEEKLP: /* Seek load point. */ - goto badreq; - - case QIOFORWARD: /* Move tape in logical forward direction. */ - return(ftreq_lfwd(ftu)); - - case QIOSTOP: /* Causes tape to stop. */ - return(ftreq_stop(ftu)); - - case QIOPRIMARY: /* Enter primary mode. */ - case QIOFORMAT: /* Enter format mode. */ - case QIOVERIFY: /* Enter verify mode. */ - return(ftreq_setmode(ftu, cmd)); - - case QIOWRREF: /* Write reference burst. */ - goto badreq; - - case QIOSTATUS: /* Get drive status. */ - return(ftreq_status(ftu, cmd, (int *)data, p)); - - case QIOCONFIG: /* Get tape configuration. */ - return(ftreq_config(ftu, cmd, (int *)data, p)); - - case QIOGEOM: - return(ftreq_geom(ftu, (QIC_Geom *)data)); - - case QIOHWINFO: - return(ftreq_hwinfo(ftu, (QIC_HWInfo *)data)); - - case QIOSENDHDR: - case QIORECVHDR: - return(ftreq_hdr(ftu, cmd, (QIC_Segment *)data)); - } -badreq: - DPRT(("ft%d: unknown ioctl(%#lx) request\n", ftu, cmd)); - return(ENXIO); -} - -#endif diff --git a/sys/i386/isa/ftreg.h b/sys/i386/isa/ftreg.h deleted file mode 100644 index eea78ec9ea5a..000000000000 --- a/sys/i386/isa/ftreg.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 1993, 1994 Steve Gerakines - * - * This is freely redistributable software. You may do anything you - * wish with it, so long as the above notice stays intact. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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. - * - * ftreg.h - QIC-40/80 floppy tape driver header - * 06/03/94 v0.9 - * Changed seek load point to QC_SEEKLP, added reqseg to SegReq structure. - * - * 10/30/93 v0.3 - * More things will end up here. QC_VENDORID and QC_VERSION now used. - * - * 08/07/93 v0.2 release - * Things that should've been here in the first place were moved. - * Tape geometry and segment request types were added. - * - * 06/03/93 v0.1 Alpha release - * Initial revision. Many more things should be moved here. - */ - -/* QIC-117 command set. */ -#define QC_RESET 1 /* reset */ -#define QC_NEXTBIT 2 /* report next bit */ -#define QC_PAUSE 3 /* pause */ -#define QC_STPAUSE 4 /* step pause */ -#define QC_TIMEOUT 5 /* alt timeout */ -#define QC_STATUS 6 /* report status */ -#define QC_ERRCODE 7 /* report error code */ -#define QC_CONFIG 8 /* report config */ -#define QC_VERSION 9 /* report version */ -#define QC_FORWARD 10 /* logical forward */ -#define QC_SEEKSTART 11 /* seek to track start */ -#define QC_SEEKEND 12 /* seek to track end */ -#define QC_SEEKTRACK 13 /* seek head to track */ -#define QC_SEEKLP 14 /* seek load point */ -#define QC_FORMAT 15 /* format mode */ -#define QC_WRITEREF 16 /* write reference */ -#define QC_VERIFY 17 /* verify mode */ -#define QC_STOP 18 /* stop tape */ -#define QC_STEPUP 21 /* step head up */ -#define QC_STEPDOWN 22 /* step head down */ -#define QC_SEEKREV 25 /* seek reverse */ -#define QC_SEEKFWD 26 /* seek forward */ -#define QC_RATE 27 /* select data rate */ -#define QC_DIAG1 28 /* diagnostic mode 1 */ -#define QC_DIAG2 29 /* diagnostic mode 2 */ -#define QC_PRIMARY 30 /* primary mode */ -#define QC_VENDORID 32 /* vendor id */ -#define QC_TSTATUS 33 /* report tape status */ -#define QC_EXTREV 34 /* extended skip reverse */ -#define QC_EXTFWD 35 /* extended skip forward */ - -/* Colorado enable/disable. */ -#define QC_COL_ENABLE1 46 /* enable */ -#define QC_COL_ENABLE2 2 /* unit+2 */ -#define QC_COL_DISABLE 47 /* disable */ - -/* Mountain enable/disable. */ -#define QC_MTN_ENABLE1 23 /* enable 1 */ -#define QC_MTN_ENABLE2 20 /* enable 2 */ -#define QC_MTN_DISABLE 24 /* disable */ - -/* Segment I/O request. */ -typedef struct segq { - unsigned char buff[QCV_SEGSIZE];/* Segment data; first for alignment */ - int reqtype; /* Request type */ - long reqcrc; /* CRC Errors found */ - long reqbad; /* Bad sector map */ - long reqblk; /* Block request starts at */ - long reqseg; /* Segment request is at */ - int reqcan; /* Cancel read-ahead */ - struct segq *next; /* Next request */ -} SegReq; - -typedef int ftu_t; -typedef int ftsu_t; -typedef struct ft_data *ft_p; |