summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files.i3864
-rw-r--r--sys/i386/conf/files.i3864
-rw-r--r--sys/i386/isa/wd.c125
-rw-r--r--sys/i386/isa/wdreg.h104
-rw-r--r--sys/pci/ide_pci.c817
-rw-r--r--sys/pci/ide_pcireg.h63
-rw-r--r--sys/pci/pcisupport.c11
7 files changed, 1111 insertions, 17 deletions
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index fe46c28..8a79192 100644
--- a/sys/conf/files.i386
+++ b/sys/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.167 1997/07/24 23:45:17 fsmp Exp $
+# $Id: files.i386,v 1.168 1997/07/25 11:53:20 phk Exp $
#
aic7xxx_asm optional ahc device-driver \
dependency "$S/dev/aic7xxx/*.[chyl]" \
@@ -293,4 +293,4 @@ gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate
gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate
gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate
gnu/i386/isa/dgb.c optional dgb device-driver
-pci/wd82371.c optional wd device-driver
+pci/ide_pci.c optional wd device-driver
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index fe46c28..8a79192 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.167 1997/07/24 23:45:17 fsmp Exp $
+# $Id: files.i386,v 1.168 1997/07/25 11:53:20 phk Exp $
#
aic7xxx_asm optional ahc device-driver \
dependency "$S/dev/aic7xxx/*.[chyl]" \
@@ -293,4 +293,4 @@ gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate
gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate
gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate
gnu/i386/isa/dgb.c optional dgb device-driver
-pci/wd82371.c optional wd device-driver
+pci/ide_pci.c optional wd device-driver
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index 09beae0..09231ad 100644
--- a/sys/i386/isa/wd.c
+++ b/sys/i386/isa/wd.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
- * $Id: wd.c,v 1.131 1997/07/01 00:22:45 bde Exp $
+ * $Id: wd.c,v 1.132 1997/07/20 14:10:17 bde Exp $
*/
/* TODO:
@@ -110,6 +110,7 @@ extern void wdstart(int ctrlr);
/* can't handle that in all cases */
#define WDOPT_32BIT 0x8000
#define WDOPT_SLEEPHACK 0x4000
+#define WDOPT_DMA 0x2000
#define WDOPT_FORCEHD(x) (((x)&0x0f00)>>8)
#define WDOPT_MULTIMASK 0x00ff
@@ -173,12 +174,17 @@ struct disk {
#define DKFL_32BIT 0x00100 /* use 32-bit i/o mode */
#define DKFL_MULTI 0x00200 /* use multi-i/o mode */
#define DKFL_BADSCAN 0x00400 /* report all errors */
+#define DKFL_USEDMA 0x00800 /* use DMA for data transfers */
+#define DKFL_DMA 0x01000 /* using DMA on this transfer-- DKFL_SINGLE
+ * overrides this
+ */
struct wdparams dk_params; /* ESDI/IDE drive/controller parameters */
int dk_dkunit; /* disk stats unit number */
int dk_multi; /* multi transfers */
int dk_currentiosize; /* current io size */
struct diskgeom dk_dd; /* device configuration data */
struct diskslices *dk_slices; /* virtual drives */
+ void *dk_dmacookie; /* handle for DMA services */
};
#define WD_COUNT_RETRIES
@@ -215,6 +221,7 @@ static int wdsetctlr(struct disk *du);
#if 0
static int wdwsetctlr(struct disk *du);
#endif
+static int wdsetmode(int mode, void *wdinfo);
static int wdgetctlr(struct disk *du);
static void wderror(struct buf *bp, struct disk *du, char *mesg);
static void wdflushirq(struct disk *du, int old_ipl);
@@ -381,6 +388,7 @@ wdattach(struct isa_device *dvp)
int unit, lunit;
struct isa_device *wdup;
struct disk *du;
+ struct wdparams *wp;
if (dvp->id_unit >= NWDC)
return (0);
@@ -443,6 +451,8 @@ wdattach(struct isa_device *dvp)
dvp->id_unit, unit, lunit,
sizeof du->dk_params.wdp_model,
du->dk_params.wdp_model);
+ if (du->dk_flags & DKFL_USEDMA)
+ printf(", DMA");
if (du->dk_flags & DKFL_32BIT)
printf(", 32-bit");
if (du->dk_multi > 1)
@@ -465,6 +475,17 @@ wdattach(struct isa_device *dvp)
du->dk_dd.d_nsectors,
du->dk_dd.d_secsize);
+ if (bootverbose) {
+ wp = &du->dk_params;
+ printf(
+"wd%d: ATA INQUIRE valid = %04x, dmamword = %04x, apio = %04x, udma = %04x\n",
+ du->dk_lunit,
+ wp->wdp_atavalid,
+ wp->wdp_dmamword,
+ wp->wdp_eidepiomodes,
+ wp->wdp_udmamode);
+ }
+
/*
* Start timeout routine for this drive.
* XXX timeout should be per controller.
@@ -818,7 +839,19 @@ wdstart(int ctrlr)
count = 1;
du->dk_currentiosize = 1;
} else {
- if( (count > 1) && (du->dk_multi > 1)) {
+ if((du->dk_flags & DKFL_USEDMA) &&
+ wddma.wdd_dmaverify(du->dk_dmacookie,
+ (void *)((int)bp->b_un.b_addr +
+ du->dk_skip * DEV_BSIZE),
+ du->dk_bc,
+ bp->b_flags & B_READ)) {
+ du->dk_flags |= DKFL_DMA;
+ if( bp->b_flags & B_READ)
+ command = WDCC_READ_DMA;
+ else
+ command = WDCC_WRITE_DMA;
+ du->dk_currentiosize = count;
+ } else if( (count > 1) && (du->dk_multi > 1)) {
du->dk_flags |= DKFL_MULTI;
if( bp->b_flags & B_READ) {
command = WDCC_READ_MULTI;
@@ -854,6 +887,14 @@ wdstart(int ctrlr)
if(du->dk_dkunit >= 0) {
dk_busy |= 1 << du->dk_dkunit;
}
+
+ if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) {
+ wddma.wdd_dmaprep(du->dk_dmacookie,
+ (void *)((int)bp->b_un.b_addr +
+ du->dk_skip * DEV_BSIZE),
+ du->dk_bc,
+ bp->b_flags & B_READ);
+ }
while (wdcommand(du, cylin, head, sector, count, command)
!= 0) {
wderror(bp, du,
@@ -884,6 +925,12 @@ wdstart(int ctrlr)
*/
du->dk_timeout = 1 + 3;
+ /* if this is a DMA op, start DMA and go away until it's done. */
+ if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) {
+ wddma.wdd_dmastart(du->dk_dmacookie);
+ return;
+ }
+
/* If this is a read operation, just go away until it's done. */
if (bp->b_flags & B_READ)
return;
@@ -988,6 +1035,15 @@ wdintr(int unit)
du = wddrives[dkunit(bp->b_dev)];
du->dk_timeout = 0;
+ /* finish off DMA. ignore errors if we're not using it. */
+ if (du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) {
+ if ((wddma.wdd_dmadone(du->dk_dmacookie) != WDDS_INTERRUPT) &&
+ !(du->dk_flags & DKFL_USEDMA)) {
+ wderror(bp, du, "wdintr: DMA failure");
+ du->dk_status |= WDCS_ERR; /* XXX totally bogus err */
+ }
+ }
+
if (wdwait(du, 0, TIMEOUT) < 0) {
wderror(bp, du, "wdintr: timeout waiting for status");
du->dk_status |= WDCS_ERR; /* XXX */
@@ -1014,7 +1070,12 @@ oops:
* XXX bogus inb() here, register 0 is assumed and intr status
* is reset.
*/
- if( (du->dk_flags & DKFL_MULTI) && (inb(du->dk_port) & WDERR_ABORT)) {
+ if((du->dk_flags & DKFL_DMA ) &&
+ (inb(du->dk_port) & WDERR_ABORT)) {
+ wderror(bp, du, "reverting to PIO mode");
+ du->dk_flags |= ~DKFL_USEDMA;
+ } else if((du->dk_flags & DKFL_MULTI) &&
+ (inb(du->dk_port) & WDERR_ABORT)) {
wderror(bp, du, "reverting to non-multi sector mode");
du->dk_multi = 1;
}
@@ -1052,6 +1113,7 @@ oops:
* If this was a successful read operation, fetch the data.
*/
if (((bp->b_flags & (B_READ | B_ERROR)) == B_READ)
+ && !(du->dk_flags & DKFL_DMA)
&& wdtab[unit].b_active) {
int chk, dummy, multisize;
multisize = chk = du->dk_currentiosize * DEV_BSIZE;
@@ -1093,6 +1155,20 @@ oops:
dk_wds[du->dk_dkunit] += chk >> 6;
}
+ /* final cleanup on DMA */
+ if (((bp->b_flags & B_ERROR) == 0)
+ && (du->dk_flags & DKFL_DMA)
+ && wdtab[unit].b_active) {
+ int iosize;
+
+ iosize = du->dk_currentiosize * DEV_BSIZE;
+
+ du->dk_bc -= iosize;
+
+ if (du->dk_dkunit >= 0)
+ dk_wds[du->dk_dkunit] += iosize >> 6;
+ }
+
outt:
if (wdtab[unit].b_active) {
if ((bp->b_flags & B_ERROR) == 0) {
@@ -1124,7 +1200,7 @@ outt:
done: ;
/* done with this transfer, with or without error */
- du->dk_flags &= ~DKFL_SINGLE;
+ du->dk_flags &= ~(DKFL_SINGLE|DKFL_DMA);
TAILQ_REMOVE(&wdtab[unit].controller_queue, bp, b_act);
wdtab[unit].b_errcnt = 0;
bp->b_resid = bp->b_bcount - du->dk_skip * DEV_BSIZE;
@@ -1441,7 +1517,7 @@ wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector,
outb(wdc + wd_sector, sector + 1);
outb(wdc + wd_seccnt, count);
}
- if (wdwait(du, command == WDCC_DIAGNOSE || command == WDCC_IDC
+ if (wdwait(du, (command == WDCC_DIAGNOSE || command == WDCC_IDC)
? 0 : WDCS_READY, TIMEOUT) < 0)
return (1);
outb(wdc + wd_command, command);
@@ -1557,6 +1633,25 @@ wdwsetctlr(struct disk *du)
#endif
/*
+ * gross little callback function for wdddma interface. returns 1 for
+ * success, 0 for failure.
+ */
+static int
+wdsetmode(int mode, void *wdinfo)
+{
+ int i;
+ struct disk *du;
+
+ du = wdinfo;
+ if (bootverbose)
+ printf("wdsetmode() setting transfer mode to %02x\n", mode);
+ i = wdcommand(du, 0, 0, mode, WDFEA_SETXFER,
+ WDCC_FEATURES) == 0 &&
+ wdwait(du, WDCS_READY, TIMEOUT) == 0;
+ return i;
+}
+
+/*
* issue READP to drive to ask it what it is.
*/
static int
@@ -1711,6 +1806,21 @@ failed:
du->dk_multi = wp->wdp_nsecperint & 0xff;
wdsetmulti(du);
+ du->dk_dmacookie = NULL;
+ /*
+ * check drive's DMA capability
+ */
+ /* does user want this? */
+ if ((du->cfg_flags & WDOPT_DMA) &&
+ /* have we got a DMA controller? */
+ (wddma.wdd_candma &&
+ (du->dk_dmacookie = wddma.wdd_candma(du->dk_port,
+ du->dk_unit))) &&
+ /* can said drive do DMA? */
+ (wddma.wdd_dmainit(du->dk_dmacookie, wp, wdsetmode, du)))
+
+ du->dk_flags |= DKFL_USEDMA;
+
#ifdef WDDEBUG
printf(
"\nwd(%d,%d): wdgetctlr: gc %x cyl %d trk %d sec %d type %d sz %d model %s\n",
@@ -2061,6 +2171,9 @@ wdreset(struct disk *du)
{
int wdc, err = 0;
+ if ((du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) && du->dk_dmacookie)
+ wddma.wdd_dmadone(du->dk_dmacookie);
+
wdc = du->dk_port;
(void)wdwait(du, 0, TIMEOUT);
outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST);
@@ -2112,7 +2225,7 @@ wdtimeout(void *cdu)
if(timeouts++ == 5)
wderror((struct buf *)NULL, du,
"Last time I say: interrupt timeout. Probably a portable PC.");
- else if(timeouts++ < 5)
+ else if(timeouts < 5)
wderror((struct buf *)NULL, du, "interrupt timeout");
wdunwedge(du);
wdflushirq(du, x);
diff --git a/sys/i386/isa/wdreg.h b/sys/i386/isa/wdreg.h
index 3ad2403..f7dfa488 100644
--- a/sys/i386/isa/wdreg.h
+++ b/sys/i386/isa/wdreg.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)wdreg.h 7.1 (Berkeley) 5/9/91
- * $Id$
+ * $Id: wdreg.h,v 1.17 1997/02/22 09:37:27 peter Exp $
*/
/*
@@ -122,6 +122,8 @@
#define WDCC_READ_MULTI 0xC4 /* read multiple */
#define WDCC_WRITE_MULTI 0xC5 /* write multiple */
#define WDCC_SET_MULTI 0xC6 /* set multiple count */
+#define WDCC_READ_DMA 0xC8 /* read using DMA */
+#define WDCC_WRITE_DMA 0xCA /* write using DMA */
#define WDCC_EXTDCMD 0xE0 /* send extended command */
@@ -130,6 +132,7 @@
#define WDFEA_RCACHE 0xAA /* read cache enable */
#define WDFEA_WCACHE 0x02 /* write cache enable */
+#define WDFEA_SETXFER 0x03 /* set transfer mode */
#define WD_STEP 0 /* winchester- default 35us step */
@@ -140,10 +143,14 @@
* read parameters command returns this:
*/
struct wdparams {
+ /*
+ * XXX partly based on DRAFT X3T13/1153D rev 14.
+ * by the time you read this it will have changed.
+ */
/* drive info */
short wdp_config; /* general configuration bits */
u_short wdp_cylinders; /* number of cylinders */
- short wdp_reserved;
+ short wdp_reserved2;
u_short wdp_heads; /* number of heads */
short wdp_unfbytespertrk; /* number of unformatted bytes/track */
short wdp_unfbytes; /* number of unformatted bytes/sector */
@@ -159,8 +166,58 @@ struct wdparams {
short wdp_necc; /* ecc bytes appended */
char wdp_rev[8]; /* firmware revision */
char wdp_model[40]; /* model name */
- short wdp_nsecperint; /* sectors per interrupt */
+ char wdp_nsecperint; /* sectors per interrupt */
+ char wdp_vendorunique1;
short wdp_usedmovsd; /* can use double word read/write? */
+ char wdp_vendorunique2;
+ char wdp_capability; /* various capability bits */
+ short wdp_cap_validate; /* validation for above */
+ char wdp_vendorunique3;
+ char wdp_opiomode; /* PIO modes 0-2 */
+ char wdp_vendorunique4;
+ char wdp_odmamode; /* old DMA modes, not in ATA-3 */
+ short wdp_atavalid; /* validation for newer fields */
+ short wdp_currcyls;
+ short wdp_currheads;
+ short wdp_currsectors;
+ short wdp_currsize0;
+ short wdp_currsize1;
+ char wdp_currmultsect;
+ char wdp_multsectvalid;
+ int wdp_lbasize;
+ short wdp_dmasword; /* obsolete in ATA-3 */
+ short wdp_dmamword; /* multiword DMA modes */
+ short wdp_eidepiomodes; /* advanced PIO modes */
+ short wdp_eidedmamin; /* fastest possible DMA timing */
+ short wdp_eidedmanorm; /* recommended DMA timing */
+ short wdp_eidepioblind; /* fastest possible blind PIO */
+ short wdp_eidepioacked; /* fastest possible IORDY PIO */
+ short wdp_reserved69;
+ short wdp_reserved70;
+ short wdp_reserved71;
+ short wdp_reserved72;
+ short wdp_reserved73;
+ short wdp_reserved74;
+ short wdp_queuelen;
+ short wdp_reserved76;
+ short wdp_reserved77;
+ short wdp_reserved78;
+ short wdp_reserved79;
+ short wdp_versmaj;
+ short wdp_versmin;
+ short wdp_featsupp1;
+ short wdp_featsupp2;
+ short wdp_featsupp3;
+ short wdp_featenab1;
+ short wdp_featenab2;
+ short wdp_featenab3;
+ short wdp_udmamode; /* UltraDMA modes */
+ short wdp_erasetime;
+ short wdp_enherasetime;
+ short wdp_apmlevel;
+ short wdp_reserved92[34];
+ short wdp_rmvcap;
+ short wdp_securelevel;
};
/*
@@ -179,12 +236,18 @@ int wdformat(struct buf *bp);
* To use this:
* For each drive which you might want to do DMA on, call wdd_candma()
* to get a cookie. If it returns a null pointer, then the drive
- * can't do DMA.
+ * can't do DMA. Then call wdd_dmainit() to initialize the controller
+ * and drive. wdd_dmainit should leave PIO modes operational, though
+ * perhaps with suboptimal performance.
*
- * Set up the transfer be calling wdd_dmaprep(). The cookie is what
+ * Check the transfer by calling wdd_dmaverify(). The cookie is what
* you got before; vaddr is the virtual address of the buffer to be
* written; len is the length of the buffer; and direction is either
- * B_READ or B_WRITE.
+ * B_READ or B_WRITE. This function verifies that the DMA hardware is
+ * capable of handling the request you've made.
+ *
+ * Setup the transfer by calling wdd_dmaprep(). This takes the same
+ * paramaters as wdd_dmaverify().
*
* Send a read/write DMA command to the drive.
*
@@ -199,6 +262,8 @@ int wdformat(struct buf *bp);
struct wddma {
void *(*wdd_candma) /* returns a cookie if can do DMA */
__P((int ctlr, int drive));
+ int (*wdd_dmaverify) /* verify that request is DMA-able */
+ __P((void *cookie, char *vaddr, u_long len, int direction));
int (*wdd_dmaprep) /* prepare DMA hardware */
__P((void *cookie, char *vaddr, u_long len, int direction));
void (*wdd_dmastart) /* begin DMA transfer */
@@ -207,12 +272,39 @@ struct wddma {
__P((void *cookie));
int (*wdd_dmastatus) /* return status of DMA */
__P((void *cookie));
+ int (*wdd_dmainit) /* initialize controller and drive */
+ __P((void *cookie,
+ struct wdparams *wp,
+ int(wdcmd)__P((int mode, void *wdinfo)),
+ void *wdinfo));
};
+/* logical status bits returned by wdd_dmastatus */
#define WDDS_ACTIVE 0x0001
#define WDDS_ERROR 0x0002
#define WDDS_INTERRUPT 0x0004
+#if 0
+/* XXX are these now useless? */
+/* local defines for ATA timing modes */
+#define WDDMA_GRPMASK 0xf0
+/* flow-controlled PIO modes */
+#define WDDMA_PIO 0x10
+#define WDDMA_PIO3 0x10
+#define WDDMA_PIO4 0x11
+/* multi-word DMA timing modes */
+#define WDDMA_MDMA 0x20
+#define WDDMA_MDMA0 0x20
+#define WDDMA_MDMA1 0x21
+#define WDDMA_MDMA2 0x22
+
+/* Ultra DMA timing modes */
+#define WDDMA_UDMA 0x30
+#define WDDMA_UDMA0 0x30
+#define WDDMA_UDMA1 0x31
+#define WDDMA_UDMA2 0x32
+#endif
+
extern struct wddma wddma;
#endif /* KERNEL */
diff --git a/sys/pci/ide_pci.c b/sys/pci/ide_pci.c
new file mode 100644
index 0000000..e8e13c7
--- /dev/null
+++ b/sys/pci/ide_pci.c
@@ -0,0 +1,817 @@
+/*
+ * Copyright 1996 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ *
+ * From: wd82371.c,v 1.5.2.1 1996/11/16 21:19:51 phk Exp $
+ * $Id$
+ */
+
+#include "pci.h"
+#if NPCI > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h> /* for vtophys */
+
+#include <i386/isa/wdreg.h>
+
+#include <pci/pcivar.h>
+#include <pci/pcireg.h>
+#include <pci/ide_pcireg.h>
+
+struct ide_pci_cookie; /* structs vendor_fns, ide_pci_cookie are recursive */
+
+struct vendor_fns {
+ int (*vendor_dmainit) /* initialize DMA controller and drive */
+ (struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int(*wdcmd)(int, void *),
+ void *);
+
+ void (*vendor_status) /* prints off DMA timing info */
+ (int iobase_wd,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type);
+};
+
+/*
+ * XXX the fact that this list keeps all kinds of info on PCI controllers
+ * is pretty grotty-- much of this should be replaced by a proper integration
+ * of PCI probes into the wd driver.
+ * XXX if we're going to support native-PCI controllers, we also need to
+ * keep the address of the IDE control block register, which is something wd.c
+ * needs to know, which is why this info is in the wrong place.
+ */
+
+struct ide_pci_cookie {
+ LIST_ENTRY(ide_pci_cookie) le;
+ int iobase_wd;
+ int unit;
+ int iobase_bm; /* SFF-8038 control registers */
+ pcici_t tag;
+ pcidi_t type;
+ struct ide_pci_prd *prd;
+ struct vendor_fns vs;
+};
+
+struct ide_pci_softc {
+ LIST_HEAD(, ide_pci_cookie) cookies;
+};
+
+static int
+generic_dmainit(struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int(*wdcmd)(int, void *),
+ void *wdinfo);
+static void
+generic_status(int iobase_wd,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type);
+static void
+via_571_status(int iobase_wd,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type);
+static void
+intel_piix_dump_drive(char *ctlr,
+ int sitre,
+ int word40,
+ int word44,
+ int drive);
+static void
+intel_piix_status(int iobase_wd,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type);
+
+static struct ide_pci_cookie *
+mkcookie(int iobase_wd,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type,
+ struct vendor_fns *vp);
+
+
+
+static void ide_pci_attach(pcici_t tag, int unit);
+static void *ide_pci_candma(int, int);
+static int ide_pci_dmainit(void *,
+ struct wdparams *,
+ int (*)(int, void *),
+ void *);
+static int ide_pci_dmaverify(void *, char *, u_long, int);
+static int ide_pci_dmasetup(void *, char *, u_long, int);
+static void ide_pci_dmastart(void *);
+static int ide_pci_dmadone(void *);
+static int ide_pci_status(void *);
+static int ide_pci_timing(void *, int);
+
+static struct ide_pci_softc softc;
+
+static int ide_pci_softc_cookies_initted = 0;
+
+/*
+ * PRD_ALLOC_SIZE should be something that will not be allocated across a 64k
+ * boundary.
+ * PRD_MAX_SEGS is defined to be the maximum number of segments required for
+ * a transfer on an IDE drive, for an xfer that is linear in virtual memory.
+ * PRD_BUF_SIZE is the size of the buffer needed for a PRD table.
+ */
+#define PRD_ALLOC_SIZE PAGE_SIZE
+#define PRD_MAX_SEGS ((256 * 512 / PAGE_SIZE) + 1)
+#define PRD_BUF_SIZE PRD_MAX_SEGS * 8
+
+static void *prdbuf = 0;
+static void *prdbuf_next = 0;
+
+/*
+ * Hardware specific IDE controller code. All vendor-specific code
+ * for handling IDE timing and other chipset peculiarities should be
+ * encapsulated here.
+ */
+
+/* Generic busmastering PCI-IDE */
+
+static int
+generic_dmainit(struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int(*wdcmd)(int, void *),
+ void *wdinfo)
+{
+ int mode, r;
+ /*
+ * XXX punt on the whole timing issue by looking for either a
+ * drive programmed for both PIO4 and mDMA2 (which use similar
+ * timing) or a drive in an UltraDMA mode (hopefully all
+ * controllers have separate timing for UDMA). one hopes that if
+ * the drive's DMA mode has been configured by the BIOS, the
+ * controller's has also. this code may eventually be replaced
+ * by gunk in the hw-specific code to deal with specific
+ * controllers.
+ */
+ /* XXX way too sick and twisted conditional */
+ if (!((((wp->wdp_atavalid & 2) == 2) &&
+ ((wp->wdp_dmamword & 0x404) == 0x404) &&
+ ((wp->wdp_eidepiomodes & 2) == 2)) ||
+ (((wp->wdp_atavalid & 4) == 4) &&
+ (wp->wdp_udmamode == 4))))
+ return 0;
+
+#if 0
+ /*
+ * XXX flesh this out into real code that actually
+ * does something-- this was just testing gunk.
+ */
+ if (((wp->wdp_atavalid & 0x4) == 0x4) &&
+ (wp->wdp_udmamode == 4)) {
+ printf("UDMA mode\n");
+ mode = 0x42; /* XXX where's the #defines... */
+ }
+ else {
+ printf("MDMA mode\n");
+ mode = 0x24;
+ }
+
+ r = wdcmd(mode, wdinfo);
+ printf("dmainit out like we expect\n");
+ if (!r)
+ return 0;
+#endif
+ return 1;
+}
+
+static void
+generic_status(int iobase_wd,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type)
+{
+ printf("generic_status: no PCI IDE timing info available\n");
+}
+
+static struct vendor_fns vs_generic =
+{
+ generic_dmainit,
+ generic_status
+};
+
+/* VIA Technologies "82C571" PCI-IDE controller core */
+
+static void
+via_571_status(int iobase_wd,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type)
+{
+ unsigned int word40[5];
+ int i;
+
+ /* XXX how to handle four calls for one controller? */
+ if (iobase_wd != 0x1f0 || unit != 0)
+ return;
+
+ for (i=0; i<5; i++) {
+ word40[i] = pci_conf_read(tag, i * 4 + 0x40);
+ }
+
+ printf("via_571_status: Primary IDE prefetch/postwrite %s/%s\n",
+ word40[0] & 0x8000 ? "enabled" : "disabled",
+ word40[0] & 0x4000 ? "enabled" : "disabled");
+ printf("via_571_status: Secondary IDE prefetch/postwrite %s/%s\n",
+ word40[0] & 0x2000 ? "enabled" : "disabled",
+ word40[0] & 0x1000 ? "enabled" : "disabled");
+
+ printf("via_571_status: Master %d read/%d write IRDY# wait states\n",
+ (word40[1] & 0x40) >> 6,
+ (word40[1] & 0x20) >> 5);
+ printf("via_571_status: busmaster status read retry %s\n",
+ (word40[1] & 0x10) ? "enabled" : "disabled");
+
+ for (i=0; i<4; i++)
+ printf("via_571_status: %s drive %d setup=%d active=%d recovery=%d\n",
+ i < 2 ? "primary" : "secondary",
+ i & 1,
+ ((word40[3] >> ((3 - i) * 2)) & 3) + 1,
+ ((word40[2] >> (((3 - i) * 8) + 4)) & 0x0f) + 1,
+ ((word40[2] >> ((3 - i) * 8)) & 0x0f) + 1);
+
+
+ /* XXX could go on and do UDMA status for '586B */
+}
+
+static struct vendor_fns vs_via_571 =
+{
+ generic_dmainit,
+ via_571_status
+};
+
+/* Intel PIIX, PIIX3, and PIIX4 IDE controller subfunctions */
+
+static void
+intel_piix_dump_drive(char *ctlr,
+ int sitre,
+ int word40,
+ int word44,
+ int drive)
+{
+ char *ms;
+
+ if (!sitre)
+ ms = "master/slave";
+ else if (drive == 0)
+ ms = "master";
+ else
+ ms = "slave";
+
+ if (sitre || drive == 0)
+ printf("intel_piix_status: %s %s sample = %d, %s recovery = %d\n",
+ ctlr,
+ ms,
+ 5 - ((sitre && drive) ?
+ ((word44 >> 2) & 3) :
+ ((word40 >> 12) & 3)),
+ ms,
+ 4 - ((sitre && drive) ?
+ ((word44 >> 0) & 3) :
+ ((word40 >> 8) & 3)));
+
+ word40 >>= (drive * 4);
+ printf("\
+intel_piix_status: %s %s fastDMAonly %s, pre/post %s,\n\
+intel_piix_status: IORDY sampling %s,\n\
+intel_piix_status: fast PIO %s%s\n",
+ ctlr,
+ (drive == 0) ? "master" : "slave",
+ (word40 & 8) ? "enabled" : "disabled",
+ (word40 & 4) ? "enabled" : "disabled",
+ (word40 & 2) ? "enabled" : "disabled",
+ (word40 & 1) ? "enabled" : "disabled",
+ ((word40 & 9) == 9) ? " (overridden by fastDMAonly)" : "" );
+
+ /* XXX extend to dump 82371AB's UltraDMA modes */
+}
+
+static void
+intel_piix_status(int iobase_wd,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type)
+{
+ unsigned int word40, word44;
+ int sitre;
+
+ /* XXX how to handle four calls for one controller? */
+ if (iobase_wd != 0x1f0 || unit != 0)
+ return;
+
+ word40 = pci_conf_read(tag, 0x40);
+ word44 = pci_conf_read(tag, 0x44);
+
+ sitre = word40 & 0x4000;
+
+ intel_piix_dump_drive("primary", sitre, word40 & 0xffff, word44 & 0x0f, 0);
+ intel_piix_dump_drive("primary", sitre, word40 & 0xffff, word44 & 0x0f, 1);
+ intel_piix_dump_drive("secondary",
+ sitre,
+ (word40 >> 16) & 0xffff,
+ (word44 >> 4) & 0x0f,0);
+ intel_piix_dump_drive("secondary",
+ sitre,
+ (word40 >> 16) & 0xffff,
+ (word44 >> 4) & 0x0f,1);
+}
+
+static struct vendor_fns vs_intel_piix =
+{
+ generic_dmainit,
+ intel_piix_status
+};
+
+/* Generic SFF-8038i code-- all code below here, except for PCI probes,
+ * more or less conforms to the SFF-8038i spec as extended for PCI.
+ * There should be no code that goes beyond that feature set below.
+ */
+
+/* XXX mkcookie is overloaded with too many parameters */
+
+static struct ide_pci_cookie *
+mkcookie(int iobase_wd,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type,
+ struct vendor_fns *vp)
+{
+ struct ide_pci_cookie *cp;
+
+ cp = malloc(sizeof *cp, M_DEVBUF, M_NOWAIT);
+ if (!cp) return cp;
+
+ cp->iobase_wd = iobase_wd;
+ cp->unit = unit;
+ cp->tag = tag;
+ cp->type = type;
+ cp->iobase_bm = iobase_bm;
+ bcopy(vp, &cp->vs, sizeof(struct vendor_fns));
+
+ if (!prdbuf) {
+ prdbuf = malloc(PRD_ALLOC_SIZE, M_DEVBUF, M_NOWAIT);
+ if (!prdbuf) {
+ FREE(cp, M_DEVBUF);
+ return 0;
+ }
+ if (((int)prdbuf >> PAGE_SHIFT) ^
+ (((int)prdbuf + PRD_ALLOC_SIZE - 1) >> PAGE_SHIFT)) {
+ printf("ide_pci: prdbuf straddles page boundary, no DMA");
+ FREE(cp, M_DEVBUF);
+ FREE(prdbuf, M_DEVBUF);
+ return 0;
+ }
+
+ prdbuf_next = prdbuf;
+ }
+ cp->prd = prdbuf_next;
+ (char *)prdbuf_next += PRD_BUF_SIZE;
+
+ if ((char *)prdbuf_next > ((char *)prdbuf + PRD_ALLOC_SIZE))
+ panic("ide_pci: too many prdbufs allocated");
+
+ if (bootverbose)
+ printf("ide_pci: mkcookie %04x:%d: PRD vstart = %08x vend = %08x\n",
+ iobase_wd, unit, (int)cp->prd, ((int)cp->prd)+PRD_BUF_SIZE);
+ LIST_INSERT_HEAD(&softc.cookies, cp, le);
+ return cp;
+}
+
+static char *
+ide_pci_probe(pcici_t tag, pcidi_t type)
+{
+ int data = pci_conf_read(tag, PCI_CLASS_REG);
+
+ switch (data & PCI_CLASS_MASK) {
+
+ case PCI_CLASS_MASS_STORAGE:
+ if ((data & PCI_SUBCLASS_MASK) == 0x00010000) {
+ if (type == 0x71118086)
+ return ("Intel PIIX4 Bus-master IDE controller");
+ if (type == 0x70108086)
+ return ("Intel PIIX3 Bus-master IDE controller");
+ if (type == 0x12308086)
+ return ("Intel PIIX Bus-master IDE controller");
+ if (type == 0x05711106)
+ return ("VIA 82C586x (Apollo) Bus-master IDE controller");
+ if (data & 0x8000)
+ return ("PCI IDE controller (busmaster capable)");
+/*
+ * XXX leave this out for now, to allow CMD640B hack to work. said
+ * hack should be better integrated, or something.
+ */
+#if 0
+ else
+ return ("PCI IDE controller (not busmaster capable)");
+#endif
+ }
+ };
+ return ((char*)0);
+}
+
+static void
+ide_pci_attach(pcici_t tag, int unit)
+{
+ u_long idetm;
+ int class;
+ int bmista;
+ int iobase_wd, iobase_bm;
+ int cmd;
+ struct vendor_fns *vp;
+ pcidi_t type;
+
+ if (unit) return;
+
+ /* is it busmaster capable? bail if not */
+ class = pci_conf_read(tag, PCI_CLASS_REG);
+ if (!(class & 0x8000)) return;
+
+ /* is it enabled and is busmastering turned on? */
+ cmd = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
+ if ((cmd & 5) != 5) return;
+
+ /* set up vendor-specific stuff */
+ type = pci_conf_read(tag, PCI_ID_REG);
+
+ switch (type) {
+ case 0x71118086:
+ case 0x70108086:
+ case 0x12308086:
+ /* Intel PIIX, PIIX3, PIIX4 */
+ vp = &vs_intel_piix;
+ break;
+
+ case 0x5711106:
+ /* VIA Apollo chipset family */
+ vp = &vs_via_571;
+ break;
+
+ default:
+ /* everybody else */
+ vp = &vs_generic;
+ break;
+ }
+
+ iobase_wd = (class & 0x100) ?
+ (pci_conf_read(tag, 0x10) & 0xfffc) :
+ 0x1f0;
+ iobase_bm = pci_conf_read(tag, 0x20) & 0xfffc;
+
+ if (!ide_pci_softc_cookies_initted) {
+ LIST_INIT(&softc.cookies);
+ ide_pci_softc_cookies_initted = 1;
+ }
+
+ bmista = inb(iobase_bm + BMISTA_PORT);
+
+ if (bootverbose)
+ printf("ide_pci: busmaster 0 status: %02x from port: %08x\n",
+ bmista, iobase_bm+BMISTA_PORT);
+
+ if (!(bmista & BMISTA_DMA0CAP))
+ printf("ide_pci: warning, ide0:0 not configured for DMA?\n");
+ mkcookie(iobase_wd, 0, iobase_bm, tag, type, vp);
+ if (bootverbose)
+ vp->vendor_status(iobase_wd, 0, iobase_bm, tag, type);
+
+ if (!(bmista & BMISTA_DMA1CAP))
+ printf("ide_pci: warning, ide0:1 not configured for DMA?\n");
+ mkcookie(iobase_wd, 1, iobase_bm, tag, type, vp);
+ if (bootverbose)
+ vp->vendor_status(iobase_wd, 1, iobase_bm, tag, type);
+
+ if (bmista & BMISTA_SIMPLEX) {
+ printf("ide_pci: primary is simplex-only, no DMA on secondary\n");
+ } else {
+ iobase_wd = (class & 0x400) ?
+ (pci_conf_read(tag, 0x10) & 0xfffc) :
+ 0x170;
+ iobase_bm += SFF8038_CTLR_1;
+ bmista = inb(iobase_bm + BMISTA_PORT);
+
+ if (bootverbose)
+ printf("ide_pci: busmaster 1 status: %02x from port: %08x\n",
+ bmista, iobase_bm+BMISTA_PORT);
+
+ if (bmista & BMISTA_SIMPLEX) {
+ printf("ide_pci: secondary is simplex-only, no DMA on secondary\n");
+ } else {
+ if (!(bmista & BMISTA_DMA0CAP))
+ printf("ide_pci: warning, ide1:0 not configured for DMA?\n");
+ mkcookie(iobase_wd, 0, iobase_bm, tag, type, vp);
+ if (bootverbose)
+ vp->vendor_status(iobase_wd, 0, iobase_bm, tag, type);
+ if (!(bmista & BMISTA_DMA1CAP))
+ printf("ide_pci: warning, ide1:1 not configured for DMA?\n");
+ mkcookie(iobase_wd, 1, iobase_bm, tag, type, vp);
+ if (bootverbose)
+ vp->vendor_status(iobase_wd, 1, iobase_bm, tag, type);
+ }
+ }
+
+ wddma.wdd_candma = ide_pci_candma;
+ wddma.wdd_dmainit = ide_pci_dmainit;
+ wddma.wdd_dmaverify = ide_pci_dmaverify;
+ wddma.wdd_dmaprep = ide_pci_dmasetup;
+ wddma.wdd_dmastart = ide_pci_dmastart;
+ wddma.wdd_dmadone = ide_pci_dmadone;
+ wddma.wdd_dmastatus = ide_pci_status;
+}
+
+static u_long ide_pci_count;
+
+static struct pci_device ide_pci_device = {
+ "ide_pci",
+ ide_pci_probe,
+ ide_pci_attach,
+ &ide_pci_count,
+ 0
+};
+
+DATA_SET(pcidevice_set, ide_pci_device);
+
+/*
+ * Return a cookie if we can do DMA on the specified (iobase_wd, unit).
+ */
+static void *
+ide_pci_candma(int iobase_wd, int unit)
+{
+ struct ide_pci_cookie *cp;
+
+ cp = softc.cookies.lh_first;
+ while(cp) {
+ if (cp->unit == unit && cp->iobase_wd == iobase_wd)
+ break;
+ cp = cp->le.le_next;
+ }
+
+ return cp;
+}
+
+/*
+ * Initialize controller and drive for DMA operation, including timing modes.
+ * Uses data passed from the wd driver and a callback function to initialize
+ * timing modes on the drive.
+ */
+static int
+ide_pci_dmainit(void *cookie,
+ struct wdparams *wp,
+ int(*wdcmd)(int, void *),
+ void *wdinfo)
+{
+ struct ide_pci_cookie *cp = cookie;
+
+ return(cp->vs.vendor_dmainit(cp, wp, wdcmd, wdinfo));
+}
+/*
+ * Verify that controller can handle a dma request for cp. Should
+ * not affect any hardware or driver state.
+ */
+static int
+ide_pci_dmaverify(void *xcp, char *vaddr, u_long count, int dir)
+{
+ int badfu;
+
+ /*
+ * check for nonaligned or odd-length Stuff
+ */
+ badfu = ((unsigned int)vaddr & 1) || (count & 1);
+#if 1
+ if (badfu) {
+ printf("ide_pci: dmaverify odd vaddr or length, ");
+ printf("vaddr = %08x length = %08x\n", (int)vaddr, count);
+ }
+#endif
+ /*
+ * XXX should perhaps be checking that length of generated table
+ * does not exceed space available, but that Would Be Hairy
+ */
+ return (!badfu);
+}
+
+/*
+ * Set up DMA for cp. It is the responsibility of the caller
+ * to ensure that the controller is idle before this routine
+ * is called.
+ */
+static int
+ide_pci_dmasetup(void *xcp, char *vaddr, u_long count, int dir)
+{
+ struct ide_pci_cookie *cp = xcp;
+ struct ide_pci_prd *prd;
+ int i;
+ u_long pgresid;
+ int iobase_bm;
+ static int trashmore;
+ static int *trashmore_p = 0;
+
+
+ prd = cp->prd;
+ i = 0;
+
+ iobase_bm = cp->iobase_bm;
+ /*
+ * ensure that 0-length transfers get a PRD that won't smash much
+ */
+ if (!trashmore_p)
+ trashmore_p = (void *)vtophys(&trashmore);
+
+ prd[0].prd_base = (unsigned int)trashmore_p;
+ prd[0].prd_count = 0x80000002;
+
+ if (count == 0) {
+ printf("ide_pci: dmasetup 0-length transfer, ");
+ printf("vaddr = %08x length = %08x\n", (int)vaddr, count);
+ }
+
+ /*
+ * XXX the PRD generation code is somewhat ugly and will not
+ * port easily to big endian systems.
+ *
+ * but it works.
+ */
+
+ /*
+ * Deal with transfers that don't start on a page
+ * boundary.
+ */
+ pgresid = (u_long)vaddr % PAGE_SIZE;
+ if (pgresid) {
+ prd[i].prd_base = vtophys(vaddr);
+ if (count >= (PAGE_SIZE - pgresid))
+ prd[i].prd_count = PAGE_SIZE - pgresid;
+ else
+ prd[i].prd_count = count;
+ vaddr += prd[i].prd_count;
+ count -= prd[i].prd_count;
+ i++;
+ }
+
+ /*
+ * We have now ensured that vaddr is page-aligned, so just
+ * step through the pages adding each one onto the list.
+ */
+ while(count) {
+ u_long phys, n;
+
+ phys = vtophys(vaddr);
+ n = ((count > PAGE_SIZE) ? PAGE_SIZE : count);
+ /*
+ * If the current page is physically contiguous with
+ * whatever we have in the previous PRD, just tack it
+ * onto the end.
+ * CAVEAT: due to a hardware deficiency, PRDs
+ * cannot cross a 64K boundary.
+ * XXX should we bother with this collapsing? scattered
+ * pages appear to be the common case anyway.
+ */
+ if (i > 0
+ && (phys == prd[i - 1].prd_base + prd[i - 1].prd_count)
+ && ((prd[i - 1].prd_base & 0xffff)
+ + prd[i - 1].prd_count + n) <= 65535) {
+
+ prd[i - 1].prd_count += n;
+ } else {
+ prd[i].prd_base = phys;
+ prd[i].prd_count = n;
+ i++;
+ if (i >= PRD_MAX_SEGS)
+ panic("wd82371: too many segments\n");
+ }
+ count -= n;
+ vaddr += n;
+ }
+
+ /* put a sign at the edge of the cliff... */
+ prd[(i>0) ? (i-1) : 0].prd_count |= PRD_EOT_BIT;
+
+ if (i == 0)
+ printf("ide_pci: dmasetup 0-length PRD???\n");
+
+ /* Set up PRD base register */
+ outl(iobase_bm + BMIDTP_PORT, vtophys(prd));
+
+ /* Set direction of transfer */
+ if (dir == B_READ) {
+ outb(iobase_bm + BMICOM_PORT, BMICOM_READ_WRITE);
+ } else {
+ outb(iobase_bm + BMICOM_PORT, 0);
+ }
+
+ /* Clear interrupt and error bits */
+ outb(iobase_bm + BMISTA_PORT,
+ (inb(iobase_bm + BMISTA_PORT)
+ | (BMISTA_INTERRUPT | BMISTA_DMA_ERROR)));
+
+ /* printf("dma enable: iobase_bm = %08x command/status = %08x pointer = %08x\n", iobase_bm, inl(iobase_bm + BMICOM_PORT), inl(iobase_bm + BMIDTP_PORT)); */
+
+ /* printf("P"); */
+
+ return 0;
+}
+
+static void
+ide_pci_dmastart(void *xcp)
+{
+ struct ide_pci_cookie *cp = xcp;
+ int iobase_bm;
+
+ iobase_bm = cp->iobase_bm;
+
+ outb(iobase_bm + BMICOM_PORT,
+ inb(iobase_bm + BMICOM_PORT) | BMICOM_STOP_START);
+
+ /* printf("["); */
+}
+
+static int
+ide_pci_dmadone(void *xcp)
+{
+ struct ide_pci_cookie *cp = xcp;
+ int iobase_bm, status;
+
+ status = ide_pci_status(xcp);
+ iobase_bm = cp->iobase_bm;
+
+ outb(iobase_bm + BMICOM_PORT,
+ inb(iobase_bm + BMICOM_PORT) & ~BMICOM_STOP_START);
+
+ /* printf("]"); */
+
+ return status;
+}
+
+static int
+ide_pci_status(void *xcp)
+{
+ struct ide_pci_cookie *cp = xcp;
+ int iobase_bm, status, bmista;
+
+ status = 0;
+ iobase_bm = cp->iobase_bm;
+
+ bmista = inb(iobase_bm + BMISTA_PORT);
+
+ /* printf("dmastatus: iobase_bm = %08x status = %02x command/status = %08x pointer = %08x\n", iobase_bm, bmista, inl(iobase_bm + BMICOM_PORT), inl(iobase_bm + BMIDTP_PORT)); */
+
+ if (bmista & BMISTA_INTERRUPT)
+ status |= WDDS_INTERRUPT;
+ if (bmista & BMISTA_DMA_ERROR)
+ status |= WDDS_ERROR;
+ if (bmista & BMISTA_DMA_ACTIVE)
+ status |= WDDS_ACTIVE;
+
+ /* printf( (bmista == BMISTA_INTERRUPT)? "?":"!"); */
+
+ return status;
+}
+
+#endif /* NPCI > 0 */
diff --git a/sys/pci/ide_pcireg.h b/sys/pci/ide_pcireg.h
new file mode 100644
index 0000000..769645f
--- /dev/null
+++ b/sys/pci/ide_pcireg.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 1996 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ *
+ * From: wd82371reg.h,v 1.3 1997/02/22 09:44:15 peter Exp $
+ * $Id$
+ */
+
+#ifndef _PCI_IDEPCIREG_H_
+#define _PCI_IDEPCIREG_H_ 1
+
+/* Ports are for controller 0. Add SFF8038_CTLR_1 for controller 1. */
+#define SFF8038_CTLR_1 8
+
+/* Contents of BMICOM register */
+#define BMICOM_PORT 0
+#define BMICOM_READ_WRITE 0x0008 /* false = read, true = write */
+#define BMICOM_STOP_START 0x0001 /* false = stop, true = start */
+
+/* Contents of BMISTA register */
+#define BMISTA_PORT 2
+#define BMISTA_SIMPLEX 0x0080 /* 1 = controller cannot DMA on both
+ channels simultaneously */
+#define BMISTA_DMA1CAP 0x0040 /* true = drive 1 can DMA */
+#define BMISTA_DMA0CAP 0x0020 /* true = drive 0 can DMA */
+#define BMISTA_INTERRUPT 0x0004
+#define BMISTA_DMA_ERROR 0x0002
+#define BMISTA_DMA_ACTIVE 0x0001
+
+#define BMIDTP_PORT 4 /* use outl */
+
+struct ide_pci_prd {
+ u_int32_t prd_base;
+ u_int32_t prd_count;
+};
+
+#define PRD_EOT_BIT 0x80000000
+
+#endif /* _PCI_IDEPCIREG_H_ */
diff --git a/sys/pci/pcisupport.c b/sys/pci/pcisupport.c
index 1108d30..ac78356 100644
--- a/sys/pci/pcisupport.c
+++ b/sys/pci/pcisupport.c
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** $Id: pcisupport.c,v 1.47 1997/05/30 21:01:47 se Exp $
+** $Id: pcisupport.c,v 1.48 1997/07/18 19:47:23 se Exp $
**
** Device driver for DEC/INTEL PCI chipsets.
**
@@ -167,8 +167,11 @@ chipset_probe (pcici_t tag, pcidi_t type)
return ("Intel 82437FX PCI cache memory controller");
case 0x122e8086:
return ("Intel 82371FB PCI to ISA bridge");
+#if 0
+ /* ide_pci takes care of this now */
case 0x12308086:
return ("Intel 82371FB IDE interface");
+#endif
case 0x12508086:
return ("Intel 82439");
case 0x04061039:
@@ -179,12 +182,18 @@ chipset_probe (pcici_t tag, pcidi_t type)
return ("SiS 85c601");
case 0x70008086:
return ("Intel 82371SB PCI to ISA bridge");
+#if 0
+ /* ide_pci takes care of this now */
case 0x70108086:
return ("Intel 82371SB IDE interface");
+#endif
case 0x71108086:
return ("Intel 82371AB PCI to ISA bridge");
+#if 0
+ /* ide_pci takes care of this now */
case 0x71118086:
return ("Intel 82371AB IDE interface");
+#endif
case 0x71128086:
return ("Intel 82371AB USB host controller");
case 0x71138086:
OpenPOWER on IntegriCloud