aboutsummaryrefslogtreecommitdiff
path: root/sys/i386
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/conf/GENERIC6
-rw-r--r--sys/i386/conf/LINT4
-rw-r--r--sys/i386/conf/NOTES4
-rw-r--r--sys/i386/conf/files.i3863
-rw-r--r--sys/i386/isa/fd.c84
-rw-r--r--sys/i386/isa/ft.c2580
-rw-r--r--sys/i386/isa/ftreg.h90
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;