summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcsapuntz <csapuntz@openbsd.org>1999-12-11 21:25:07 +0000
committercsapuntz <csapuntz@openbsd.org>1999-12-11 21:25:07 +0000
commit212751fd09da558cc0e542be8be01a117381df2a (patch)
tree1c3ee0f84f61c6b73acb24927be6dbc92c8cb9b5
parentRemove old atapi driver (diff)
downloadwireguard-openbsd-212751fd09da558cc0e542be8be01a117381df2a.tar.xz
wireguard-openbsd-212751fd09da558cc0e542be8be01a117381df2a.zip
Remove old IDE driver
-rw-r--r--sys/dev/isa/wd.c1010
-rw-r--r--sys/dev/isa/wdc.c1972
-rw-r--r--sys/dev/isa/wdlink.h160
-rw-r--r--sys/dev/isa/wdreg.h211
4 files changed, 0 insertions, 3353 deletions
diff --git a/sys/dev/isa/wd.c b/sys/dev/isa/wd.c
deleted file mode 100644
index 149a668a832..00000000000
--- a/sys/dev/isa/wd.c
+++ /dev/null
@@ -1,1010 +0,0 @@
-/* $OpenBSD: wd.c,v 1.41 1999/08/10 23:09:49 deraadt Exp $ */
-/* $NetBSD: wd.c,v 1.150 1996/05/12 23:54:03 mycroft Exp $ */
-
-/*
- * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
- *
- * DMA and multi-sector PIO handling are derived from code contributed by
- * Onno van der Linden.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Charles M. Hannum.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
- */
-
-#include "isadma.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/buf.h>
-#include <sys/uio.h>
-#include <sys/malloc.h>
-#include <sys/device.h>
-#include <sys/disklabel.h>
-#include <sys/disk.h>
-#include <sys/syslog.h>
-#include <sys/proc.h>
-
-#include <vm/vm.h>
-
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/intr.h>
-
-#include <dev/isa/isavar.h>
-#include <dev/isa/wdreg.h>
-#include <dev/isa/wdlink.h>
-
-#define WDUNIT(dev) DISKUNIT(dev)
-#define WDPART(dev) DISKPART(dev)
-#define MAKEWDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part)
-
-#define WDLABELDEV(dev) (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART))
-
-#ifdef WDDEBUG
-#define WDDEBUG_PRINT(args) printf args
-#else
-#define WDDEBUG_PRINT(args)
-#endif
-
-struct wd_softc {
- struct device sc_dev;
- struct disk sc_dk;
- struct wd_link *d_link;
- struct buf sc_q;
-};
-
-int wdprobe __P((struct device *, void *, void *));
-void wdattach __P((struct device *, struct device *, void *));
-int wdprint __P((void *, const char *));
-
-struct cfattach wd_ca = {
- sizeof(struct wd_softc), wdprobe, wdattach
-};
-
-struct cfdriver wd_cd = {
- NULL, "wd", DV_DISK
-};
-
-void wdgetdisklabel __P((dev_t, struct wd_softc *, struct disklabel *,
- struct cpu_disklabel *, int));
-int wd_get_parms __P((struct wd_softc *));
-void wdstrategy __P((struct buf *));
-
-struct dkdriver wddkdriver = { wdstrategy };
-
-/* XXX: these should go elsewhere */
-cdev_decl(wd);
-bdev_decl(wd);
-
-void wdfinish __P((struct wd_softc *, struct buf *));
-int wdsetctlr __P((struct wd_link *));
-#ifdef DKBAD
-static void bad144intern __P((struct wd_softc *));
-#endif
-int wdlock __P((struct wd_link *));
-void wdunlock __P((struct wd_link *));
-
-int
-wdprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct cfdata *cf = match;
- struct wd_link *d_link = aux;
- int drive;
-
- if (d_link == NULL)
- return 0;
- if (d_link->type != DRIVE)
- return 0;
-
- drive = d_link->sc_drive;
- if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
- return 0;
-
- return 1;
-}
-
-void
-wdattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct wd_softc *wd = (void *)self;
- struct wd_link *d_link= aux;
- int i, blank;
- char buf[41], c, *p, *q;
-
- wd->d_link = d_link;
- d_link->openings = 1;
- d_link->wd_softc = (caddr_t)wd;
-
- /*
- * Initialize and attach the disk structure.
- */
- wd->sc_dk.dk_driver = &wddkdriver;
- wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
- disk_attach(&wd->sc_dk);
-
- dk_establish(&wd->sc_dk, &wd->sc_dev);
-
- d_link->sc_lp = wd->sc_dk.dk_label;
-
- wdc_get_parms(d_link);
- for (blank = 0, p = d_link->sc_params.wdp_model, q = buf, i = 0;
- i < sizeof(d_link->sc_params.wdp_model); i++) {
- c = *p++;
- if (c == '\0')
- break;
- if (c != ' ') {
- if (blank) {
- *q++ = ' ';
- blank = 0;
- }
- *q++ = c;
- } else
- blank = 1;
- }
- *q++ = '\0';
-
- printf(": <%s>\n", buf);
- if (d_link->sc_lp->d_type != DTYPE_ST506) {
- if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
- printf("%s: %dMB, %d cyl, %d head, %d sec, %d bytes/sec, %d sec total\n",
- self->dv_xname,
- d_link->sc_params.wdp_lbacapacity / 2048,
- d_link->sc_params.wdp_cylinders,
- d_link->sc_params.wdp_heads,
- d_link->sc_params.wdp_sectors,
- DEV_BSIZE, /* XXX */
- d_link->sc_params.wdp_lbacapacity);
- } else {
- printf("%s: %dMB, %d cyl, %d head, %d sec, %d bytes/sec, %d sec total\n",
- self->dv_xname,
- d_link->sc_params.wdp_cylinders *
- (d_link->sc_params.wdp_heads *
- d_link->sc_params.wdp_sectors) / (1048576 / DEV_BSIZE),
- d_link->sc_params.wdp_cylinders,
- d_link->sc_params.wdp_heads,
- d_link->sc_params.wdp_sectors,
- DEV_BSIZE, /* XXX */
- d_link->sc_params.wdp_cylinders *
- (d_link->sc_params.wdp_heads *
- d_link->sc_params.wdp_sectors));
- }
- }
-
-#if NISADMA > 0
- if ((d_link->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
- d_link->sc_mode == WDM_DMA) {
- d_link->sc_mode = WDM_DMA;
- } else
-#endif
- if (d_link->sc_params.wdp_maxmulti > 1) {
- d_link->sc_mode = WDM_PIOMULTI;
- d_link->sc_multiple = min(d_link->sc_params.wdp_maxmulti, 16);
- } else {
- d_link->sc_mode = WDM_PIOSINGLE;
- d_link->sc_multiple = 1;
- }
-
- printf("%s: using", wd->sc_dev.dv_xname);
-#if NISADMA > 0
- if (d_link->sc_mode == WDM_DMA)
- printf(" dma transfers,");
- else
-#endif
- printf(" %d-sector %d-bit pio transfers,",
- d_link->sc_multiple,
- (d_link->sc_flags & WDF_32BIT) == 0 ? 16 : 32);
- if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
- printf(" lba addressing");
- else
- printf(" chs addressing");
- if (d_link->sc_params.wdp_bufsize > 0)
- printf(" (%dKB cache)", d_link->sc_params.wdp_bufsize / 2);
- printf("\n");
-}
-
-/*
- * Read/write routine for a buffer. Validates the arguments and schedules the
- * transfer. Does not wait for the transfer to complete.
- */
-void
-wdstrategy(bp)
- struct buf *bp;
-{
- struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)];
- struct wd_link *d_link= wd->d_link;
- int s;
-
- /* Valid request? */
- if (bp->b_blkno < 0 ||
- (bp->b_bcount % wd->sc_dk.dk_label->d_secsize) != 0 ||
- (bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
- bp->b_error = EINVAL;
- goto bad;
- }
-
- /* If device invalidated (e.g. media change, door open), error. */
- if ((d_link->sc_flags & WDF_LOADED) == 0) {
- bp->b_error = EIO;
- goto bad;
- }
-
- /* If it's a null transfer, return immediately. */
- if (bp->b_bcount == 0)
- goto done;
-
- /*
- * Do bounds checking, adjust transfer. if error, process.
- * If end of partition, just return.
- */
- if (WDPART(bp->b_dev) != RAW_PART &&
- bounds_check_with_label(bp, wd->sc_dk.dk_label,
- wd->sc_dk.dk_cpulabel,
- (d_link->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
- goto done;
-
- /* Queue transfer on drive, activate drive and controller if idle. */
- s = splbio();
- disksort(&wd->sc_q, bp);
- wdstart(wd);
- splx(s);
- return;
-
-bad:
- bp->b_flags |= B_ERROR;
-done:
- /* Toss transfer; we're done early. */
- bp->b_resid = bp->b_bcount;
- biodone(bp);
-}
-
-/*
- * Queue a drive for I/O.
- */
-void
-wdstart(vp)
- void *vp;
-{
- struct wd_softc *wd = vp;
- struct buf *dp, *bp=0;
- struct wd_link *d_link = wd->d_link;
- struct wdc_link *ctlr_link = d_link->ctlr_link;
- struct wdc_xfer *xfer;
- u_int32_t p_offset;
-
- while (d_link->openings > 0) {
-
- /* Is there a buf for us ? */
- dp = &wd->sc_q;
- if ((bp = dp->b_actf) == NULL) /* yes, an assign */
- return;
- dp->b_actf = bp->b_actf;
-
- /*
- * Make the command. First lock the device
- */
- d_link->openings--;
- if (WDPART(bp->b_dev) != RAW_PART)
- p_offset =
- wd->sc_dk.dk_label->d_partitions[WDPART(bp->b_dev)].p_offset;
- else
- p_offset = 0;
-
- xfer = wdc_get_xfer(ctlr_link, 0);
- if (xfer == NULL)
- panic("wdc_xfer");
-
- xfer->d_link = d_link;
- xfer->c_bp = bp;
- xfer->c_p_offset = p_offset;
- xfer->databuf = bp->b_data;
- xfer->c_flags |= bp->b_flags & (B_READ|B_WRITE);
- xfer->c_skip = 0;
- xfer->c_errors = 0;
- /* count and blkno are filled in by wdcstart */
-
- /* Instrumentation. */
- disk_busy(&wd->sc_dk);
- wdc_exec_xfer(wd->d_link,xfer);
- }
-}
-
-int
-wdread(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
-{
-
- WDDEBUG_PRINT(("wdread\n"));
- return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
-}
-
-int
-wdwrite(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
-{
-
- WDDEBUG_PRINT(("wdwrite\n"));
- return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
-}
-
-/*
- * Wait interruptibly for an exclusive lock.
- *
- * XXX
- * Several drivers do this; it should be abstracted and made MP-safe.
- */
-int
-wdlock(d_link)
- struct wd_link *d_link;
-{
- int error;
- int s;
-
- WDDEBUG_PRINT(("wdlock\n"));
-
- s = splbio();
-
- while ((d_link->sc_flags & WDF_LOCKED) != 0) {
- d_link->sc_flags |= WDF_WANTED;
- if ((error = tsleep(d_link, PRIBIO | PCATCH,
- "wdlck", 0)) != 0) {
- splx(s);
- return error;
- }
- }
- d_link->sc_flags |= WDF_LOCKED;
- splx(s);
- return 0;
-}
-
-/*
- * Unlock and wake up any waiters.
- */
-void
-wdunlock(d_link)
- struct wd_link *d_link;
-{
-
- WDDEBUG_PRINT(("wdunlock"));
-
- d_link->sc_flags &= ~WDF_LOCKED;
- if ((d_link->sc_flags & WDF_WANTED) != 0) {
- d_link->sc_flags &= ~WDF_WANTED;
- wakeup(d_link);
- }
-}
-
-int
-wdopen(dev, flag, fmt, p)
- dev_t dev;
- int flag, fmt;
- struct proc *p;
-{
- struct wd_softc *wd;
- struct wd_link *d_link;
- int unit, part;
- int error;
-
- WDDEBUG_PRINT(("wdopen\n"));
-
- unit = WDUNIT(dev);
- if (unit >= wd_cd.cd_ndevs)
- return ENXIO;
- wd = wd_cd.cd_devs[unit];
- if (wd == 0)
- return ENXIO;
-
- d_link = wd->d_link;
- if ((error = wdlock(d_link)) != 0)
- return error;
-
- if (wd->sc_dk.dk_openmask != 0) {
- /*
- * If any partition is open, but the disk has been invalidated,
- * disallow further opens.
- */
- if ((d_link->sc_flags & WDF_LOADED) == 0) {
- error = EIO;
- goto bad3;
- }
- } else {
- if ((d_link->sc_flags & WDF_LOADED) == 0) {
- d_link->sc_flags |= WDF_LOADED;
-
- /* Load the physical device parameters. */
- if (wdc_get_parms(d_link) != 0) {
- error = ENXIO;
- goto bad2;
- }
-
- /* Load the partition info if not already loaded. */
- wdgetdisklabel(dev, wd, wd->sc_dk.dk_label,
- wd->sc_dk.dk_cpulabel, 0);
- }
- }
-
- part = WDPART(dev);
-
- /* Check that the partition exists. */
- if (part != RAW_PART &&
- (part >= wd->sc_dk.dk_label->d_npartitions ||
- wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
- error = ENXIO;
- goto bad;
- }
-
- /* Insure only one open at a time. */
- switch (fmt) {
- case S_IFCHR:
- wd->sc_dk.dk_copenmask |= (1 << part);
- break;
- case S_IFBLK:
- wd->sc_dk.dk_bopenmask |= (1 << part);
- break;
- }
- wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
-
- wdunlock(d_link);
- return 0;
-
-bad2:
- d_link->sc_flags &= ~WDF_LOADED;
-
-bad:
- if (wd->sc_dk.dk_openmask == 0) {
- }
-
-bad3:
- wdunlock(d_link);
- return error;
-}
-
-int
-wdclose(dev, flag, fmt, p)
- dev_t dev;
- int flag, fmt;
- struct proc *p;
-{
- struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
- int part = WDPART(dev);
- int error;
-
- if ((error = wdlock(wd->d_link)) != 0)
- return error;
-
- switch (fmt) {
- case S_IFCHR:
- wd->sc_dk.dk_copenmask &= ~(1 << part);
- break;
- case S_IFBLK:
- wd->sc_dk.dk_bopenmask &= ~(1 << part);
- break;
- }
- wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
-
- if (wd->sc_dk.dk_openmask == 0) {
- /* XXXX Must wait for I/O to complete! */
- }
-
- wdunlock(wd->d_link);
- return 0;
-}
-
-/*
- * Fabricate a default disk label, and try to read the correct one.
- */
-void
-wdgetdisklabel(dev, wd, lp, clp, spoofonly)
- dev_t dev;
- struct wd_softc *wd;
- struct disklabel *lp;
- struct cpu_disklabel *clp;
- int spoofonly;
-{
- struct wd_link *d_link = wd->d_link;
- char *errstring;
-
- WDDEBUG_PRINT(("wdgetdisklabel\n"));
-
- bzero(lp, sizeof(struct disklabel));
- bzero(clp, sizeof(struct cpu_disklabel));
-
- lp->d_secsize = DEV_BSIZE;
- lp->d_ntracks = d_link->sc_params.wdp_heads;
- lp->d_nsectors = d_link->sc_params.wdp_sectors;
- lp->d_ncylinders = d_link->sc_params.wdp_cylinders;
- lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
-
- strncpy(lp->d_packname, d_link->sc_params.wdp_model, 16);
- if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA)) {
- lp->d_secperunit = d_link->sc_params.wdp_lbacapacity;
- strncpy(lp->d_typename, "ESDI/IDE disk", 16);
- lp->d_type = DTYPE_ESDI;
- } else {
- lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
- strncpy(lp->d_typename, "ST506/MFM/RLL", 16);
- lp->d_type = DTYPE_ST506;
- }
-
- lp->d_rpm = 3600;
- lp->d_interleave = 1;
- lp->d_flags = 0;
-
- lp->d_partitions[RAW_PART].p_offset = 0;
- lp->d_partitions[RAW_PART].p_size =
- lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
- lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
- lp->d_npartitions = RAW_PART + 1;
-
- lp->d_magic = DISKMAGIC;
- lp->d_magic2 = DISKMAGIC;
- lp->d_checksum = dkcksum(lp);
-
- d_link->sc_badsect[0] = -1;
-
- if (d_link->sc_state > RECAL)
- d_link->sc_state = RECAL;
-
- /*
- * Call the generic disklabel extraction routine
- */
- errstring = readdisklabel(WDLABELDEV(dev), wdstrategy, lp, clp,
- spoofonly);
- if (errstring) {
- /*
- * This probably happened because the drive's default
- * geometry doesn't match the DOS geometry. We
- * assume the DOS geometry is now in the label and try
- * again. XXX This is a kluge.
- */
- if (d_link->sc_state > GEOMETRY)
- d_link->sc_state = GEOMETRY;
- errstring = readdisklabel(WDLABELDEV(dev), wdstrategy, lp, clp,
- spoofonly);
- }
- if (errstring) {
- /*printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);*/
- return;
- }
-
- if (d_link->sc_state > GEOMETRY)
- d_link->sc_state = GEOMETRY;
-#ifdef DKBAD
- if ((lp->d_flags & D_BADSECT) != 0)
- bad144intern(wd);
-#endif
-}
-
-/*
- * Tell the drive what geometry to use.
- */
-int
-wdsetctlr(d_link)
- struct wd_link *d_link;
-{
- struct wd_softc *wd=(struct wd_softc *)d_link->wd_softc;
-
- WDDEBUG_PRINT(("wd(%d,%d) C%dH%dS%d\n", wd->sc_dev.dv_unit,
- d_link->sc_drive, wd->sc_dk.dk_label->d_ncylinders,
- wd->sc_dk.dk_label->d_ntracks, wd->sc_dk.dk_label->d_nsectors));
-
- if (wdccommand(d_link, WDCC_IDP, d_link->sc_drive,
- wd->sc_dk.dk_label->d_ncylinders,
- wd->sc_dk.dk_label->d_ntracks - 1, 0,
- wd->sc_dk.dk_label->d_nsectors) != 0) {
- wderror(d_link, NULL, "wdsetctlr: geometry upload failed");
- return -1;
- }
-
- return 0;
-}
-
-int
-wdioctl(dev, xfer, addr, flag, p)
- dev_t dev;
- u_long xfer;
- caddr_t addr;
- int flag;
- struct proc *p;
-{
- struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
- struct wd_link *d_link = wd->d_link;
- int error;
-
- WDDEBUG_PRINT(("wdioctl\n"));
-
- if ((d_link->sc_flags & WDF_LOADED) == 0)
- return EIO;
-
- switch (xfer) {
-#ifdef DKBAD
- case DIOCSBAD:
- if ((flag & FWRITE) == 0)
- return EBADF;
- DKBAD(wd->sc_dk.dk_cpulabel) = *(struct dkbad *)addr;
- wd->sc_dk.dk_label->d_flags |= D_BADSECT;
- bad144intern(wd);
- return 0;
-#endif
-
- case DIOCRLDINFO:
- wdgetdisklabel(dev, wd, wd->sc_dk.dk_label,
- wd->sc_dk.dk_cpulabel, 0);
- return 0;
- case DIOCGPDINFO: {
- struct cpu_disklabel osdep;
-
- wdgetdisklabel(dev, wd, (struct disklabel *)addr,
- &osdep, 1);
- return 0;
- }
- case DIOCGDINFO:
- *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
- return 0;
-
- case DIOCGPART:
- ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
- ((struct partinfo *)addr)->part =
- &wd->sc_dk.dk_label->d_partitions[WDPART(dev)];
- return 0;
-
- case DIOCWDINFO:
- case DIOCSDINFO:
- if ((flag & FWRITE) == 0)
- return EBADF;
-
- if ((error = wdlock(wd->d_link)) != 0)
- return error;
- d_link->sc_flags |= WDF_LABELLING;
-
- error = setdisklabel(wd->sc_dk.dk_label,
- (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0,
- wd->sc_dk.dk_cpulabel);
- if (error == 0) {
- if (d_link->sc_state > GEOMETRY)
- d_link->sc_state = GEOMETRY;
- if (xfer == DIOCWDINFO)
- error = writedisklabel(WDLABELDEV(dev),
- wdstrategy, wd->sc_dk.dk_label,
- wd->sc_dk.dk_cpulabel);
- }
-
- d_link->sc_flags &= ~WDF_LABELLING;
- wdunlock(d_link);
- return error;
-
- case DIOCWLABEL:
- if ((flag & FWRITE) == 0)
- return EBADF;
- if (*(int *)addr)
- d_link->sc_flags |= WDF_WLABEL;
- else
- d_link->sc_flags &= ~WDF_WLABEL;
- return 0;
-
-#ifdef notyet
- case DIOCWFORMAT:
- if ((flag & FWRITE) == 0)
- return EBADF;
- {
- register struct format_op *fop;
- struct iovec aiov;
- struct uio auio;
-
- fop = (struct format_op *)addr;
- aiov.iov_base = fop->df_buf;
- aiov.iov_len = fop->df_count;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_resid = fop->df_count;
- auio.uio_segflg = 0;
- auio.uio_offset =
- fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
- auio.uio_procp = p;
- error = physio(wdformat, NULL, dev, B_WRITE, minphys,
- &auio);
- fop->df_count -= auio.uio_resid;
- fop->df_reg[0] = wdc->sc_status;
- fop->df_reg[1] = wdc->sc_error;
- return error;
- }
-#endif
-
- default:
- return ENOTTY;
- }
-
-#ifdef DIAGNOSTIC
- panic("wdioctl: impossible");
-#endif
-}
-
-#ifdef B_FORMAT
-int
-wdformat(struct buf *bp)
-{
-
- bp->b_flags |= B_FORMAT;
- return wdstrategy(bp);
-}
-#endif
-
-int
-wdsize(dev)
- dev_t dev;
-{
- struct wd_softc *wd;
- int part, unit, omask;
- int size;
-
- WDDEBUG_PRINT(("wdsize\n"));
-
- unit = WDUNIT(dev);
- if (unit >= wd_cd.cd_ndevs)
- return -1;
- wd = wd_cd.cd_devs[unit];
- if (wd == NULL)
- return -1;
-
- part = WDPART(dev);
- omask = wd->sc_dk.dk_openmask & (1 << part);
-
- if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0)
- return -1;
- else if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
- size = -1;
- else
- size = wd->sc_dk.dk_label->d_partitions[part].p_size *
- (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
-
- if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0)
- return -1;
- return size;
-}
-
-
-#ifndef __BDEVSW_DUMP_OLD_TYPE
-/* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
-static int wddoingadump;
-static int wddumprecalibrated;
-
-/*
- * Dump core after a system crash.
- *
- * XXX: This needs work! Currently, it's a major hack: the
- * use of wdc_softc is very bad and should go away.
- */
-int
-wddump(dev, blkno, va, size)
- dev_t dev;
- daddr_t blkno;
- caddr_t va;
- size_t size;
-{
- struct wd_softc *wd; /* disk unit to do the I/O */
- struct wdc_softc *wdc; /* disk controller to do the I/O */
- struct disklabel *lp; /* disk's disklabel */
- struct wd_link *d_link;
- int unit, part;
- int nblks; /* total number of sectors left to write */
-
- /* Check if recursive dump; if so, punt. */
- if (wddoingadump)
- return EFAULT;
- wddoingadump = 1;
-
- unit = WDUNIT(dev);
- if (unit >= wd_cd.cd_ndevs)
- return ENXIO;
- wd = wd_cd.cd_devs[unit];
- if (wd == (struct wd_softc *)0)
- return ENXIO;
- d_link = wd->d_link;
-
- part = WDPART(dev);
-
- /* Make sure it was initialized. */
- if (d_link->sc_state < READY)
- return ENXIO;
-
- wdc = (void *)wd->sc_dev.dv_parent;
-
- /* Convert to disk sectors. Request must be a multiple of size. */
- lp = wd->sc_dk.dk_label;
- if ((size % lp->d_secsize) != 0)
- return EFAULT;
- nblks = size / lp->d_secsize;
- blkno = blkno / (lp->d_secsize / DEV_BSIZE);
-
- /* Check transfer bounds against partition size. */
- if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
- return EINVAL;
-
- /* Offset block number to start of partition. */
- blkno += lp->d_partitions[part].p_offset;
-
- /* Recalibrate, if first dump transfer. */
- if (wddumprecalibrated == 0) {
- wddumprecalibrated = 1;
- if (wdccommandshort(wdc, d_link->sc_drive, WDCC_RECAL) != 0 ||
- wait_for_ready(wdc) != 0 || wdsetctlr(d_link) != 0 ||
- wait_for_ready(wdc) != 0) {
- wderror(d_link, NULL, "wddump: recal failed");
- return EIO;
- }
- }
-
- while (nblks > 0) {
- daddr_t xlt_blkno = blkno;
- int cylin, head, sector;
-
- if ((lp->d_flags & D_BADSECT) != 0) {
- int blkdiff;
- int i;
-
- for (i = 0; (blkdiff = d_link->sc_badsect[i]) != -1; i++) {
- blkdiff -= xlt_blkno;
- if (blkdiff < 0)
- continue;
- if (blkdiff == 0) {
- /* Replace current block of transfer. */
- xlt_blkno = lp->d_secperunit -
- lp->d_nsectors - i - 1;
- }
- break;
- }
- /* Tranfer is okay now. */
- }
-
- if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
- sector = (xlt_blkno >> 0) & 0xff;
- cylin = (xlt_blkno >> 8) & 0xffff;
- head = (xlt_blkno >> 24) & 0xf;
- head |= WDSD_LBA;
- } else {
- sector = xlt_blkno % lp->d_nsectors;
- sector++; /* Sectors begin with 1, not 0. */
- xlt_blkno /= lp->d_nsectors;
- head = xlt_blkno % lp->d_ntracks;
- xlt_blkno /= lp->d_ntracks;
- cylin = xlt_blkno;
- head |= WDSD_CHS;
- }
-
-#ifndef WD_DUMP_NOT_TRUSTED
- if (wdccommand(d_link, WDCC_WRITE, d_link->sc_drive, cylin,
- head, sector, 1) != 0 ||
- wait_for_drq(wdc) != 0) {
- wderror(d_link, NULL, "wddump: write failed");
- return EIO;
- }
-
- /* XXX XXX XXX */
- bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
- (u_int16_t *)va, lp->d_secsize >> 1);
-
- /* Check data request (should be done). */
- if (wait_for_ready(wdc) != 0) {
- wderror(d_link, NULL,
- "wddump: timeout waiting for ready");
- return EIO;
- }
-#else /* WD_DUMP_NOT_TRUSTED */
- /* Let's just talk about this first... */
- printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
- unit, va, cylin, head, sector);
- delay(500 * 1000); /* half a second */
-#endif
-
- /* update block count */
- nblks -= 1;
- blkno += 1;
- va += lp->d_secsize;
- }
-
- wddoingadump = 0;
- return 0;
-}
-#else /* __BDEVSW_DUMP_NEW_TYPE */
-
-
-int
-wddump(dev, blkno, va, size)
- dev_t dev;
- daddr_t blkno;
- caddr_t va;
- size_t size;
-{
-
- /* Not implemented. */
- return ENXIO;
-}
-#endif /* __BDEVSW_DUMP_NEW_TYPE */
-
-#ifdef DKBAD
-/*
- * Internalize the bad sector table.
- */
-void
-bad144intern(wd)
- struct wd_softc *wd;
-{
- struct dkbad *bt = &DKBAD(wd->sc_dk.dk_cpulabel);
- struct disklabel *lp = wd->sc_dk.dk_label;
- struct wd_link *d_link = wd->d_link;
- int i = 0;
-
- WDDEBUG_PRINT(("bad144intern\n"));
-
- for (; i < 126; i++) {
- if (bt->bt_bad[i].bt_cyl == 0xffff)
- break;
- d_link->sc_badsect[i] =
- bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
- (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
- (bt->bt_bad[i].bt_trksec & 0xff);
- }
- for (; i < 127; i++)
- d_link->sc_badsect[i] = -1;
-}
-#endif
-
-void
-wderror(d_link, bp, msg)
- struct wd_link *d_link;
- struct buf *bp;
- char *msg;
-{
- struct wd_softc *wd = (struct wd_softc *)d_link->wd_softc;
-
- if (bp) {
- diskerr(bp, "wd", msg, LOG_PRINTF, bp->b_bcount,
- wd->sc_dk.dk_label);
- printf("\n");
- } else
- printf("%s: %s\n", wd->sc_dev.dv_xname, msg);
-}
-
-void
-wddone(d_link, bp)
- struct wd_link *d_link;
- struct buf *bp;
-{
- struct wd_softc *wd = (void *)d_link->wd_softc;
-
- disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
-}
diff --git a/sys/dev/isa/wdc.c b/sys/dev/isa/wdc.c
deleted file mode 100644
index 6ec61f5c157..00000000000
--- a/sys/dev/isa/wdc.c
+++ /dev/null
@@ -1,1972 +0,0 @@
-/* $OpenBSD: wdc.c,v 1.37 1999/06/28 22:35:24 ho Exp $ */
-/* $NetBSD: wd.c,v 1.150 1996/05/12 23:54:03 mycroft Exp $ */
-
-/*
- * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
- *
- * DMA and multi-sector PIO handling are derived from code contributed by
- * Onno van der Linden.
- *
- * Atapi support added by Manuel Bouyer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Charles M. Hannum.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
- */
-
-#include "isadma.h"
-
-/* #undef ATAPI_DEBUG_WDC */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/buf.h>
-#include <sys/uio.h>
-#include <sys/malloc.h>
-#include <sys/device.h>
-#include <sys/disklabel.h>
-#include <sys/disk.h>
-#include <sys/syslog.h>
-#include <sys/proc.h>
-
-#include <vm/vm.h>
-
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/intr.h>
-
-#include <dev/isa/isavar.h>
-#if NISADMA > 0
-#include <dev/isa/isadmavar.h>
-#endif /* NISADMA > 0 */
-#include <dev/isa/wdreg.h>
-#include <dev/isa/wdlink.h>
-
-#include "wdc.h"
-
-#include "atapibus.h"
-#if NATAPIBUS > 0
-#include <dev/atapi/atapilink.h>
-#endif /* NATAPIBUS */
-
-#define WAITTIME (10 * hz) /* time to wait for a completion */
- /* this is a lot for hard drives, but not for cdroms */
-#define RECOVERYTIME hz/2
-#define WDCDELAY 100
-#define WDCNDELAY 100000 /* delay = 100us; so 10s for a controller state change */
-#if 0
-/* If you enable this, it will report any delays more than 100us * N long. */
-#define WDCNDELAY_DEBUG 50
-#endif
-
-#define WDIORETRIES 3 /* number of retries before giving up */
-
-#define WDPART(dev) DISKPART(dev)
-
-LIST_HEAD(xfer_free_list, wdc_xfer) xfer_free_list;
-
-int wdcprobe __P((struct device *, void *, void *));
-int wdcprint __P((void *, const char *));
-void wdcattach __P((struct device *, struct device *, void *));
-int wdcintr __P((void *));
-
-#if NWDC_ISA
-struct cfattach wdc_isa_ca = {
- sizeof(struct wdc_softc), wdcprobe, wdcattach
-};
-#endif
-
-#if NWDC_ISAPNP
-struct cfattach wdc_isapnp_ca = {
- sizeof(struct wdc_softc), wdcprobe, wdcattach
-};
-#endif
-
-struct cfdriver wdc_cd = {
- NULL, "wdc", DV_DULL
-};
-
-enum wdcreset_mode { WDCRESET_VERBOSE, WDCRESET_SILENT };
-
-#if NWD > 0
-int wdc_ata_intr __P((struct wdc_softc *, struct wdc_xfer *));
-void wdc_ata_start __P((struct wdc_softc *, struct wdc_xfer *));
-void wdc_ata_done __P((struct wdc_softc *, struct wdc_xfer *));
-__inline static void u_int16_to_string __P((u_int16_t *, char *, size_t));
-#endif /* NWD */
-int wait_for_phase __P((struct wdc_softc *, int));
-int wait_for_unphase __P((struct wdc_softc *, int));
-void wdcstart __P((struct wdc_softc *));
-int wdcreset __P((struct wdc_softc *, enum wdcreset_mode));
-void wdcrestart __P((void *arg));
-void wdcunwedge __P((struct wdc_softc *));
-void wdctimeout __P((void *arg));
-int wdccontrol __P((struct wd_link *));
-void wdc_free_xfer __P((struct wdc_xfer *));
-void wdcerror __P((struct wdc_softc*, char *));
-void wdcbit_bucket __P(( struct wdc_softc *, int));
-#if NATAPIBUS > 0
-void wdc_atapi_start __P((struct wdc_softc *,struct wdc_xfer *));
-int wdc_atapi_intr __P((struct wdc_softc *, struct wdc_xfer *));
-void wdc_atapi_done __P((struct wdc_softc *, struct wdc_xfer *));
-#endif /* NATAPIBUS */
-
-#ifdef ATAPI_DEBUG
-static int wdc_nxfer;
-#endif
-
-#ifdef WDDEBUG
-#define WDDEBUG_PRINT(args) printf args
-#else
-#define WDDEBUG_PRINT(args)
-#endif
-
-/* Macro for determining bus type. */
-#if NWDC_ISAPNP
-#define IS_ISAPNP(parent) \
- !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isapnp")
-#else
-#define IS_ISAPNP(parent) 0
-#endif
-
-int
-wdcprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- bus_space_tag_t iot;
- bus_space_handle_t ioh;
- bus_space_handle_t ioh_ctl;
- struct wdc_softc *wdc = match;
- struct isa_attach_args *ia = aux;
-#ifdef notyet
- int err;
-#endif
-
-#if NISADMA == 0
- if (ia->ia_drq != DRQUNK) {
- printf("cannot support dma wdc devices\n");
- return 0;
- }
-#endif
-
- wdc->sc_iot = iot = ia->ia_iot;
- if (IS_ISAPNP(parent)) {
- ioh = ia->ipa_io[0].h;
- ioh_ctl = ia->ipa_io[1].h;
- } else {
- if (bus_space_map(iot, ia->ia_iobase, 8, 0, &ioh))
- return 0;
- if (bus_space_map(iot, ia->ia_iobase + WDCTL_OFFSET,
- 1, 0, &ioh_ctl))
- return 0;
- }
- wdc->sc_ioh = ioh;
- wdc->sc_ioh_ctl = ioh_ctl;
-
- /* Check if we have registers that work. */
- /* Error register not writable, */
- bus_space_write_1(iot, ioh, wd_error, 0x5a);
- /* but all of cyl_lo are. */
- bus_space_write_1(iot, ioh, wd_cyl_lo, 0xa5);
- if (bus_space_read_1(iot, ioh, wd_error) == 0x5a ||
- bus_space_read_1(iot, ioh, wd_cyl_lo) != 0xa5) {
- /*
- * Test for a controller with no IDE master, just one
- * ATAPI device. Select drive 1, and try again.
- */
- bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10);
- bus_space_write_1(iot, ioh, wd_error, 0x5a);
- bus_space_write_1(iot, ioh, wd_cyl_lo, 0xa5);
- if (bus_space_read_1(iot, ioh, wd_error) == 0x5a ||
- bus_space_read_1(iot, ioh, wd_cyl_lo) != 0xa5)
- goto nomatch;
- wdc->sc_flags |= WDCF_ONESLAVE;
- }
-
- if (wdcreset(wdc, WDCRESET_SILENT) != 0) {
- /*
- * If the reset failed, there is no master. test for ATAPI
- * signature on the slave device. If no ATAPI slave, wait 5s
- * and retry a reset.
- */
- bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10); /* slave */
- if (bus_space_read_1(iot, ioh, wd_cyl_lo) != 0x14 ||
- bus_space_read_1(iot, ioh, wd_cyl_hi) != 0xeb) {
- delay(500000);
- if (wdcreset(wdc, WDCRESET_SILENT) != 0)
- goto nomatch;
- }
- wdc->sc_flags |= WDCF_ONESLAVE;
- }
-
- /* Select drive 0 or ATAPI slave device */
- if (wdc->sc_flags & WDCF_ONESLAVE)
- bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10);
- else
- bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM);
-
- /* Wait for controller to become ready. */
- if (wait_for_unbusy(wdc) < 0)
- goto nomatch;
-
- /* Start drive diagnostics. */
- bus_space_write_1(iot, ioh, wd_command, WDCC_DIAGNOSE);
-
- /* Wait for command to complete. */
- if (wait_for_unbusy(wdc) < 0)
- goto nomatch;
-
-#ifdef notyet
- /* See if the drive(s) are alive. */
- err = bus_space_read_1(iot, ioh, wd_error);
- if (err && (err != 0x01)) {
- if (err & 0x80) {
- /* Select drive 1. */
- bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10);
- (void) wait_for_unbusy(wdc);
-
- err = bus_space_read_1(iot, ioh, wd_error);
- if ((err != 0x01) && (err != 0x81))
- goto nomatch;
- } else
- goto nomatch;
- }
-#endif
-
- ia->ia_iosize = 8;
- ia->ia_msize = 0;
- return 1;
-
-nomatch:
- if (!IS_ISAPNP(parent)) {
- bus_space_unmap(iot, ioh, 8);
- bus_space_unmap(iot, ioh_ctl, 1);
- }
- return 0;
-}
-
-int
-wdcprint(aux, wdc)
- void *aux;
- const char *wdc;
-{
- struct wd_link *d_link = aux;
-
- if (!wdc)
- printf(" drive %d", d_link->sc_drive);
- return QUIET;
-}
-
-void
-wdcattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct wdc_softc *wdc = (void *)self;
- struct isa_attach_args *ia = aux;
-#if NWD > 0
- int drive;
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
-#endif /* NWD */
-
- TAILQ_INIT(&wdc->sc_xfer);
- wdc->sc_drq = ia->ia_drq;
-
- printf("\n");
-
- wdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
- IPL_BIO, wdcintr, wdc, wdc->sc_dev.dv_xname);
-
- wdc->ctlr_link.flags = 0;
-#ifdef ATAPI_DEBUG
- wdc_nxfer = 0;
-#endif
-
-#if NATAPIBUS > 0
- /*
- * Attach an ATAPI bus, if configured.
- */
- wdc->ab_link = malloc(sizeof(struct bus_link), M_DEVBUF, M_NOWAIT);
- if (wdc->ab_link == NULL) {
- printf("%s: can't allocate ATAPI link\n", self->dv_xname);
- return;
- }
- bzero(wdc->ab_link,sizeof(struct bus_link));
- wdc->ab_link->type = BUS;
- wdc->ab_link->wdc_softc = (caddr_t)wdc;
- wdc->ab_link->ctlr_link = &(wdc->ctlr_link);
- wdc->ab_link->ctrl = self->dv_unit;
- (void)config_found(self, (void *)wdc->ab_link, NULL);
-#endif /* NATAPIBUS */
-#if NWD > 0
- /*
- * Attach standard IDE/ESDI/etc. disks to the controller.
- */
- for (drive = 0; drive < 2; drive++) {
- /* test for ATAPI signature on this drive */
- bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | (drive << 4));
- if (bus_space_read_1(iot, ioh, wd_cyl_lo) == 0x14 &&
- bus_space_read_1(iot, ioh, wd_cyl_hi) == 0xeb) {
- continue;
- }
- /* controller active while autoconf */
- wdc->sc_flags |= WDCF_ACTIVE;
-
- if (wdccommandshort(wdc, drive, WDCC_RECAL) != 0 ||
- wait_for_ready(wdc) != 0) {
- wdc->d_link[drive] = NULL;
- wdc->sc_flags &= ~WDCF_ACTIVE;
- } else {
- wdc->sc_flags &= ~WDCF_ACTIVE;
- wdc->d_link[drive] = malloc(sizeof(struct wd_link),
- M_DEVBUF, M_NOWAIT);
- if (wdc->d_link[drive] == NULL) {
- printf("%s: can't allocate link for drive %d\n",
- self->dv_xname, drive);
- continue;
- }
- bzero(wdc->d_link[drive],sizeof(struct wd_link));
- wdc->d_link[drive]->type = DRIVE;
- wdc->d_link[drive]->wdc_softc =(caddr_t) wdc;
- wdc->d_link[drive]->ctlr_link = &(wdc->ctlr_link);
- wdc->d_link[drive]->sc_drive = drive;
-#if NISADMA > 0
- if (wdc->sc_drq != DRQUNK)
- wdc->d_link[drive]->sc_mode = WDM_DMA;
- else
-#endif /* NISADMA */
- wdc->d_link[drive]->sc_mode = 0;
-
- (void)config_found(self, (void *)wdc->d_link[drive],
- wdcprint);
- }
- }
-#endif /* NWD */
-}
-
-/*
- * Start I/O on a controller. This does the calculation, and starts a read or
- * write operation. Called to from wdstart() to start a transfer, from
- * wdcintr() to continue a multi-sector transfer or start the next transfer, or
- * wdcrestart() after recovering from an error.
- */
-void
-wdcstart(wdc)
- struct wdc_softc *wdc;
-{
- struct wdc_xfer *xfer;
-
- if ((wdc->sc_flags & WDCF_ACTIVE) != 0 ) {
- WDDEBUG_PRINT(("wdcstart: already active\n"));
- return; /* controller aleady active */
- }
-#ifdef DIAGNOSTIC
- if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0)
- panic("wdcstart: controller waiting for irq");
-#endif
- /*
- * XXX
- * This is a kluge. See comments in wd_get_parms().
- */
- if ((wdc->sc_flags & WDCF_WANTED) != 0) {
-#ifdef ATAPI_DEBUG_WDC
- printf("WDCF_WANTED\n");
-#endif
- wdc->sc_flags &= ~WDCF_WANTED;
- wakeup(wdc);
- return;
- }
- /* is there a xfer ? */
- xfer = wdc->sc_xfer.tqh_first;
- if (xfer == NULL) {
-#ifdef ATAPI_DEBUG2
- printf("wdcstart: null xfer\n");
-#endif
- return;
- }
- wdc->sc_flags |= WDCF_ACTIVE;
-#if NATAPIBUS > 0 && NWD > 0
- if (xfer->c_flags & C_ATAPI) {
-#ifdef ATAPI_DEBUG_WDC
- printf("wdcstart: atapi\n");
-#endif
- wdc_atapi_start(wdc, xfer);
- } else
- wdc_ata_start(wdc, xfer);
-#else
-#if NATAPIBUS > 0
-#ifdef ATAPI_DEBUG_WDC
- printf("wdcstart: atapi\n");
-#endif
- wdc_atapi_start(wdc, xfer);
-#endif /* NATAPIBUS */
-#if NWD > 0
- wdc_ata_start(wdc, xfer);
-#endif /* NWD */
-#endif /* NATAPIBUS && NWD */
-}
-
-#if NWD > 0
-void
-wdc_ata_start(wdc, xfer)
- struct wdc_softc *wdc;
- struct wdc_xfer *xfer;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
-#ifdef WDDEBUG
- bus_space_handle_t ioh_ctl = wdc->sc_ioh_ctl;
-#endif
- struct wd_link *d_link = xfer->d_link;
- struct buf *bp = xfer->c_bp;
- int nblks;
-
- if (xfer->c_errors >= WDIORETRIES) {
- wderror(d_link, bp, "wdcstart hard error");
- xfer->c_flags |= C_ERROR;
- wdc_ata_done(wdc, xfer);
- return;
- }
-
- /* Do control operations specially. */
- if (d_link->sc_state < READY) {
- /*
- * Actually, we want to be careful not to mess with the control
- * state if the device is currently busy, but we can assume
- * that we never get to this point if that's the case.
- */
- if (wdccontrol(d_link) == 0) {
- /* The drive is busy. Wait. */
- return;
- }
- }
-
- /*
- * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
- * encountered. If we are in multi-sector mode, then we switch to
- * single-sector mode and retry the operation from the start.
- */
- if (wdc->sc_flags & WDCF_ERROR) {
- wdc->sc_flags &= ~WDCF_ERROR;
- if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
- wdc->sc_flags |= WDCF_SINGLE;
- xfer->c_skip = 0;
- }
- }
-
-
- /* When starting a transfer... */
- if (xfer->c_skip == 0) {
- struct buf *bp = xfer->c_bp;
-
- xfer->c_bcount = bp->b_bcount;
- xfer->c_blkno = (bp->b_blkno + xfer->c_p_offset) / (d_link->sc_lp->d_secsize / DEV_BSIZE);
- WDDEBUG_PRINT(("\n%s: wdc_ata_start %s %d@%d; map ",
- wdc->sc_dev.dv_xname,
- (xfer->c_flags & B_READ) ? "read" : "write",
- xfer->c_bcount, xfer->c_blkno));
- } else {
- WDDEBUG_PRINT((" %d)0x%x", xfer->c_skip,
- bus_space_read_1(iot, ioh_ctl, wd_altsts)));
- }
-
- /*
- * When starting a multi-sector transfer, or doing single-sector
- * transfers...
- */
- if (xfer->c_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
- d_link->sc_mode == WDM_DMA) {
- daddr_t blkno = xfer->c_blkno;
- int cylin, head, sector;
- int command;
-
- if ((wdc->sc_flags & WDCF_SINGLE) != 0)
- nblks = 1;
-#if NISADMA > 0
- else if (d_link->sc_mode != WDM_DMA)
- nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
- else
- nblks =
- min(xfer->c_bcount / d_link->sc_lp->d_secsize, 8);
-#else
- else
- nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
-#endif
-
- /* Check for bad sectors and adjust transfer, if necessary. */
- if ((d_link->sc_lp->d_flags & D_BADSECT) != 0
-#ifdef B_FORMAT
- && (bp->b_flags & B_FORMAT) == 0
-#endif
- ) {
- int blkdiff;
- int i;
-
- for (i = 0;
- (blkdiff = d_link->sc_badsect[i]) != -1; i++) {
- blkdiff -= blkno;
- if (blkdiff < 0)
- continue;
- if (blkdiff == 0) {
- /* Replace current block of xfer. */
- blkno = d_link->sc_lp->d_secperunit -
- d_link->sc_lp->d_nsectors - i - 1;
- }
- if (blkdiff < nblks) {
- /* Bad block inside transfer. */
- wdc->sc_flags |= WDCF_SINGLE;
- nblks = 1;
- }
- break;
- }
- /* Tranfer is okay now. */
- }
-
- if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
- sector = (blkno >> 0) & 0xff;
- cylin = (blkno >> 8) & 0xffff;
- head = (blkno >> 24) & 0xf;
- head |= WDSD_LBA;
- } else {
- sector = blkno % d_link->sc_lp->d_nsectors;
- sector++; /* Sectors begin with 1, not 0. */
- blkno /= d_link->sc_lp->d_nsectors;
- head = blkno % d_link->sc_lp->d_ntracks;
- blkno /= d_link->sc_lp->d_ntracks;
- cylin = blkno;
- head |= WDSD_CHS;
- }
-
- if (d_link->sc_mode == WDM_PIOSINGLE ||
- (wdc->sc_flags & WDCF_SINGLE) != 0)
- xfer->c_nblks = 1;
- else if (d_link->sc_mode == WDM_PIOMULTI)
- xfer->c_nblks = min(nblks, d_link->sc_multiple);
- else
- xfer->c_nblks = nblks;
- xfer->c_nbytes = xfer->c_nblks * d_link->sc_lp->d_secsize;
-
-#ifdef B_FORMAT
- if (bp->b_flags & B_FORMAT) {
- sector = d_link->sc_lp->d_gap3;
- nblks = d_link->sc_lp->d_nsectors;
- command = WDCC_FORMAT;
- } else
-#endif
- switch (d_link->sc_mode) {
-#if NISADMA > 0
- case WDM_DMA:
- command = (xfer->c_flags & B_READ) ?
- WDCC_READDMA : WDCC_WRITEDMA;
- /*
- * Start the DMA channel and bounce the buffer if
- * necessary.
- */
- isadma_start(xfer->databuf + xfer->c_skip,
- xfer->c_nbytes, wdc->sc_drq,
- xfer->c_flags & B_READ ?
- DMAMODE_READ : DMAMODE_WRITE);
- break;
-#endif
-
- case WDM_PIOMULTI:
- command = (xfer->c_flags & B_READ) ?
- WDCC_READMULTI : WDCC_WRITEMULTI;
- break;
-
- case WDM_PIOSINGLE:
- command = (xfer->c_flags & B_READ) ?
- WDCC_READ : WDCC_WRITE;
- break;
-
- default:
-#ifdef DIAGNOSTIC
- panic("bad wd mode");
-#endif
- return;
- }
-
- /* Initiate command! */
- if (wdccommand(d_link, command, d_link->sc_drive,
- cylin, head, sector, nblks) != 0) {
- wderror(d_link, NULL,
- "wdc_ata_start: timeout waiting for unbusy");
- wdcunwedge(wdc);
- return;
- }
-
- WDDEBUG_PRINT(("sector %d cylin %d head %d addr %x sts %x\n",
- sector, cylin, head, xfer->databuf,
- bus_space_read_1(iot, ioh_ctl, wd_altsts)));
-
- } else if (xfer->c_nblks > 1) {
- /* The number of blocks in the last stretch may be smaller. */
- nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
- if (xfer->c_nblks > nblks) {
- xfer->c_nblks = nblks;
- xfer->c_nbytes = xfer->c_bcount;
- }
- }
-
- /* If this was a write and not using DMA, push the data. */
- if (d_link->sc_mode != WDM_DMA &&
- (xfer->c_flags & (B_READ|B_WRITE)) == B_WRITE) {
- if (wait_for_drq(wdc) < 0) {
- wderror(d_link, NULL,
- "wdc_ata_start: timeout waiting for drq");
- wdcunwedge(wdc);
- return;
- }
-
- /* Push out data. */
- if ((d_link->sc_flags & WDF_32BIT) == 0)
- bus_space_write_raw_multi_2(iot, ioh, wd_data,
- xfer->databuf + xfer->c_skip, xfer->c_nbytes);
- else
- bus_space_write_raw_multi_4(iot, ioh, wd_data,
- xfer->databuf + xfer->c_skip, xfer->c_nbytes);
- }
-
- wdc->sc_flags |= WDCF_IRQ_WAIT;
- WDDEBUG_PRINT(("wdc_ata_start: timeout "));
- timeout(wdctimeout, wdc, WAITTIME);
- WDDEBUG_PRINT(("done\n"));
-}
-
-int
-wdc_ata_intr(wdc, xfer)
- struct wdc_softc *wdc;
- struct wdc_xfer *xfer;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- struct wd_link *d_link = xfer->d_link;
-
- if (wait_for_unbusy(wdc) < 0) {
- wdcerror(wdc, "wdcintr: timeout waiting for unbusy");
- wdc->sc_status |= WDCS_ERR; /* XXX */
- }
-
- untimeout(wdctimeout, wdc);
-
- /* Is it not a transfer, but a control operation? */
- if (d_link->sc_state < READY) {
- if (wdccontrol(d_link) == 0) {
- /* The drive is busy. Wait. */
- return 1;
- }
- WDDEBUG_PRINT(
- ("wdc_ata_start from wdc_ata_intr(open) flags %d\n",
- wdc->sc_flags));
- wdc_ata_start(wdc,xfer);
- return 1;
- }
-
-#if NISADMA > 0
- /* Turn off the DMA channel and unbounce the buffer. */
- if (d_link->sc_mode == WDM_DMA)
- isadma_done(wdc->sc_drq);
-#endif
-
- /* Have we an error? */
- if (wdc->sc_status & WDCS_ERR) {
-#ifdef WDDEBUG
- wderror(d_link, NULL, "wdc_ata_intr");
-#endif
- if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
- wdc->sc_flags |= WDCF_ERROR;
- goto restart;
- }
-
-#ifdef B_FORMAT
- if (bp->b_flags & B_FORMAT)
- goto bad;
-#endif
-
- if (++xfer->c_errors == (WDIORETRIES + 1) / 2) {
- wdcunwedge(wdc);
- return 1;
- }
- if (xfer->c_errors < WDIORETRIES)
- goto restart;
-
- wderror(d_link, xfer->c_bp, "hard error");
-
-#ifdef B_FORMAT
- bad:
-#endif
- xfer->c_flags |= C_ERROR;
- goto done;
- }
-
- /* If this was a read and not using DMA, fetch the data. */
- if (d_link->sc_mode != WDM_DMA &&
- (xfer->c_flags & (B_READ|B_WRITE)) == B_READ) {
- if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
- != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
- wderror(d_link, NULL, "wdcintr: read intr before drq");
- wdcunwedge(wdc);
- return 1;
- }
-
- /* Pull in data. */
- if ((d_link->sc_flags & WDF_32BIT) == 0)
- bus_space_read_raw_multi_2(iot, ioh, wd_data,
- xfer->databuf + xfer->c_skip, xfer->c_nbytes);
- else
- bus_space_read_raw_multi_4(iot, ioh, wd_data,
- xfer->databuf + xfer->c_skip, xfer->c_nbytes);
- }
-
- /* If we encountered any abnormalities, flag it as a soft error. */
- if (xfer->c_errors > 0 ||
- (wdc->sc_status & WDCS_CORR) != 0) {
- wderror(d_link, xfer->c_bp, "soft error (corrected)");
- xfer->c_errors = 0;
- }
-
- /* Adjust pointers for the next block, if any. */
- xfer->c_blkno += xfer->c_nblks;
- xfer->c_skip += xfer->c_nbytes;
- xfer->c_bcount -= xfer->c_nbytes;
-
- /* See if this transfer is complete. */
- if (xfer->c_bcount > 0)
- goto restart;
-
-done:
- /* Done with this transfer, with or without error. */
- wdc_ata_done(wdc, xfer);
- return 0;
-
-restart:
- /* Start the next operation */
- WDDEBUG_PRINT(("wdc_ata_start from wdcintr flags %d\n",
- wdc->sc_flags));
- wdc_ata_start(wdc, xfer);
-
- return 1;
-}
-
-void
-wdc_ata_done(wdc, xfer)
- struct wdc_softc *wdc;
- struct wdc_xfer *xfer;
-{
- struct buf *bp = xfer->c_bp;
- struct wd_link *d_link = xfer->d_link;
- int s;
-
- WDDEBUG_PRINT(("wdc_ata_done\n"));
-
- /* remove this command from xfer queue */
- s = splbio();
- TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
- wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
- if (bp) {
- if (xfer->c_flags & C_ERROR) {
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- }
- bp->b_resid = xfer->c_bcount;
- wddone(d_link, bp);
- biodone(bp);
- } else {
- wakeup(xfer->databuf);
- }
- xfer->c_skip = 0;
- wdc_free_xfer(xfer);
- d_link->openings++;
- wdstart((void *)d_link->wd_softc);
- WDDEBUG_PRINT(("wdcstart from wdc_ata_done, flags %d\n",
- wdc->sc_flags));
- wdcstart(wdc);
- splx(s);
-}
-
-/* decode IDE strings, stored as if the words are big-endian. */
-__inline static void
-u_int16_to_string(from, to, cnt)
- u_int16_t *from;
- char *to;
- size_t cnt;
-{
- size_t i;
-
- for (i = 0; i < cnt; i += 2) {
- *to++ = (char)(*from >> 8 & 0xff);
- *to++ = (char)(*from++ & 0xff);
- }
-}
-
-/*
- * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
- */
-int
-wdc_get_parms(d_link)
- struct wd_link *d_link;
-{
- struct wdc_softc *wdc = (struct wdc_softc *)d_link->wdc_softc;
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- u_int16_t tb[DEV_BSIZE / sizeof(u_int16_t)];
- int s, error;
-
- /*
- * XXX
- * The locking done here, and the length of time this may keep the rest
- * of the system suspended, is a kluge. This should be rewritten to
- * set up a transfer and queue it through wdstart(), but it's called
- * infrequently enough that this isn't a pressing matter.
- */
-
- s = splbio();
-
- while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
- wdc->sc_flags |= WDCF_WANTED;
- error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0);
- if (error != 0) {
- splx(s);
- return error;
- }
- }
-
- wdc->sc_flags |= WDCF_ACTIVE;
-
- if (wdccommandshort(wdc, d_link->sc_drive, WDCC_IDENTIFY) != 0 ||
- wait_for_drq(wdc) != 0) {
- /*
- * We `know' there's a drive here; just assume it's old.
- * This geometry is only used to read the MBR and print a
- * (false) attach message.
- */
- strncpy(d_link->sc_lp->d_typename, "ST506",
- sizeof d_link->sc_lp->d_typename);
- d_link->sc_lp->d_type = DTYPE_ST506;
-
- strncpy(d_link->sc_params.wdp_model, "ST506/MFM/RLL",
- sizeof d_link->sc_params.wdp_model);
- d_link->sc_params.wdp_config = WD_CFG_FIXED;
- d_link->sc_params.wdp_cylinders = 1024;
- d_link->sc_params.wdp_heads = 8;
- d_link->sc_params.wdp_sectors = 17;
- d_link->sc_params.wdp_maxmulti = 0;
- d_link->sc_params.wdp_usedmovsd = 0;
- d_link->sc_params.wdp_capabilities = 0;
- } else {
- strncpy(d_link->sc_lp->d_typename, "ESDI/IDE",
- sizeof d_link->sc_lp->d_typename);
- d_link->sc_lp->d_type = DTYPE_ESDI;
-
- /* Read in parameter block. */
- bus_space_read_multi_2(iot, ioh, wd_data, tb,
- sizeof(tb) / sizeof(u_int16_t));
- d_link->sc_params.wdp_config = (u_int16_t)tb[0];
- d_link->sc_params.wdp_cylinders = (u_int16_t)tb[1];
- d_link->sc_params.wdp_heads = (u_int16_t)tb[3];
- d_link->sc_params.wdp_unfbytespertrk = (u_int16_t)tb[4];
- d_link->sc_params.wdp_unfbytespersec = (u_int16_t)tb[5];
- d_link->sc_params.wdp_sectors = (u_int16_t)tb[6];
- u_int16_to_string (tb + 7, d_link->sc_params.wdp_vendor1, 6);
- u_int16_to_string (tb + 10, d_link->sc_params.wdp_serial, 20);
- d_link->sc_params.wdp_buftype = (u_int16_t)tb[20];
- d_link->sc_params.wdp_bufsize = (u_int16_t)tb[21];
- d_link->sc_params.wdp_eccbytes = (u_int16_t)tb[22];
- u_int16_to_string (tb + 23, d_link->sc_params.wdp_revision, 8);
- u_int16_to_string (tb + 27, d_link->sc_params.wdp_model, 40);
- d_link->sc_params.wdp_maxmulti = (u_int8_t)(tb[47] & 0xff);
- d_link->sc_params.wdp_vendor2[0] = (u_int8_t)(tb[47] >> 8 &
- 0xff);
- d_link->sc_params.wdp_usedmovsd = (u_int16_t)tb[48];
- d_link->sc_params.wdp_vendor3[0] = (u_int8_t)(tb[49] & 0xff);
- d_link->sc_params.wdp_capabilities = (u_int8_t)(tb[49] >> 8 &
- 0xff);
- d_link->sc_params.wdp_vendor4[0] = (u_int8_t)(tb[50] & 0xff);
- d_link->sc_params.wdp_piotiming = (u_int8_t)(tb[50] >> 8 &
- 0xff);
- d_link->sc_params.wdp_vendor5[0] = (u_int8_t)(tb[51] & 0xff);
- d_link->sc_params.wdp_dmatiming = (u_int8_t)(tb[51] >> 8 &
- 0xff);
- d_link->sc_params.wdp_capvalid = (u_int16_t)tb[53];
- d_link->sc_params.wdp_curcyls = (u_int16_t)tb[54];
- d_link->sc_params.wdp_curheads = (u_int16_t)tb[55];
- d_link->sc_params.wdp_cursectors = (u_int16_t)tb[56];
- d_link->sc_params.wdp_curcapacity = ((u_int32_t)tb[58] << 16) + tb[57];
- d_link->sc_params.wdp_curmulti = (u_int8_t)(tb[59] & 0xff);
- d_link->sc_params.wdp_valmulti = (u_int8_t)(tb[59] >> 8 & 0xff);
- d_link->sc_params.wdp_lbacapacity = ((u_int32_t)tb[61] << 16) + tb[60];
- d_link->sc_params.wdp_dma1word = (u_int16_t)tb[62];
- d_link->sc_params.wdp_dmamword = (u_int16_t)tb[63];
- d_link->sc_params.wdp_eidepiomode = (u_int16_t)tb[64];
- d_link->sc_params.wdp_eidedmamin = (u_int16_t)tb[65];
- d_link->sc_params.wdp_eidedmatime = (u_int16_t)tb[66];
- d_link->sc_params.wdp_eidepiotime = (u_int16_t)tb[67];
- d_link->sc_params.wdp_eidepioiordy = (u_int16_t)tb[68];
- }
-
- /* Clear any leftover interrupt. */
- (void) bus_space_read_1(iot, ioh, wd_status);
-
- /* Restart the queue. */
- WDDEBUG_PRINT(("wdcstart from wdc_get_parms flags %d\n",
- wdc->sc_flags));
- wdc->sc_flags &= ~WDCF_ACTIVE;
- wdcstart(wdc);
-
- splx(s);
- return 0;
-}
-
-/*
- * Implement operations needed before read/write.
- * Returns 0 if operation still in progress, 1 if completed.
- */
-int
-wdccontrol(d_link)
- struct wd_link *d_link;
-{
- struct wdc_softc *wdc = (void *)d_link->wdc_softc;
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
-
- WDDEBUG_PRINT(("wdccontrol\n"));
-
- switch (d_link->sc_state) {
- case RECAL: /* Set SDH, step rate, do recal. */
- if (wdccommandshort(wdc, d_link->sc_drive, WDCC_RECAL) != 0) {
- wderror(d_link, NULL, "wdccontrol: recal failed (1)");
- goto bad;
- }
- d_link->sc_state = RECAL_WAIT;
- break;
-
- case RECAL_WAIT:
- if (wdc->sc_status & WDCS_ERR) {
- wderror(d_link, NULL, "wdccontrol: recal failed (2)");
- goto bad;
- }
- /* fall through */
-
- case GEOMETRY:
- if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
- goto multimode;
- if (wdsetctlr(d_link) != 0) {
- /* Already printed a message. */
- goto bad;
- }
- d_link->sc_state = GEOMETRY_WAIT;
- break;
-
- case GEOMETRY_WAIT:
- if (wdc->sc_status & WDCS_ERR) {
- wderror(d_link, NULL, "wdccontrol: geometry failed");
- goto bad;
- }
- /* fall through */
-
- case MULTIMODE:
- multimode:
- if (d_link->sc_mode != WDM_PIOMULTI)
- goto ready;
- bus_space_write_1(iot, ioh, wd_seccnt, d_link->sc_multiple);
- if (wdccommandshort(wdc, d_link->sc_drive,
- WDCC_SETMULTI) != 0) {
- wderror(d_link, NULL,
- "wdccontrol: setmulti failed (1)");
- goto bad;
- }
- d_link->sc_state = MULTIMODE_WAIT;
- break;
-
- case MULTIMODE_WAIT:
- if (wdc->sc_status & WDCS_ERR) {
- wderror(d_link, NULL,
- "wdccontrol: setmulti failed (2)");
- goto bad;
- }
- /* fall through */
-
- case READY:
- ready:
- d_link->sc_state = READY;
- /*
- * The rest of the initialization can be done by normal means.
- */
- return 1;
-
- bad:
- wdcunwedge(wdc);
- return 0;
- }
-
- wdc->sc_flags |= WDCF_IRQ_WAIT;
- timeout(wdctimeout, wdc, WAITTIME);
- return 0;
-}
-#endif /* NWD */
-
-int
-wait_for_phase(wdc, wphase)
- struct wdc_softc *wdc;
- int wphase;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- int i, phase;
-
- for (i = 20000; i; i--) {
- phase = (bus_space_read_1(iot, ioh, wd_ireason) &
- (WDCI_CMD | WDCI_IN)) |
- (bus_space_read_1(iot, ioh, wd_status)
- & WDCS_DRQ);
- if (phase == wphase)
- break;
- delay(10);
- }
- return (phase);
-}
-
-int
-wait_for_unphase(wdc, wphase)
- struct wdc_softc *wdc;
- int wphase;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- int i, phase;
-
- for (i = 20000; i; i--) {
- phase = (bus_space_read_1(iot, ioh, wd_ireason) &
- (WDCI_CMD | WDCI_IN)) |
- (bus_space_read_1(iot, ioh, wd_status)
- & WDCS_DRQ);
- if (phase != wphase)
- break;
- delay(10);
- }
- return (phase);
-}
-
-#if NATAPIBUS > 0
-void
-wdc_atapi_start(wdc, xfer)
- struct wdc_softc *wdc;
- struct wdc_xfer *xfer;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- struct atapi_command_packet *acp = xfer->atapi_cmd;
-
-#ifdef ATAPI_DEBUG_WDC
- printf("wdc_atapi_start, acp flags %lx\n",acp->flags);
-#endif
- if (xfer->c_errors >= WDIORETRIES) {
- acp->status |= ERROR;
- acp->error = bus_space_read_1(iot, ioh, wd_error);
- wdc_atapi_done(wdc, xfer);
- return;
- }
- if (wait_for_unbusy(wdc) != 0) {
- if ((wdc->sc_status & WDCS_ERR) == 0) {
- printf("wdc_atapi_start: not ready, st = %02x\n",
- wdc->sc_status);
- acp->status = ERROR;
- return;
- }
- }
-
- if (wdccommand((struct wd_link*)xfer->d_link, ATAPI_PACKET_COMMAND,
- acp->drive, acp->data_size, 0, 0, 0) != 0) {
- printf("wdc_atapi_start: can't send atapi paket command\n");
- acp->status = ERROR;
- wdc->sc_flags |= WDCF_IRQ_WAIT;
- return;
- }
- if ((acp->flags & (ACAP_DRQ_INTR|ACAP_DRQ_ACCEL)) != ACAP_DRQ_INTR) {
- if (!(wdc->sc_flags & WDCF_BROKENPOLL)) {
- int phase = wait_for_phase(wdc, PHASE_CMDOUT);
-
- if (phase != PHASE_CMDOUT) {
- printf("wdc_atapi_start: timeout waiting "
- "PHASE_CMDOUT, got 0x%x\n", phase);
-
- /* NEC SUCKS. */
- wdc->sc_flags |= WDCF_BROKENPOLL;
- }
- } else
- DELAY(10); /* Simply pray for the data. */
-
- bus_space_write_raw_multi_2(iot, ioh, wd_data, acp->command,
- acp->command_size);
- }
- wdc->sc_flags |= WDCF_IRQ_WAIT;
-
-#ifdef ATAPI_DEBUG2
- printf("wdc_atapi_start: timeout\n");
-#endif
- timeout(wdctimeout, wdc, WAITTIME);
- return;
-}
-
-int
-wdc_atapi_get_params(ab_link, drive, id)
- struct bus_link *ab_link;
- u_int8_t drive;
- struct atapi_identify *id;
-{
- struct wdc_softc *wdc = (void*)ab_link->wdc_softc;
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- int status, len, excess = 0;
- int s, error;
-
- if (wdc->d_link[drive] != 0) {
-#ifdef ATAPI_DEBUG_PROBE
- printf("wdc_atapi_get_params: WD drive %d\n", drive);
-
-#endif
- return 0;
- }
-
- /*
- * If there is only one ATAPI slave on the bus, don't probe
- * drive 0 (master)
- */
-
- if ((wdc->sc_flags & WDCF_ONESLAVE) && (drive != 1))
- return 0;
-
-#ifdef ATAPI_DEBUG_PROBE
- printf("wdc_atapi_get_params: probing drive %d\n", drive);
-#endif
-
- /*
- * XXX
- * The locking done here, and the length of time this may keep the rest
- * of the system suspended, is a kluge. This should be rewritten to
- * set up a transfer and queue it through wdstart(), but it's called
- * infrequently enough that this isn't a pressing matter.
- */
-
- s = splbio();
-
- while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
- wdc->sc_flags |= WDCF_WANTED;
- if ((error = tsleep(wdc, PRIBIO | PCATCH, "atprm", 0)) != 0) {
- splx(s);
- return error;
- }
- }
-
- wdc->sc_flags |= WDCF_ACTIVE;
- error = 1;
- (void)wdcreset(wdc, WDCRESET_VERBOSE);
- if ((status = wdccommand((struct wd_link*)ab_link,
- ATAPI_SOFT_RESET, drive, 0, 0, 0, 0)) != 0) {
-#ifdef ATAPI_DEBUG
- printf("wdc_atapi_get_params: ATAPI_SOFT_RESET"
- "failed for drive %d: status %d error %d\n",
- drive, status, wdc->sc_error);
-#endif
- error = 0;
- goto end;
- }
- if ((status = wait_for_unbusy(wdc)) != 0) {
-#ifdef ATAPI_DEBUG
- printf("wdc_atapi_get_params: wait_for_unbusy failed "
- "for drive %d: status %d error %d\n",
- drive, status, wdc->sc_error);
-#endif
- error = 0;
- goto end;
- }
-
- if (wdccommand((struct wd_link*)ab_link, ATAPI_IDENTIFY_DEVICE,
- drive, sizeof(struct atapi_identify), 0, 0, 0) != 0 ||
- atapi_ready(wdc) != 0) {
-#ifdef ATAPI_DEBUG_PROBE
- printf("ATAPI_IDENTIFY_DEVICE failed for drive %d\n", drive);
-#endif
- error = 0;
- goto end;
- }
- len = bus_space_read_1(iot, ioh, wd_cyl_lo) + 256 *
- bus_space_read_1(iot, ioh, wd_cyl_hi);
- if (len != sizeof(struct atapi_identify)) {
- if (len < 142) { /* XXX */
- printf("%s: drive %d returned %d/%d of identify device data, device unusuable\n",
- wdc->sc_dev.dv_xname, drive, len,
- sizeof(struct atapi_identify));
-
- error = 0;
- goto end;
- }
-
- excess = (len - sizeof(struct atapi_identify));
- if (excess < 0)
- excess = 0;
- }
- bus_space_read_raw_multi_2(iot, ioh, wd_data, (u_int8_t *)id,
- sizeof(struct atapi_identify));
- wdcbit_bucket(wdc, excess);
-
- end: /* Restart the queue. */
- WDDEBUG_PRINT(("wdcstart from wdc_atapi_get_params flags %d\n",
- wdc->sc_flags));
- wdc->sc_flags &= ~WDCF_ACTIVE;
- wdcstart(wdc);
- splx(s);
- return error;
-}
-
-void
-wdc_atapi_send_command_packet(ab_link, acp)
- struct bus_link *ab_link;
- struct atapi_command_packet *acp;
-{
- struct wdc_softc *wdc = (void*)ab_link->wdc_softc;
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- bus_space_handle_t ioh_ctl = wdc->sc_ioh_ctl;
- struct wdc_xfer *xfer;
- u_int8_t flags = acp->flags & 0xff;
-
- if (flags & A_POLLED) { /* Must use the queue and wdc_atapi_start */
- struct wdc_xfer xfer_s;
- int i, phase;
-
-#ifdef ATAPI_DEBUG_WDC
- printf("wdc_atapi_send_cmd: "
- "flags %ld drive %d cmdlen %d datalen %d",
- acp->flags, acp->drive, acp->command_size, acp->data_size);
-#endif
- xfer = &xfer_s;
- bzero(xfer, sizeof(xfer_s));
- xfer->c_flags = C_INUSE|C_ATAPI|acp->flags;
- xfer->d_link = (struct wd_link *)ab_link;
- xfer->c_link = ab_link->ctlr_link;
- xfer->c_bp = acp->bp;
- xfer->atapi_cmd = acp;
- xfer->c_blkno = 0;
- xfer->databuf = acp->databuf;
- xfer->c_bcount = acp->data_size;
- if (wait_for_unbusy (wdc) != 0) {
- if ((wdc->sc_status & WDCS_ERR) == 0) {
- printf("wdc_atapi_send_command: not ready, "
- "st = %02x\n", wdc->sc_status);
- acp->status = ERROR;
- return;
- }
- }
-
- /* Turn off interrupts. */
- bus_space_write_1(iot, ioh_ctl, wd_ctlr, WDCTL_4BIT|WDCTL_IDS);
- delay(1000);
-
- if (wdccommand((struct wd_link*)ab_link,
- ATAPI_PACKET_COMMAND, acp->drive, acp->data_size,
- 0, 0, 0) != 0) {
- printf("can't send atapi paket command\n");
- acp->status = ERROR;
- return;
- }
-
- /* Wait for cmd i/o phase. */
- phase = wait_for_phase(wdc, PHASE_CMDOUT);
- if (phase != PHASE_CMDOUT)
- printf("wdc_atapi_send_command_packet: "
- "got wrong phase (0x%x) wanted cmd I/O\n",
- phase);
-
- bus_space_write_raw_multi_2(iot, ioh, wd_data, acp->command,
- acp->command_size);
-
- /* Wait for data i/o phase. */
- phase = wait_for_unphase(wdc, PHASE_CMDOUT);
- if (phase == PHASE_CMDOUT)
- printf("wdc_atapi_send_command_packet: "
- "got wrong phase (0x%x) wanted data I/O\n",
- phase);
-
- while (wdc_atapi_intr(wdc, xfer)) {
- for (i = 2000; i > 0; --i) {
- if ((bus_space_read_1(iot, ioh, wd_status) &
- WDCS_DRQ) == 0)
- break;
- delay(10);
- }
-#ifdef ATAPI_DEBUG_WDC
- printf("wdc_atapi_send_command_packet: i = %d\n", i);
-#endif
- }
-
- /* Turn on interrupts again. */
- bus_space_write_1(iot, ioh_ctl, wd_ctlr, WDCTL_4BIT);
- delay(1000);
-
- wdc->sc_flags &= ~(WDCF_IRQ_WAIT | WDCF_SINGLE | WDCF_ERROR);
- xfer->c_errors = 0;
- xfer->c_skip = 0;
- return;
- } else { /* POLLED */
- xfer = wdc_get_xfer(ab_link->ctlr_link,
- flags & A_NOSLEEP ? IDE_NOSLEEP : 0);
- if (xfer == NULL) {
- acp->status = ERROR;
- return;
- }
- xfer->c_flags |= C_ATAPI|acp->flags;
- xfer->d_link = (struct wd_link*) ab_link;
- xfer->c_link = ab_link->ctlr_link;
- xfer->c_bp = acp->bp;
- xfer->atapi_cmd = acp;
- xfer->c_blkno = 0;
- xfer->databuf = acp->databuf;
- xfer->c_bcount = acp->data_size;
- wdc_exec_xfer((struct wd_link*)ab_link,xfer);
- return;
- }
-}
-
-int
-wdc_atapi_intr(wdc, xfer)
- struct wdc_softc *wdc;
- struct wdc_xfer *xfer;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- struct atapi_command_packet *acp = xfer->atapi_cmd;
- int len, phase, i, retries = 0;
- int err, st, ire;
-
- if (wait_for_unbusy(wdc) < 0) {
- printf("wdc_atapi_intr: controller busy\n");
- acp->status = ERROR;
- acp->error = bus_space_read_1(iot, ioh, wd_error);
- return 0;
- }
-
-#ifdef ATAPI_DEBUG2
- printf("wdc_atapi_intr: %s\n", wdc->sc_dev.dv_xname);
-#endif
-
-again:
- len = bus_space_read_1(iot, ioh, wd_cyl_lo) +
- 256 * bus_space_read_1(iot, ioh, wd_cyl_hi);
-
- st = bus_space_read_1(iot, ioh, wd_status);
- err = bus_space_read_1(iot, ioh, wd_error);
- ire = bus_space_read_1(iot, ioh, wd_ireason);
-
- phase = (ire & (WDCI_CMD | WDCI_IN)) | (st & WDCS_DRQ);
-#ifdef ATAPI_DEBUG_WDC
- printf("wdc_atapi_intr: len %d st %d err %d ire %d :",
- len, st, err, ire);
-#endif
- switch (phase) {
- case PHASE_CMDOUT:
- /* send packet command */
-#ifdef ATAPI_DEBUG_WDC
- printf("PHASE_CMDOUT\n");
-#endif
-
-#ifdef ATAPI_DEBUG_WDC
- {
- int i;
- char *c = (char *)acp->command;
-
- printf("wdc_atapi_intr: cmd ");
- for (i = 0; i < acp->command_size; i++)
- printf("0x%x ", c[i]);
- printf("\n");
- }
-#endif
-
- wdc->sc_flags |= WDCF_IRQ_WAIT;
- bus_space_write_raw_multi_2(iot, ioh, wd_data, acp->command,
- acp->command_size);
- return 1;
-
- case PHASE_DATAOUT:
- /* write data */
-#ifdef ATAPI_DEBUG_WDC
- printf("PHASE_DATAOUT\n");
-#endif
- if ((acp->flags & (B_READ|B_WRITE)) != B_WRITE) {
- printf("wdc_atapi_intr: bad data phase\n");
- acp->status = ERROR;
- return 1;
- }
- wdc->sc_flags |= WDCF_IRQ_WAIT;
- if (xfer->c_bcount < len) {
- printf("wdc_atapi_intr: warning: write only "
- "%d of %d requested bytes\n", xfer->c_bcount, len);
- bus_space_write_raw_multi_2(iot, ioh, wd_data,
- xfer->databuf + xfer->c_skip, xfer->c_bcount);
- for (i = xfer->c_bcount; i < len;
- i += sizeof(u_int16_t))
- bus_space_write_2(iot, ioh, wd_data, 0);
- xfer->c_bcount = 0;
- return 1;
- } else {
- bus_space_write_raw_multi_2(iot, ioh, wd_data,
- xfer->databuf + xfer->c_skip, len);
- xfer->c_skip += len;
- xfer->c_bcount -= len;
- return 1;
- }
-
- case PHASE_DATAIN:
- /* Read data */
-#ifdef ATAPI_DEBUG_WDC
- printf("PHASE_DATAIN\n");
-#endif
- if ((acp->flags & (B_READ|B_WRITE)) != B_READ) {
- printf("wdc_atapi_intr: bad data phase\n");
- acp->status = ERROR;
- return 1;
- }
- wdc->sc_flags |= WDCF_IRQ_WAIT;
- if (xfer->c_bcount < len) {
- printf("wdc_atapi_intr: warning: reading only "
- "%d of %d bytes\n", xfer->c_bcount, len);
- bus_space_read_raw_multi_2(iot, ioh, wd_data,
- xfer->databuf + xfer->c_skip, xfer->c_bcount);
- wdcbit_bucket(wdc, len - xfer->c_bcount);
- xfer->c_bcount = 0;
- return 1;
- } else {
- bus_space_read_raw_multi_2(iot, ioh, wd_data,
- xfer->databuf + xfer->c_skip, len);
- xfer->c_skip += len;
- xfer->c_bcount -=len;
- return 1;
- }
-
- case PHASE_ABORTED:
- case PHASE_COMPLETED:
-#ifdef ATAPI_DEBUG_WDC
- printf("PHASE_COMPLETED\n");
-#endif
- if (st & WDCS_ERR) {
- acp->error = bus_space_read_1(iot, ioh, wd_error);
- acp->status = ERROR;
- }
-#ifdef ATAPI_DEBUG_WDC
- if (xfer->c_bcount != 0) {
- printf("wdc_atapi_intr warning: bcount value "
- "is %d after io\n", xfer->c_bcount);
- }
-#endif
- break;
-
- default:
- if (++retries < 500) {
- DELAY(100);
- goto again;
- }
- printf("wdc_atapi_intr: unknown phase %d\n", phase);
- acp->status = ERROR;
- }
-
- wdc_atapi_done(wdc, xfer);
- return (0);
-}
-
-
-void
-wdc_atapi_done(wdc, xfer)
- struct wdc_softc *wdc;
- struct wdc_xfer *xfer;
-{
- struct atapi_command_packet *acp = xfer->atapi_cmd;
- int s;
-
- acp->data_size = xfer->c_bcount;
-
- s = splbio();
-
- /* remove this command from xfer queue */
- xfer->c_skip = 0;
- if ((xfer->c_flags & A_POLLED) == 0) {
- untimeout(wdctimeout, wdc);
- TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
- wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
- wdc_free_xfer(xfer);
-#ifdef ATAPI_DEBUG
- printf("wdc_atapi_done: atapi_done\n");
-#endif
- atapi_done(acp);
-#ifdef WDDEBUG
- printf("wdcstart from wdc_atapi_intr, flags %d\n",
- wdc->sc_flags);
-#endif
- wdcstart(wdc);
- } else
- wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
-
- splx(s);
-}
-#endif /* NATAPIBUS */
-
-/*
- * Interrupt routine for the controller. Acknowledge the interrupt, check for
- * errors on the current operation, mark it done if necessary, and start the
- * next request. Also check for a partially done transfer, and continue with
- * the next chunk if so.
- */
-int
-wdcintr(arg)
- void *arg;
-{
- struct wdc_softc *wdc = arg;
- struct wdc_xfer *xfer;
-
- /*
- * It appears that some drives are causing the controller to
- * interrupt too quickly. It also appears that such drives do not
- * conform to the MMC2 specifications. This needs to be fixed
- * correctly and the extra check for NULL removed from the following
- * if().
- */
- if (((wdc->sc_flags & WDCF_IRQ_WAIT) == 0)
- || (wdc->sc_xfer.tqh_first == NULL)) {
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- u_char s;
-#ifdef ATAPI_DEBUG_WDC
- u_char e, i;
-#endif
- DELAY(100);
-
- /* Clear the pending interrupt and abort. */
- s = bus_space_read_1(iot, ioh, wd_status);
- if (s != (WDCS_DRDY|WDCS_DSC)) {
-#ifdef ATAPI_DEBUG_WDC
- e = bus_space_read_1(iot, ioh, wd_error);
- i = bus_space_read_1(iot, ioh, wd_seccnt);
-
- printf("wdcintr: inactive controller, "
- "punting st=%02x er=%02x irr=%02x\n", s, e, i);
-#else
- bus_space_read_1(iot, ioh, wd_error);
- bus_space_read_1(iot, ioh, wd_seccnt);
-#endif
-
- if (s & WDCS_DRQ) {
- int len = 256 * bus_space_read_1(iot, ioh,
- wd_cyl_hi) +
- bus_space_read_1(iot, ioh, wd_cyl_lo);
-#ifdef ATAPI_DEBUG_WDC
- printf("wdcintr: clearing up %d bytes\n", len);
-#endif
- wdcbit_bucket(wdc, len);
- }
- }
- return 0;
- }
-
- WDDEBUG_PRINT(("wdcintr\n"));
-
- wdc->sc_flags &= ~WDCF_IRQ_WAIT;
- xfer = wdc->sc_xfer.tqh_first;
- if (xfer == NULL) {
-#ifdef ATAPI_DEBUG
- printf("wdcintr: null xfer\n");
-#endif
- return 0;
- }
-#if NATAPIBUS > 0 && NWD > 0
- if (xfer->c_flags & C_ATAPI) {
- (void)wdc_atapi_intr(wdc, xfer);
- return 0;
- } else
- return wdc_ata_intr(wdc, xfer);
-#else
-#if NATAPIBUS > 0
- (void)wdc_atapi_intr(wdc, xfer);
- return 0;
-#endif /* NATAPIBUS */
-#if NWD > 0
- return wdc_ata_intr(wdc, xfer);
-#endif /* NWD */
-#endif /* NATAPIBUS && NWD */
-}
-
-int
-wdcreset(wdc, mode)
- struct wdc_softc *wdc;
- enum wdcreset_mode mode;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- bus_space_handle_t ioh_ctl = wdc->sc_ioh_ctl;
-
- /* Reset the device. */
- bus_space_write_1(iot, ioh_ctl, wd_ctlr, WDCTL_RST|WDCTL_IDS);
- delay(1000);
- bus_space_write_1(iot, ioh_ctl, wd_ctlr, WDCTL_IDS);
- delay(1000);
- (void) bus_space_read_1(iot, ioh, wd_error);
- bus_space_write_1(iot, ioh_ctl, wd_ctlr, WDCTL_4BIT);
-
- if (wait_for_unbusy(wdc) < 0) {
- if (mode != WDCRESET_SILENT)
- printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
- return 1;
- }
-
- return 0;
-}
-
-void
-wdcrestart(arg)
- void *arg;
-{
- struct wdc_softc *wdc = arg;
- int s;
-
- s = splbio();
- wdcstart(wdc);
- splx(s);
-}
-
-/*
- * Unwedge the controller after an unexpected error. We do this by resetting
- * it, marking all drives for recalibration, and stalling the queue for a short
- * period to give the reset time to finish.
- * NOTE: We use a timeout here, so this routine must not be called during
- * autoconfig or dump.
- */
-void
-wdcunwedge(wdc)
- struct wdc_softc *wdc;
-{
- int unit;
-
-#ifdef ATAPI_DEBUG
- printf("wdcunwedge\n");
-#endif
-
- untimeout(wdctimeout, wdc);
- wdc->sc_flags &= ~WDCF_IRQ_WAIT;
- (void) wdcreset(wdc, WDCRESET_VERBOSE);
-
- /* Schedule recalibrate for all drives on this controller. */
- for (unit = 0; unit < 2; unit++) {
- if (!wdc->d_link[unit]) continue;
- if (wdc->d_link[unit]->sc_state > RECAL)
- wdc->d_link[unit]->sc_state = RECAL;
- }
-
- wdc->sc_flags |= WDCF_ERROR;
-
- /* Wake up in a little bit and restart the operation. */
- WDDEBUG_PRINT(("wdcrestart from wdcunwedge\n"));
- wdc->sc_flags &= ~WDCF_ACTIVE;
- timeout(wdcrestart, wdc, RECOVERYTIME);
-}
-
-int
-wdcwait(wdc, mask)
- struct wdc_softc *wdc;
- int mask;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- int timeout = 0;
- u_char status;
-#ifdef WDCNDELAY_DEBUG
- extern int cold;
-#endif
-
- WDDEBUG_PRINT(("wdcwait\n"));
-
- for (;;) {
- wdc->sc_status = status = bus_space_read_1(iot, ioh,
- wd_status);
- /*
- * If a single slave ATAPI device is attached, it may
- * have released the bus. Select it and try again.
- */
- if (status == 0xff && wdc->sc_flags & WDCF_ONESLAVE) {
- bus_space_write_1(iot, ioh, wd_sdh,
- WDSD_IBM | 0x10);
- wdc->sc_status = status = bus_space_read_1(iot, ioh,
- wd_status);
- }
- if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
- break;
- if (++timeout > WDCNDELAY) {
-#ifdef ATAPI_DEBUG2
- printf("wdcwait: timeout, status 0x%x\n", status);
-#endif
- return -1;
- }
- delay(WDCDELAY);
- }
- if (status & WDCS_ERR) {
- wdc->sc_error = bus_space_read_1(iot, ioh, wd_error);
- return WDCS_ERR;
- }
-#ifdef WDCNDELAY_DEBUG
- /* After autoconfig, there should be no long delays. */
- if (!cold && timeout > WDCNDELAY_DEBUG) {
- struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
- if (xfer == NULL)
- printf("%s: warning: busy-wait took %dus\n",
- wdc->sc_dev.dv_xname, WDCDELAY * timeout);
- else
- printf("%s(%s): warning: busy-wait took %dus\n",
- wdc->sc_dev.dv_xname,
- ((struct device*)xfer->d_link->wd_softc)->dv_xname,
- WDCDELAY * timeout);
- }
-#endif
- return 0;
-}
-
-void
-wdctimeout(arg)
- void *arg;
-{
- struct wdc_softc *wdc = (struct wdc_softc *)arg;
- int s;
-
- WDDEBUG_PRINT(("wdctimeout\n"));
-
- s = splbio();
- if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0) {
- wdc->sc_flags &= ~WDCF_IRQ_WAIT;
- wdcerror(wdc, "lost interrupt");
- wdcunwedge(wdc);
- } else
- wdcerror(wdc, "missing untimeout");
- splx(s);
-}
-
-/*
- * Wait for the drive to become ready and send a command.
- * Return -1 if busy for too long or 0 otherwise.
- * Assumes interrupts are blocked.
- */
-int
-wdccommand(d_link, command, drive, cylin, head, sector, count)
- struct wd_link *d_link;
- int command;
- int drive, cylin, head, sector, count;
-{
- struct wdc_softc *wdc = (void*)d_link->wdc_softc;
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- int stat;
-
- WDDEBUG_PRINT(("wdccommand drive %d\n", drive));
-
-#if defined(DIAGNOSTIC) && defined(WDCDEBUG)
- if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
- printf("wdccommand: controler not active (drive %d)\n", drive);
-#endif
-
- /* Select drive, head, and addressing mode. */
- bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | (drive << 4) | head);
-
- /* Wait for it to become ready to accept a command. */
- if (command == WDCC_IDP || d_link->type == BUS)
- stat = wait_for_unbusy(wdc);
- else
- stat = wdcwait(wdc, WDCS_DRDY);
-
- if (stat < 0) {
-#ifdef ATAPI_DEBUG
- printf("wdcommand: xfer failed (wait_for_unbusy) status %d\n",
- stat);
-#endif
- return -1;
- }
-
- /* Load parameters. */
- if (d_link->type == DRIVE && d_link->sc_lp->d_type == DTYPE_ST506)
- bus_space_write_1(iot, ioh, wd_precomp,
- d_link->sc_lp->d_precompcyl / 4);
- else
- bus_space_write_1(iot, ioh, wd_features, 0);
- bus_space_write_1(iot, ioh, wd_cyl_lo, cylin);
- bus_space_write_1(iot, ioh, wd_cyl_hi, cylin >> 8);
- bus_space_write_1(iot, ioh, wd_sector, sector);
- bus_space_write_1(iot, ioh, wd_seccnt, count);
-
- /* Send command. */
- bus_space_write_1(iot, ioh, wd_command, command);
-
- return 0;
-}
-
-/*
- * Simplified version of wdccommand().
- */
-int
-wdccommandshort(wdc, drive, command)
- struct wdc_softc *wdc;
- int drive;
- int command;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
-
- WDDEBUG_PRINT(("wdccommandshort\n"));
-
-#if defined(DIAGNOSTIC) && defined(WDCDEBUG)
- if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
- printf("wdccommandshort: controller not active (drive %d)\n",
- drive);
-#endif
-
- /* Select drive. */
- bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM|(drive << 4));
-
- if (wdcwait(wdc, WDCS_DRDY) < 0)
- return -1;
-
- bus_space_write_1(iot, ioh, wd_command, command);
-
- return 0;
-}
-
-void
-wdc_exec_xfer(d_link, xfer)
- struct wd_link *d_link;
- struct wdc_xfer *xfer;
-{
- struct wdc_softc *wdc = (struct wdc_softc *)d_link->wdc_softc;
- int s;
-
- WDDEBUG_PRINT(("wdc_exec_xfer\n"));
-
- s = splbio();
-
- /* insert at the end of command list */
- TAILQ_INSERT_TAIL(&wdc->sc_xfer,xfer , c_xferchain);
- WDDEBUG_PRINT(("wdcstart from wdc_exec_xfer, flags %d\n",
- wdc->sc_flags));
- wdcstart(wdc);
- splx(s);
-}
-
-struct wdc_xfer *
-wdc_get_xfer(c_link,flags)
- struct wdc_link *c_link;
- int flags;
-{
- struct wdc_xfer *xfer;
- int s;
-
- s = splbio();
- if ((xfer = xfer_free_list.lh_first) != NULL) {
- LIST_REMOVE(xfer, free_list);
- splx(s);
-#ifdef DIAGNOSTIC
- if ((xfer->c_flags & C_INUSE) != 0)
- panic("wdc_get_xfer: xfer already in use");
-#endif
- } else {
- splx(s);
-#ifdef ATAPI_DEBUG
- printf("wdc:making xfer %d\n",wdc_nxfer);
-#endif
- xfer = malloc(sizeof(*xfer), M_DEVBUF,
- ((flags & IDE_NOSLEEP) != 0 ? M_NOWAIT : M_WAITOK));
- if (xfer == NULL)
- return 0;
-
-#ifdef DIAGNOSTIC
- xfer->c_flags &= ~C_INUSE;
-#endif
-#ifdef ATAPI_DEBUG
- wdc_nxfer++;
-#endif
- }
-#ifdef DIAGNOSTIC
- if ((xfer->c_flags & C_INUSE) != 0)
- panic("wdc_get_xfer: xfer already in use");
-#endif
- bzero(xfer, sizeof(struct wdc_xfer));
- xfer->c_flags = C_INUSE;
- xfer->c_link = c_link;
- return xfer;
-}
-
-void
-wdc_free_xfer(xfer)
- struct wdc_xfer *xfer;
-{
- int s;
-
- s = splbio();
- xfer->c_flags &= ~C_INUSE;
- LIST_INSERT_HEAD(&xfer_free_list, xfer, free_list);
- splx(s);
-}
-
-void
-wdcerror(wdc, msg)
- struct wdc_softc *wdc;
- char *msg;
-{
- struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
- if (xfer == NULL)
- printf("%s: %s\n", wdc->sc_dev.dv_xname, msg);
- else
- printf("%s(%s): %s\n", wdc->sc_dev.dv_xname,
- ((struct device*)xfer->d_link->wd_softc)->dv_xname, msg);
-}
-
-/*
- * the bit bucket
- */
-void
-wdcbit_bucket(wdc, size)
- struct wdc_softc *wdc;
- int size;
-{
- bus_space_tag_t iot = wdc->sc_iot;
- bus_space_handle_t ioh = wdc->sc_ioh;
- int i;
-
- for (i = 0 ; i < size / 2 ; i++) {
- u_int16_t null;
-
- bus_space_read_multi_2(iot, ioh, wd_data, &null, 1);
- }
-
- if (size % 2)
- bus_space_read_1(iot, ioh, wd_data);
-}
diff --git a/sys/dev/isa/wdlink.h b/sys/dev/isa/wdlink.h
deleted file mode 100644
index 7f69a2d5cf9..00000000000
--- a/sys/dev/isa/wdlink.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/* $OpenBSD: wdlink.h,v 1.10 1998/08/08 23:01:11 downsj Exp $ */
-
-/*
- * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
- *
- * DMA and multi-sector PIO handling are derived from code contributed by
- * Onno van der Linden.
- *
- * Atapi support added by Manuel Bouyer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Charles M. Hannum.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
- */
-
-/* #undef WDDEBUG */
-/* #undef DIAGNOSTIC */
-
-#include "wd.h"
-
-struct wdc_link {
- int flags;
- int openings;
-};
-
-struct wdc_softc {
- struct device sc_dev;
- void *sc_ih;
- struct wd_link *d_link[2];
- struct bus_link *ab_link;
- struct wdc_link ctlr_link;
- bus_space_tag_t sc_iot;
- bus_space_handle_t sc_ioh;
- bus_space_handle_t sc_ioh_ctl;
- int sc_drq; /* DMA channel */
-
- TAILQ_HEAD(xferhead, wdc_xfer) sc_xfer;
- int sc_flags;
-#define WDCF_ACTIVE 0x01 /* controller is active */
-#define WDCF_SINGLE 0x02 /* sector at a time mode */
-#define WDCF_ERROR 0x04 /* processing a disk error */
-#define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */
-#define WDCF_IRQ_WAIT 0x10 /* controller is waiting for irq */
-#define WDCF_ONESLAVE 0x20 /* ctrl. has one ATAPI slave attached */
-#define WDCF_BROKENPOLL 0x40 /* or, generally fucked up */
- u_char sc_status; /* copy of status register */
- u_char sc_error; /* copy of error register */
-};
-
-struct wd_link {
- u_char type;
-#define DRIVE 0
-#define BUS 1
- caddr_t wdc_softc;
- caddr_t wd_softc;
- struct wdc_link *ctlr_link;
- struct wdparams sc_params;
-
- /* Long-term state: */
- u_int8_t openings;
- int sc_drive; /* physical unit number */
- int sc_state; /* control state */
-#define RECAL 0 /* recalibrate */
-#define RECAL_WAIT 1 /* done recalibrating */
-#define GEOMETRY 2 /* upload geometry */
-#define GEOMETRY_WAIT 3 /* done uploading geometry */
-#define MULTIMODE 4 /* set multiple mode */
-#define MULTIMODE_WAIT 5 /* done setting multiple mode */
-#define READY 6 /* done with open */
- int sc_mode; /* transfer mode */
-#define WDM_PIOSINGLE 0 /* single-sector PIO */
-#define WDM_PIOMULTI 1 /* multi-sector PIO */
-#define WDM_DMA 2 /* DMA */
- int sc_multiple; /* multiple for WDM_PIOMULTI */
- int sc_flags; /* drive characteistics found */
-#define WDF_LOCKED 0x01
-#define WDF_WANTED 0x02
-#define WDF_WLABEL 0x04 /* label is writable */
-#define WDF_LABELLING 0x08 /* writing label */
-
-/*
- * XXX Nothing resets this yet, but disk change sensing will when ATAPI is
- * implemented.
- */
-#define WDF_LOADED 0x10 /* parameters loaded */
-#define WDF_32BIT 0x20 /* can do 32-bit transfer */
-#define WDF_WAIT 0x40 /* waiting for resourses */
-
- daddr_t sc_badsect[127]; /* 126 plus trailing -1 marker */
- struct disklabel *sc_lp; /* label info for this disk */
-};
-
-struct wdc_xfer {
- struct wdc_link *c_link; /* controller structure info */
- struct wd_link *d_link; /* drive/bus structure info */
- volatile int c_flags; /* handle also B_READ and B_WRITE */
-#define C_INUSE 0x01
-#define C_ATAPI 0x02
-#define C_ERROR 0x04
-
- /* Information about the current transfer */
- struct buf *c_bp;
- void *atapi_cmd;
- void *databuf;
- daddr_t c_blkno; /* starting block number */
- int c_bcount; /* byte count left */
- int c_skip; /* bytes already transferred */
- int c_nblks; /* number of blocks currently transferring */
- int c_nbytes; /* number of bytes currently transferring */
- u_int32_t c_p_offset; /* offset of the partition */
- int c_errors; /* errors during current transfer */
- TAILQ_ENTRY(wdc_xfer) c_xferchain;
- LIST_ENTRY(wdc_xfer) free_list;
-};
-
-void wdc_exec_xfer __P((struct wd_link *, struct wdc_xfer *));
-struct wdc_xfer *wdc_get_xfer __P((struct wdc_link *, int));
-int wdc_get_parms __P((struct wd_link *));
-int wdccommandshort __P((struct wdc_softc *, int, int));
-int wdcwait __P((struct wdc_softc *, int));
-int wdccommand __P((struct wd_link *, int, int, int, int, int, int));
-
-#if NWD > 0
-void wderror __P((struct wd_link* , struct buf *, char *));
-int wdsetctlr __P((struct wd_link *));
-void wdstart __P((void *));
-void wddone __P((struct wd_link*, struct buf*));
-#endif /* NWD */
-
-/*
- * ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
- * command is aborted.
- */
-#define wait_for_drq(d) wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
-#define wait_for_unbusy(d) wdcwait(d, 0)
-#define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
-#define atapi_ready(d) wdcwait(d, WDCS_DRQ)
-
-#define IDE_NOSLEEP 0x01
diff --git a/sys/dev/isa/wdreg.h b/sys/dev/isa/wdreg.h
deleted file mode 100644
index 9def532b136..00000000000
--- a/sys/dev/isa/wdreg.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/* $OpenBSD: wdreg.h,v 1.8 1998/08/08 23:01:12 downsj Exp $ */
-/* $NetBSD: wdreg.h,v 1.13 1995/03/29 21:56:46 briggs Exp $ */
-
-/*-
- * Copyright (c) 1991 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)wdreg.h 7.1 (Berkeley) 5/9/91
- */
-
-/*
- * Disk Controller register definitions.
- */
-#define wd_data 0x000 /* data register (R/W - 16 bits) */
-#define wd_error 0x001 /* error register (R) */
-#define wd_precomp 0x001 /* write precompensation (W) */
-#define wd_features 0x001 /* features (W) */
-#define wd_seccnt 0x002 /* sector count (R/W) */
-#define wd_ireason 0x002 /* interrupt reason (R/W) (for atapi) */
-#define wd_sector 0x003 /* first sector number (R/W) */
-#define wd_cyl_lo 0x004 /* cylinder address, low byte (R/W) */
-#define wd_cyl_hi 0x005 /* cylinder address, high byte (R/W) */
-#define wd_sdh 0x006 /* sector size/drive/head (R/W) */
-#define wd_command 0x007 /* command register (W) */
-#define wd_status 0x007 /* immediate status (R) */
-
-/*
- * Control register definiations.
- */
-#define WDCTL_OFFSET 0x206 /* offset from the first set. */
-
-#define wd_altsts 0x000 /* alternate fixed disk status (via 1015) (R) */
-#define wd_ctlr 0x000 /* fixed disk controller control (via 1015) (W) */
-#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */
-#define WDCTL_RST 0x04 /* reset the controller */
-#define WDCTL_IDS 0x02 /* disable controller interrupts */
-#if 0
-#define wd_digin 0x001 /* disk controller input (via 1015) (R) */
-#endif
-
-/*
- * Status bits.
- */
-#define WDCS_BSY 0x80 /* busy */
-#define WDCS_DRDY 0x40 /* drive ready */
-#define WDCS_DWF 0x20 /* drive write fault */
-#define WDCS_DSC 0x10 /* drive seek complete */
-#define WDCS_DRQ 0x08 /* data request */
-#define WDCS_CORR 0x04 /* corrected data */
-#define WDCS_IDX 0x02 /* index */
-#define WDCS_ERR 0x01 /* error */
-#define WDCS_BITS "\020\010bsy\007drdy\006dwf\005dsc\004drq\003corr\002idx\001err"
-
-/*
- * Error bits.
- */
-#define WDCE_BBK 0x80 /* bad block detected */
-#define WDCE_UNC 0x40 /* uncorrectable data error */
-#define WDCE_MC 0x20 /* media changed */
-#define WDCE_IDNF 0x10 /* id not found */
-#define WDCE_ABRT 0x08 /* aborted command */
-#define WDCE_MCR 0x04 /* media change requested */
-#define WDCE_TK0NF 0x02 /* track 0 not found */
-#define WDCE_AMNF 0x01 /* address mark not found */
-#define WDERR_BITS "\020\010bbk\007unc\006mc\005idnf\004mcr\003abrt\002tk0nf\001amnf"
-
-/*
- * Commands for Disk Controller.
- */
-#define WDCC_RECAL 0x10 /* disk restore code -- resets cntlr */
-
-#define WDCC_READ 0x20 /* disk read code */
-#define WDCC_WRITE 0x30 /* disk write code */
-#define WDCC__LONG 0x02 /* modifier -- access ecc bytes */
-#define WDCC__NORETRY 0x01 /* modifier -- no retrys */
-
-#define WDCC_FORMAT 0x50 /* disk format code */
-#define WDCC_DIAGNOSE 0x90 /* controller diagnostic */
-#define WDCC_IDP 0x91 /* initialize drive parameters */
-
-#define WDCC_READMULTI 0xc4 /* read multiple */
-#define WDCC_WRITEMULTI 0xc5 /* write multiple */
-#define WDCC_SETMULTI 0xc6 /* set multiple mode */
-
-#define WDCC_READDMA 0xc8 /* read with DMA */
-#define WDCC_WRITEDMA 0xca /* write with DMA */
-
-#define WDCC_ACKMC 0xdb /* acknowledge media change */
-#define WDCC_LOCK 0xde /* lock drawer */
-#define WDCC_UNLOCK 0xdf /* unlock drawer */
-
-#define WDCC_IDENTIFY 0xec /* read parameters from controller */
-#define WDCC_CACHEC 0xef /* cache control */
-
-#define WDSD_IBM 0xa0 /* forced to 512 byte sector, ecc */
-#define WDSD_CHS 0x00 /* cylinder/head/sector addressing */
-#define WDSD_LBA 0x40 /* logical block addressing */
-
-/* Commands for ATAPI devices */
-#define ATAPI_CHECK_POWER_MODE 0xe5
-#define ATAPI_EXEC_DRIVE_DIAGS 0x90
-#define ATAPI_IDLE_IMMEDIATE 0xe1
-#define ATAPI_NOP 0x00
-#define ATAPI_PACKET_COMMAND 0xa0
-#define ATAPI_IDENTIFY_DEVICE 0xa1
-#define ATAPI_SOFT_RESET 0x08
-#define ATAPI_SET_FEATURES 0xef
-#define ATAPI_SLEEP 0xe6
-#define ATAPI_STANDBY_IMMEDIATE 0xe0
-
-/* ireason */
-#define WDCI_CMD 0x01 /* command(1) or data(0) */
-#define WDCI_IN 0x02 /* transfer to(1) or from(0) the host */
-#define WDCI_RELEASE 0x04 /* bus released until completion */
-
-#define PHASE_CMDOUT (WDCS_DRQ | WDCI_CMD)
-#define PHASE_DATAIN (WDCS_DRQ | WDCI_IN)
-#define PHASE_DATAOUT WDCS_DRQ
-#define PHASE_COMPLETED (WDCI_IN | WDCI_CMD)
-#define PHASE_ABORTED 0
-
-
-#if defined(_KERNEL) && !defined(_LOCORE)
-/*
- * read parameters command returns this:
- */
-struct wdparams {
- u_int16_t wdp_config; /* general configuration */
-#define WD_CFG_REMOVABLE 0x0080
-#define WD_CFG_FIXED 0x0040
- u_int16_t wdp_cylinders; /* number of non-removable cylinders */
- u_int8_t __reserved1[2];
- u_int16_t wdp_heads; /* number of heads */
- u_int16_t wdp_unfbytespertrk; /* number of unformatted bytes/track */
- u_int16_t wdp_unfbytespersec; /* number of unformatted bytes/sector */
- u_int16_t wdp_sectors; /* number of sectors */
- u_int8_t wdp_vendor1[6];
- u_int8_t wdp_serial[20]; /* serial number */
- u_int16_t wdp_buftype; /* buffer type */
-#define WD_BUF_SINGLEPORTSECTOR 1 /* single port, single sector buffer */
-#define WD_BUF_DUALPORTMULTI 2 /* dual port, multiple sector buffer */
-#define WD_BUF_DUALPORTMULTICACHE 3 /* above plus track cache */
- u_int16_t wdp_bufsize; /* buffer size, in 512-byte units */
- u_int16_t wdp_eccbytes; /* ecc bytes appended */
- u_int8_t wdp_revision[8]; /* firmware revision */
- u_int8_t wdp_model[40]; /* model name */
- u_int8_t wdp_maxmulti; /* maximum sectors per interrupt */
- u_int8_t wdp_vendor2[1];
- u_int16_t wdp_usedmovsd; /* can use double word read/write? */
- u_int8_t wdp_vendor3[1];
- u_int8_t wdp_capabilities; /* capability flags */
-#define WD_CAP_DMA 0x01
-#define WD_CAP_LBA 0x02
-#define WD_CAP_IORDYSW 0x04
-#define WD_CAP_IODRYSUP 0x08
- u_int8_t __reserved2[2];
- u_int8_t wdp_vendor4[1];
- u_int8_t wdp_piotiming; /* PIO timing mode */
- u_int8_t wdp_vendor5[1];
- u_int8_t wdp_dmatiming; /* DMA timing mode */
- u_int16_t wdp_capvalid; /* valid capabilities */
- u_int16_t wdp_curcyls; /* logical cylinders */
- u_int16_t wdp_curheads; /* logical heads */
- u_int16_t wdp_cursectors; /* logical sectors per track */
- u_int32_t wdp_curcapacity; /* logical total sectors on drive */
- u_int8_t wdp_curmulti; /* current multiple sector count */
- u_int8_t wdp_valmulti; /* multiple sector is valid */
-#define WD_CAP_MULTI 0x01
- u_int32_t wdp_lbacapacity; /* total number of sectors */
- u_int16_t wdp_dma1word; /* single-word dma info */
- u_int16_t wdp_dmamword; /* multiple-word dma info */
- u_int16_t wdp_eidepiomode; /* EIDE PIO mode */
-#define WD_CAP_PIO3 0x01
-#define WD_CAP_PIO4 0x02
- u_int16_t wdp_eidedmamin; /* min mword dma cycle time (ns) */
- u_int16_t wdp_eidedmatime; /* rec'd mword dma cycle time (ns) */
- u_int16_t wdp_eidepiotime; /* min cycle time (ns), no IORDY */
- u_int16_t wdp_eidepioiordy; /* min cycle time (ns), with IORDY */
-};
-#endif /* _KERNEL && !_LOCORE*/