summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1997-09-20 07:41:58 +0000
committerdyson <dyson@FreeBSD.org>1997-09-20 07:41:58 +0000
commit82185efa231b9e445aacba005cc9a39b5870a4ed (patch)
tree3e78b4aa1ba2dc7071d854218306ef0bac661bdd
parentbf08f9298bde2b71ea764a8f255a6d0baea61845 (diff)
downloadFreeBSD-src-82185efa231b9e445aacba005cc9a39b5870a4ed.zip
FreeBSD-src-82185efa231b9e445aacba005cc9a39b5870a4ed.tar.gz
Addition of support of the slightly rogue Promise IDE interface(Dyson), support
of multiple PCI IDE controllers(Dyson), and some updates and cleanups from John Hood, who originally made our IDE DMA stuff work :-). I have run tests with 7 IDE drives connected to my system, all in DMA mode, with no errors. Modulo any bugs, this stuff makes IDE look really good (within it's limitations.) Submitted by: John Hood <cgull@smoke.marlboro.vt.us>
-rw-r--r--sys/conf/NOTES19
-rw-r--r--sys/dev/pci/pcireg.h3
-rw-r--r--sys/i386/conf/LINT19
-rw-r--r--sys/i386/conf/NOTES19
-rw-r--r--sys/i386/isa/wd.c88
-rw-r--r--sys/i386/isa/wdreg.h10
-rw-r--r--sys/pci/ide_pci.c1698
-rw-r--r--sys/pci/pcireg.h3
8 files changed, 1205 insertions, 654 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 4e09a86..7b6675e 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.366 1997/09/16 07:45:31 joerg Exp $
+# $Id: LINT,v 1.367 1997/09/19 15:25:48 jmg Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -763,8 +763,23 @@ controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr
# allowed to probe for 32 bit transfers, but will allow multi-sector
# transfers up to the maximum that the drive supports.
#
-
+# If you are using a PCI controller that is not running in compatibility
+# mode (for example, it is a 2nd IDE PCI interface), then use config line(s)
+# such as:
+#
+#controller wdc2 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
+#disk wd4 at wdc2 drive 0
+#disk wd5 at wdc2 drive 1
+#
+#controller wdc3 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
+#disk wd6 at wdc3 drive 0
+#disk wd7 at wdc3 drive 1
#
+# Note that the above config would be useful for a Promise card, when used
+# on a MB that already has a PIIX controller. Note the bogus irq and port
+# entries. These are automatically filled in by the IDE/PCI support.
+#
+
controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr
disk wd0 at wdc0 drive 0
disk wd1 at wdc0 drive 1
diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h
index c24237f..9e8c85e 100644
--- a/sys/dev/pci/pcireg.h
+++ b/sys/dev/pci/pcireg.h
@@ -26,7 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pcireg.h,v 1.17 1997/05/28 20:37:19 se Exp $
+ * $Id: pcireg.h,v 1.18 1997/06/01 16:00:43 peter Exp $
*
*/
@@ -241,6 +241,7 @@
#define PCI_CLASS_REG 0x08
#define PCI_CLASS_MASK 0xff000000
#define PCI_SUBCLASS_MASK 0x00ff0000
+#define PCI_REVISION_MASK 0x000000ff
#define PCI_CLASS_PREHISTORIC 0x00000000
#define PCI_SUBCLASS_PREHISTORIC_VGA 0x00010000
#define PCI_CLASS_MASS_STORAGE 0x01000000
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index 4e09a86..7b6675e 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.366 1997/09/16 07:45:31 joerg Exp $
+# $Id: LINT,v 1.367 1997/09/19 15:25:48 jmg Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -763,8 +763,23 @@ controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr
# allowed to probe for 32 bit transfers, but will allow multi-sector
# transfers up to the maximum that the drive supports.
#
-
+# If you are using a PCI controller that is not running in compatibility
+# mode (for example, it is a 2nd IDE PCI interface), then use config line(s)
+# such as:
+#
+#controller wdc2 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
+#disk wd4 at wdc2 drive 0
+#disk wd5 at wdc2 drive 1
+#
+#controller wdc3 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
+#disk wd6 at wdc3 drive 0
+#disk wd7 at wdc3 drive 1
#
+# Note that the above config would be useful for a Promise card, when used
+# on a MB that already has a PIIX controller. Note the bogus irq and port
+# entries. These are automatically filled in by the IDE/PCI support.
+#
+
controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr
disk wd0 at wdc0 drive 0
disk wd1 at wdc0 drive 1
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 4e09a86..7b6675e 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.366 1997/09/16 07:45:31 joerg Exp $
+# $Id: LINT,v 1.367 1997/09/19 15:25:48 jmg Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -763,8 +763,23 @@ controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr
# allowed to probe for 32 bit transfers, but will allow multi-sector
# transfers up to the maximum that the drive supports.
#
-
+# If you are using a PCI controller that is not running in compatibility
+# mode (for example, it is a 2nd IDE PCI interface), then use config line(s)
+# such as:
+#
+#controller wdc2 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
+#disk wd4 at wdc2 drive 0
+#disk wd5 at wdc2 drive 1
+#
+#controller wdc3 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
+#disk wd6 at wdc3 drive 0
+#disk wd7 at wdc3 drive 1
#
+# Note that the above config would be useful for a Promise card, when used
+# on a MB that already has a PIIX controller. Note the bogus irq and port
+# entries. These are automatically filled in by the IDE/PCI support.
+#
+
controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr
disk wd0 at wdc0 drive 0
disk wd1 at wdc0 drive 1
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index 7d8f8a1..eecfbaa 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.137 1997/09/10 12:31:38 joerg Exp $
+ * $Id: wd.c,v 1.138 1997/09/13 16:12:12 joerg Exp $
*/
/* TODO:
@@ -66,6 +66,7 @@
#if NWDC > 0
+#include "pci.h"
#include <sys/param.h>
#include <sys/dkbad.h>
#include <sys/systm.h>
@@ -157,11 +158,13 @@ struct disk {
#endif
int dk_unit; /* physical unit number */
int dk_lunit; /* logical unit number */
+ int dk_interface; /* interface (two ctrlrs per interface) */
char dk_state; /* control state */
u_char dk_status; /* copy of status reg. */
u_char dk_error; /* copy of error reg. */
u_char dk_timeout; /* countdown to next timeout */
int dk_port; /* i/o port base */
+ int dk_altport; /* altstatus port base */
#ifdef DEVFS
void *dk_bdev; /* devfs token for whole disk */
void *dk_cdev; /* devfs token for raw whole disk */
@@ -204,7 +207,7 @@ static struct {
int b_active;
} wdtab[NWDC];
-struct wddma wddma;
+struct wddma wddma[NWDC];
#ifdef notyet
static struct buf rwdbuf[NWD]; /* buffers for raw IO */
@@ -276,6 +279,8 @@ static int
wdprobe(struct isa_device *dvp)
{
int unit = dvp->id_unit;
+ void *cookie;
+ int interface;
struct disk *du;
if (unit >= NWDC)
@@ -286,8 +291,21 @@ wdprobe(struct isa_device *dvp)
return (0);
bzero(du, sizeof *du);
du->dk_ctrlr = dvp->id_unit;
+ interface = du->dk_ctrlr / 2;
+ du->dk_interface = interface;
+#if !defined(DISABLE_PCI_IDE) && (NPCI > 0)
+ if (wddma[interface].wdd_candma) {
+ du->dk_dmacookie = wddma[interface].wdd_candma(dvp->id_iobase, du->dk_ctrlr);
+ du->dk_port = dvp->id_iobase;
+ du->dk_altport = wddma[interface].wdd_altiobase(du->dk_dmacookie);
+ } else {
+ du->dk_port = dvp->id_iobase;
+ du->dk_altport = du->dk_port + wd_ctlr;
+ }
+#else
du->dk_port = dvp->id_iobase;
-
+ du->dk_altport = du->dk_port + wd_ctlr;
+#endif
/* check if we have registers that work */
outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */
@@ -317,14 +335,16 @@ wdprobe(struct isa_device *dvp)
goto reset_ok;
#endif
DELAY(RECOVERYTIME);
- if (wdreset(du) != 0)
+ if (wdreset(du) != 0) {
goto nodevice;
+ }
reset_ok:
/* execute a controller only command */
if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0
- || wdwait(du, 0, TIMEOUT) < 0)
+ || wdwait(du, 0, TIMEOUT) < 0) {
goto nodevice;
+ }
/*
* drive(s) did not time out during diagnostic :
@@ -338,7 +358,6 @@ reset_ok:
* drive 2. (This seems to contradict the ATA spec.)
*/
du->dk_error = inb(du->dk_port + wd_error);
- /* printf("Error : %x\n", du->dk_error); */
if(du->dk_error != 0x01) {
if(du->dk_error & 0x80) { /* drive 1 failure */
@@ -776,7 +795,7 @@ wdstart(int ctrlr)
(bp->b_flags & B_READ) ? "read" : "write",
bp->b_bcount, blknum);
else
- printf(" %d)%x", du->dk_skip, inb(du->dk_port + wd_altsts));
+ printf(" %d)%x", du->dk_skip, inb(du->dk_altport));
#endif
lp = &du->dk_dd;
@@ -844,7 +863,7 @@ wdstart(int ctrlr)
du->dk_currentiosize = 1;
} else {
if((du->dk_flags & DKFL_USEDMA) &&
- wddma.wdd_dmaverify(du->dk_dmacookie,
+ wddma[du->dk_interface].wdd_dmaverify(du->dk_dmacookie,
(void *)((int)bp->b_un.b_addr +
du->dk_skip * DEV_BSIZE),
du->dk_bc,
@@ -893,7 +912,7 @@ wdstart(int ctrlr)
}
if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) {
- wddma.wdd_dmaprep(du->dk_dmacookie,
+ wddma[du->dk_interface].wdd_dmaprep(du->dk_dmacookie,
(void *)((int)bp->b_un.b_addr +
du->dk_skip * DEV_BSIZE),
du->dk_bc,
@@ -909,7 +928,7 @@ wdstart(int ctrlr)
printf("cylin %ld head %ld sector %ld addr %x sts %x\n",
cylin, head, sector,
(int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE,
- inb(du->dk_port + wd_altsts));
+ inb(du->dk_altport));
#endif
}
@@ -937,7 +956,7 @@ wdstart(int ctrlr)
/* 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);
+ wddma[du->dk_interface].wdd_dmastart(du->dk_dmacookie);
return;
}
@@ -1049,10 +1068,10 @@ wdintr(int unit)
/* finish off DMA */
if (du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) {
/* XXX SMP boxes sometimes generate an early intr. Why? */
- if ((wddma.wdd_dmastatus(du->dk_dmacookie) & WDDS_INTERRUPT)
+ if ((wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie) & WDDS_INTERRUPT)
== 0)
return;
- dmastat = wddma.wdd_dmadone(du->dk_dmacookie);
+ dmastat = wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie);
}
du->dk_timeout = 0;
@@ -1834,20 +1853,22 @@ failed:
du->dk_multi = wp->wdp_nsecperint & 0xff;
wdsetmulti(du);
- du->dk_dmacookie = NULL;
/*
* check drive's DMA capability
*/
+ if (wddma[du->dk_interface].wdd_candma) {
+ du->dk_dmacookie = wddma[du->dk_interface].wdd_candma(du->dk_port, du->dk_ctrlr);
/* does user want this? */
- if ((du->cfg_flags & WDOPT_DMA) &&
+ 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;
+ du->dk_dmacookie &&
+ /* can said drive do DMA? */
+ wddma[du->dk_interface].wdd_dmainit(du->dk_dmacookie, wp, wdsetmode, du)) {
+ du->dk_flags |= DKFL_USEDMA;
+ }
+ } else {
+ du->dk_dmacookie = NULL;
+ }
#ifdef WDDEBUG
printf(
@@ -2210,28 +2231,28 @@ wdflushirq(struct disk *du, int old_ipl)
static int
wdreset(struct disk *du)
{
- int wdc, err = 0;
+ int err = 0;
if ((du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) && du->dk_dmacookie)
- wddma.wdd_dmadone(du->dk_dmacookie);
+ wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie);
- wdc = du->dk_port;
(void)wdwait(du, 0, TIMEOUT);
- outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST);
+ outb(du->dk_altport, WDCTL_IDS | WDCTL_RST);
DELAY(10 * 1000);
- outb(wdc + wd_ctlr, WDCTL_IDS);
+ outb(du->dk_altport, WDCTL_IDS);
#ifdef ATAPI
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0)
err = 1; /* no IDE drive found */
- du->dk_error = inb(wdc + wd_error);
+ du->dk_error = inb(du->dk_port + wd_error);
if (du->dk_error != 0x01)
err = 1; /* the drive is incompatible */
#else
- if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
- || (du->dk_error = inb(wdc + wd_error)) != 0x01)
+ if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0) {
+ printf("wdreset: error1: 0x%x\n", du->dk_error);
return (1);
+ }
#endif
- outb(wdc + wd_ctlr, WDCTL_4BIT);
+ outb(du->dk_altport, WDCTL_4BIT);
return (err);
}
@@ -2273,7 +2294,7 @@ wdtimeout(void *cdu)
if (du->dk_dmacookie)
printf("wd%d: wdtimeout() DMA status %b\n",
du->dk_lunit,
- wddma.wdd_dmastatus(du->dk_dmacookie),
+ wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie),
WDDS_BITS);
}
wdunwedge(du);
@@ -2384,8 +2405,9 @@ wdwait(struct disk *du, u_char bits_wanted, int timeout)
* command completion.
*/
}
- if ((status & bits_wanted) == bits_wanted)
+ if ((status & bits_wanted) == bits_wanted) {
return (status & WDCS_ERR);
+ }
}
if (timeout < TIMEOUT)
/*
diff --git a/sys/i386/isa/wdreg.h b/sys/i386/isa/wdreg.h
index 9bb2f9b..0b37456 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: wdreg.h,v 1.12.2.3 1997/01/14 17:32:07 bde Exp $
+ * $Id: wdreg.h,v 1.19 1997/09/04 18:49:48 sos Exp $
*/
/*
@@ -260,7 +260,7 @@ int wdformat(struct buf *bp);
* WDDS_* constants below.
*/
struct wddma {
- void *(*wdd_candma) /* returns a cookie if can do DMA */
+ void *(*wdd_candma) /* returns a cookie if PCI */
__P((int ctlr, int drive));
int (*wdd_dmaverify) /* verify that request is DMA-able */
__P((void *cookie, char *vaddr, u_long len, int direction));
@@ -277,6 +277,10 @@ struct wddma {
struct wdparams *wp,
int(wdcmd)__P((int mode, void *wdinfo)),
void *wdinfo));
+ int (*wdd_iobase) /* returns iobase address */
+ __P((void *cookie));
+ int (*wdd_altiobase) /* returns altiobase address */
+ __P((void *cookie));
};
/* logical status bits returned by wdd_dmastatus */
@@ -305,6 +309,6 @@ struct wddma {
#define WDDMA_UDMA1 0x41
#define WDDMA_UDMA2 0x42
-extern struct wddma wddma;
+extern struct wddma wddma[];
#endif /* KERNEL */
diff --git a/sys/pci/ide_pci.c b/sys/pci/ide_pci.c
index 9f16080..b3a301f 100644
--- a/sys/pci/ide_pci.c
+++ b/sys/pci/ide_pci.c
@@ -26,13 +26,15 @@
* 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: ide_pci.c,v 1.2 1997/08/02 14:33:09 bde Exp $
+ * $Id: wd82371.c,v 1.5.2.1 1996/11/16 21:19:51 phk Exp $
*/
#include "pci.h"
#if NPCI > 0
#include "opt_wd.h"
+#include "wd.h"
+
+#if NWDC > 0
#include <sys/param.h>
#include <sys/systm.h>
@@ -43,6 +45,8 @@
#include <vm/pmap.h>
#include <i386/isa/wdreg.h>
+#include <i386/isa/isa.h>
+#include <i386/isa/isa_device.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
@@ -52,17 +56,19 @@
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
+#define PROMISE_ULTRA33 0x4d33105a
+
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 *);
+ (struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int (*wdcmd)(int, void *),
+ void *);
- void (*vendor_status) /* prints off DMA timing info */
- (struct ide_pci_cookie *cookie);
+ void (*vendor_status) /* prints off DMA timing info */
+ (struct ide_pci_cookie *cookie);
};
/*
@@ -75,77 +81,93 @@ struct vendor_fns {
*/
struct ide_pci_cookie {
- LIST_ENTRY(ide_pci_cookie) le;
- int iobase_wd;
- int ctlr; /* pri/sec controller on this PCI IDE interface */
- int unit;
- int iobase_bm; /* SFF-8038 control registers */
- pcici_t tag;
- pcidi_t type;
- struct ide_pci_prd *prd;
- struct vendor_fns vs;
+ LIST_ENTRY(ide_pci_cookie) le;
+ int iobase_wd;
+ int ctlr; /* controller 0/1 on PCI IDE interface */
+ int unit;
+ int iobase_bm; /* SFF-8038 control registers */
+ int altiobase_wd;
+ 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;
+ LIST_HEAD(, ide_pci_cookie) cookies;
};
static int
-generic_dmainit(struct ide_pci_cookie *cookie,
- struct wdparams *wp,
- int(*wdcmd)(int, void *),
- void *wdinfo);
+generic_dmainit(struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int (*wdcmd)(int, void *),
+ void *wdinfo);
+
static void
generic_status(struct ide_pci_cookie *cookie);
static void
via_571_status(struct ide_pci_cookie *cookie);
+static int
+via_571_dmainit(struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int (*wdcmd)(int, void *),
+ void *wdinfo);
+
static void
-intel_piix_dump_drive(char *ctlr,
- int sitre,
- int is_piix4,
- int word40,
- int word44,
- int word48,
- int word4a,
- int drive);
+intel_piix_dump_drive(char *ctlr,
+ int sitre,
+ int is_piix4,
+ int word40,
+ int word44,
+ int word48,
+ int word4a,
+ int drive);
+
static void
intel_piix_status(struct ide_pci_cookie *cookie);
static int
-intel_piix_dmainit(struct ide_pci_cookie *cookie,
- struct wdparams *wp,
- int(*wdcmd)(int, void *),
- void *wdinfo);
+intel_piix_dmainit(struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int (*wdcmd)(int, void *),
+ void *wdinfo);
static struct ide_pci_cookie *
-mkcookie(int iobase_wd,
- int ctlr,
- int unit,
- int iobase_bm,
- pcici_t tag,
- pcidi_t type,
- struct vendor_fns *vp);
+mkcookie(int iobase_wd,
+ int ctlr,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type,
+ struct vendor_fns *vp,
+ int altiobase_wd);
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 *);
+ 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 int ide_pci_iobase(void *xcp);
+static int ide_pci_altiobase(void *xcp);
static struct ide_pci_softc softc;
static int ide_pci_softc_cookies_initted = 0;
+extern void wdintr(void *);
+extern struct isa_driver wdcdriver;
+
/*
* PRD_ALLOC_SIZE should be something that will not be allocated across a 64k
* boundary.
@@ -166,6 +188,58 @@ static void *prdbuf_next = 0;
* encapsulated here.
*/
+/* helper funcs */
+
+/*
+ * nnn_mode() return the highest valid mode, or -1 if the mode class is
+ * not supported
+ */
+
+static inline int
+pio_mode(struct wdparams *wp)
+{
+ if ((wp->wdp_atavalid & 2) == 2) {
+ if ((wp->wdp_eidepiomodes & 2) == 2) return 4;
+ if ((wp->wdp_eidepiomodes & 1) == 1) return 3;
+ }
+ return -1;
+}
+
+#if 0
+static inline int
+dma_mode(struct wdparams *wp)
+{
+ /* XXX not quite sure how to verify validity on this field */
+}
+#endif
+
+static inline int
+mwdma_mode(struct wdparams *wp)
+{
+ /*
+ * XXX technically, using wdp_atavalid to test for validity of
+ * this field is not quite correct
+ */
+ if ((wp->wdp_atavalid & 2) == 2) {
+ if ((wp->wdp_dmamword & 4) == 4) return 2;
+ if ((wp->wdp_dmamword & 2) == 2) return 1;
+ if ((wp->wdp_dmamword & 1) == 1) return 0;
+ }
+ return -1;
+}
+
+static inline int
+udma_mode(struct wdparams *wp)
+{
+ if ((wp->wdp_atavalid & 4) == 4) {
+ if ((wp->wdp_udmamode & 4) == 4) return 2;
+ if ((wp->wdp_udmamode & 2) == 2) return 1;
+ if ((wp->wdp_udmamode & 1) == 1) return 0;
+ }
+ return -1;
+}
+
+
/* Generic busmastering PCI-IDE */
static int
@@ -174,35 +248,42 @@ generic_dmainit(struct ide_pci_cookie *cookie,
int(*wdcmd)(int, void *),
void *wdinfo)
{
- /*
- * 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.
- */
- /* 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;
+ /*
+ * 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.
+ *
+ * XXX there are examples where this approach is now known to be
+ * broken, at least on systems based on Intel chipsets.
+ */
- return 1;
+ if ((pio_mode(wp) >= 4 && mwdma_mode(wp) >= 2) ||
+ (udma_mode(wp) >= 2)) {
+ printf("ide_pci: generic_dmainit %04x:%d: warning, IDE controller timing not set\n",
+ cookie->iobase_wd,
+ cookie->unit);
+ return 1;
+ }
+#ifdef IDE_PCI_DEBUG
+ printf("pio_mode: %d, mwdma_mode(wp): %d, udma_mode(wp): %d\n",
+ pio_mode(wp), mwdma_mode(wp), udma_mode(wp));
+#endif
+ return 0;
}
static void
generic_status(struct ide_pci_cookie *cookie)
{
- printf("generic_status: no PCI IDE timing info available\n");
+ printf("generic_status: no PCI IDE timing info available\n");
}
static struct vendor_fns vs_generic =
{
- generic_dmainit,
- generic_status
+ generic_dmainit,
+ generic_status
};
/* VIA Technologies "82C571" PCI-IDE controller core */
@@ -210,60 +291,250 @@ static struct vendor_fns vs_generic =
static void
via_571_status(struct ide_pci_cookie *cookie)
{
- int iobase_wd;
- int unit;
- int iobase_bm;
- pcici_t tag;
- pcidi_t type;
- unsigned int word40[5];
- int i;
+ int iobase_wd;
+ int ctlr, unit;
+ int iobase_bm;
+ pcici_t tag;
+ pcidi_t type;
+ u_long word40[5];
+ int i, unitno;
+
+ iobase_wd = cookie->iobase_wd;
+ unit = cookie->unit;
+ ctlr = cookie->ctlr;
+ iobase_bm = cookie->iobase_bm;
+ tag = cookie->tag;
+ type = cookie->type;
+
+ unitno = ctlr * 2 + unit;
+
+ for (i=0; i<5; i++) {
+ word40[i] = pci_conf_read(tag, i * 4 + 0x40);
+ }
- iobase_wd = cookie->iobase_wd;
- unit = cookie->unit;
- iobase_bm = cookie->iobase_bm;
- tag = cookie->tag;
- type = cookie->type;
+ if (ctlr == 0)
+ printf("via_571_status: Primary IDE prefetch/postwrite %s/%s\n",
+ word40[0] & 0x8000 ? "enabled" : "disabled",
+ word40[0] & 0x4000 ? "enabled" : "disabled");
+ else
+ printf("via_571_status: Secondary IDE prefetch/postwrite %s/%s\n",
+ word40[0] & 0x2000 ? "enabled" : "disabled",
+ word40[0] & 0x1000 ? "enabled" : "disabled");
- /* XXX how to handle four calls for one controller? */
- if (iobase_wd != 0x1f0 || unit != 0)
- return;
+ printf("via_571_status: busmaster status read retry %s\n",
+ (word40[1] & 0x08) ? "enabled" : "disabled");
- for (i=0; i<5; i++) {
- word40[i] = pci_conf_read(tag, i * 4 + 0x40);
- }
+
+ printf("via_571_status: %s drive %d data setup=%d active=%d recovery=%d\n",
+ unitno < 2 ? "primary" : "secondary",
+ unitno & 1,
+ ((word40[3] >> ((3 - unitno) * 2)) & 3) + 1,
+ ((word40[2] >> (((3 - unitno) * 8) + 4)) & 0x0f) + 1,
+ ((word40[2] >> ((3 - unitno) * 8)) & 0x0f) + 1);
+
+ if (ctlr == 0)
+ printf("via_571_status: primary ctrl active=%d recovery=%d\n",
+ ((word40[3] >> 28) & 0x0f) + 1,
+ ((word40[2] >> 24) & 0x0f) + 1);
+ else
+ printf("via_571_status: secondary ctrl active=%d recovery=%d\n",
+ ((word40[3] >> 20) & 0x0f) + 1,
+ ((word40[2] >> 16) & 0x0f) + 1);
+
+ /* UltraDMA dump */
+ {
+ int foo;
+
+ foo = word40[4] >> ((3 - unitno) * 8);
+ printf("via_571_status: %s drive %d udma method=%d enable=%d PIOmode=%d cycle=%d\n",
+ i < 2 ? "primary" : "secondary",
+ i & 1,
+ (foo >> 7) & 1,
+ (foo >> 6) & 1,
+ (foo >> 5) & 1,
+ (foo & 3) + 2);
+ }
+}
+
+/*
+ * XXX timing values set here are only good for 30/33MHz buses; should deal
+ * with slower ones too (BTW: you overclock-- you lose)
+ */
+
+static int
+via_571_dmainit(struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int(*wdcmd)(int, void *),
+ void *wdinfo)
+{
+ int r;
+ u_long pci_revision;
+ int unitno;
+
+ pci_revision = pci_conf_read(cookie->tag, PCI_CLASS_REG) &
+ PCI_REVISION_MASK;
+
+ unitno = cookie->ctlr * 2 + cookie->unit;
+
+ /* If it's a UDMA drive on a '590, set it up */
+ /*
+ * XXX the revision number we check for is of dubious validity.
+ * it's extracted from the AMD 645 datasheet.
+ */
+ if (pci_revision >= 1 && udma_mode(wp) >= 2) {
+ unsigned int word50, mask, new;
+ word50 = pci_conf_read(cookie->tag, 0x50);
+
+ /* UDMA enable by SET FEATURES, DMA cycles, cycle time 2T */
+ mask = 0xe3000000 >> (unitno * 8);
+ new = 0x80000000 >> (unitno * 8);
+
+ word50 &= ~mask;
+ word50 |= new;
+
+ pci_conf_write(cookie->tag, 0x50, word50);
+
+ /*
+ * With the '590, drive configuration should come *after* the
+ * controller configuration, to make sure the controller sees
+ * the SET FEATURES command and does the right thing.
+ */
+ /* Set UDMA mode 2 on drive */
+ if (bootverbose)
+ printf("intel_piix_dmainit: setting ultra DMA mode 2\n");
+ r = wdcmd(WDDMA_UDMA2, wdinfo);
+ if (!r) {
+ printf("intel_piix_dmainit: setting DMA mode failed\n");
+ return 0;
+ }
+
+ if (bootverbose)
+ via_571_status(cookie);
+ return 1;
+
+ }
- 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 */
+ /* otherwise, try and program it for MW DMA mode 2 */
+ else if (mwdma_mode(wp) >= 2 && pio_mode(wp) >= 4) {
+ u_long workword;
+
+ /* Set multiword DMA mode 2 on drive */
+ if (bootverbose)
+ printf("intel_piix_dmainit: setting multiword DMA mode 2\n");
+ r = wdcmd(WDDMA_MDMA2, wdinfo);
+ if (!r) {
+ printf("intel_piix_dmainit: setting DMA mode failed\n");
+ return 0;
+ }
+
+ /* Configure the controller appropriately for MWDMA mode 2 */
+
+ workword = pci_conf_read(cookie->tag, 0x40);
+
+ /*
+ * enable prefetch/postwrite-- XXX may cause problems
+ * with CD-ROMs?
+ */
+ workword &= ~(3 << (cookie->ctlr * 2 + 12));
+ workword |= 3 << (cookie->ctlr * 2 + 12);
+
+ /* FIFO configurations-- equal split, threshold 1/2 */
+ workword &= 0x90ffffff;
+ workword |= 0x2a000000;
+
+ pci_conf_write(cookie->tag, 0x40, workword);
+
+ workword = pci_conf_read(cookie->tag, 0x44);
+
+ /* enable status read retry */
+ workword |= 8;
+
+ /* enable FIFO flush on interrupt and end of sector */
+ workword &= 0xff0cffff;
+ workword |= 0x00f00000;
+ pci_conf_write(cookie->tag, 0x44, workword);
+
+ workword = pci_conf_read(cookie->tag, 0x48);
+ /* set Mode2 timing */
+ workword &= ~(0xff000000 >> (unitno * 8));
+ workword |= 0x31000000 >> (unitno * 8);
+ pci_conf_write(cookie->tag, 0x48, workword);
+
+ /* set sector size */
+ pci_conf_write(cookie->tag, cookie->ctlr ? 0x68 : 0x60, 0x200);
+
+ if (bootverbose)
+ via_571_status(cookie);
+
+ return 1;
+
+ }
+ return 0;
}
+
static struct vendor_fns vs_via_571 =
{
+ via_571_dmainit,
+ via_571_status
+};
+
+
+static void
+promise_status(struct ide_pci_cookie *cookie)
+{
+ pcici_t tag;
+ int i,j;
+ u_int32_t port0_command, port0_altstatus;
+ u_int32_t port1_command, port1_altstatus;
+ u_int32_t dma_block;
+
+ u_int32_t lat_and_interrupt;
+ u_int32_t drivetiming;
+ int pa, pb, mb, mc;
+
+ tag = cookie->tag;
+ port0_command = pci_conf_read(tag, 0x10);
+ port0_altstatus = pci_conf_read(tag, 0x14);
+ port1_command = pci_conf_read(tag, 0x18);
+ port1_altstatus = pci_conf_read(tag, 0x1c);
+
+ dma_block = pci_conf_read(tag, 0x20);
+ lat_and_interrupt = pci_conf_read(tag, 0x3c);
+
+ printf("promise_status: port0: 0x%lx, port0_alt: 0x%lx, port1: 0x%lx, port1_alt: 0x%lx\n",
+ port0_command, port0_altstatus, port1_command, port1_altstatus);
+ printf("promise_status: dma control blk address: 0x%lx, int: %d, irq: %d\n",
+ dma_block, (lat_and_interrupt >> 8) & 0xff, lat_and_interrupt & 0xff);
+
+ for(i=0;i<4;i+=2) {
+ drivetiming = pci_conf_read(tag, 0x60 + i * 4);
+ printf("drivebits%d-%d: %b\n", i, i+1, drivetiming,
+ "\020\05Prefetch\06Iordy\07Errdy\010Sync\025DmaW\026DmaR");
+ pa = drivetiming & 0xf;
+ pb = (drivetiming >> 8) & 0x1f;
+ mb = (drivetiming >> 13) & 0x7;
+ mc = (drivetiming >> 16) & 0xf;
+ printf("drivetiming%d: pa: 0x%x, pb: 0x%x, mb: 0x%x, mc: 0x%x\n",
+ i, pa, pb, mb, mc);
+
+ drivetiming = pci_conf_read(tag, 0x60 + (i + 1) * 4);
+ pa = drivetiming & 0xf;
+ pb = (drivetiming >> 8) & 0x1f;
+ mb = (drivetiming >> 13) & 0x7;
+ mc = (drivetiming >> 16) & 0xf;
+ printf("drivetiming%d: pa: 0x%x, pb: 0x%x, mb: 0x%x, mc: 0x%x\n",
+ i + 1, pa, pb, mb, mc);
+ }
+}
+
+static struct vendor_fns vs_promise =
+{
generic_dmainit,
- via_571_status
+ promise_status
};
/* Intel PIIX, PIIX3, and PIIX4 IDE controller subfunctions */
-
static void
intel_piix_dump_drive(char *ctlr,
int sitre,
@@ -274,16 +545,15 @@ intel_piix_dump_drive(char *ctlr,
int word4a,
int drive)
{
- char *ms;
+ char *ms;
- if (!sitre)
- ms = "master/slave";
- else if (drive == 0)
- ms = "master";
- else
- ms = "slave";
+ 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,
@@ -295,217 +565,270 @@ intel_piix_dump_drive(char *ctlr,
((word44 >> 0) & 3) :
((word40 >> 8) & 3)));
- word40 >>= (drive * 4);
- printf("\
-intel_piix_status: %s %s fastDMAonly %s, pre/post %s,\n\
+ 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)" : "" );
-
- if (is_piix4)
- printf("intel_piix_status: UltraDMA %s, CT/RP = %d/%d\n",
- word48 ? "enabled": "disabled",
- 4 - (word4a & 3),
- 6 - (word4a & 3));
-
+ 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)" : "" );
+
+ if (is_piix4)
+ printf("intel_piix_status: UltraDMA %s, CT/RP = %d/%d\n",
+ word48 ? "enabled": "disabled",
+ 4 - (word4a & 3),
+ 6 - (word4a & 3));
}
static void
intel_piix_status(struct ide_pci_cookie *cookie)
{
- int iobase_wd;
- int unit;
- int iobase_bm;
- pcici_t tag;
- pcidi_t type;
- int ctlr;
- unsigned int word40, word44, word48;
- int sitre, is_piix4;
-
- iobase_wd = cookie->iobase_wd;
- unit = cookie->unit;
- iobase_bm = cookie->iobase_bm;
- tag = cookie->tag;
- type = cookie->type;
- ctlr = cookie->ctlr;
-
- word40 = pci_conf_read(tag, 0x40);
- word44 = pci_conf_read(tag, 0x44);
- word48 = pci_conf_read(tag, 0x48);
-
- /*
- * XXX will not be right for the *next* generation of upward-compatible
- * intel IDE controllers...
- */
- is_piix4 = pci_conf_read(tag, PCI_CLASS_REG) == 0x71118086;
-
- sitre = word40 & 0x4000;
-
- switch (ctlr * 2 + unit) {
- case 0:
- intel_piix_dump_drive("primary",
- sitre,
- is_piix4,
- word40 & 0xffff,
- word44 & 0x0f,
- word48,
- word48 >> 16,
- 0);
- case 1:
- intel_piix_dump_drive("primary",
- sitre,
- is_piix4,
- word40 & 0xffff,
- word44 & 0x0f,
- word48 >> 1,
- word48 >> 20,
- 1);
- case 2:
- intel_piix_dump_drive("secondary",
- sitre,
- is_piix4,
- (word40 >> 16) & 0xffff,
- (word44 >> 4) & 0x0f,
- word48 >> 2,
- word48 >> 24,
- 0);
- case 3:
- intel_piix_dump_drive("secondary",
- sitre,
- is_piix4,
- (word40 >> 16) & 0xffff,
- (word44 >> 4) & 0x0f,
- word48 >> 3,
- word48 >> 28,
- 1);
- }
+ int iobase_wd;
+ int unit;
+ int iobase_bm;
+ pcici_t tag;
+ pcidi_t type;
+ int ctlr;
+ u_long word40, word44, word48;
+ int sitre, is_piix4;
+
+ iobase_wd = cookie->iobase_wd;
+ unit = cookie->unit;
+ iobase_bm = cookie->iobase_bm;
+ tag = cookie->tag;
+ type = cookie->type;
+ ctlr = cookie->ctlr;
+
+ word40 = pci_conf_read(tag, 0x40);
+ word44 = pci_conf_read(tag, 0x44);
+ word48 = pci_conf_read(tag, 0x48);
+
+ /*
+ * XXX will not be right for the *next* generation of upward-compatible
+ * intel IDE controllers...
+ */
+ is_piix4 = pci_conf_read(tag, PCI_CLASS_REG) == 0x71118086;
+
+ sitre = word40 & 0x4000;
+
+ switch (ctlr * 2 + unit) {
+ case 0:
+ intel_piix_dump_drive("primary",
+ sitre,
+ is_piix4,
+ word40 & 0xffff,
+ word44 & 0x0f,
+ word48,
+ word48 >> 16,
+ 0);
+ break;
+ case 1:
+ intel_piix_dump_drive("primary",
+ sitre,
+ is_piix4,
+ word40 & 0xffff,
+ word44 & 0x0f,
+ word48 >> 1,
+ word48 >> 20,
+ 1);
+ break;
+ case 2:
+ intel_piix_dump_drive("secondary",
+ sitre,
+ is_piix4,
+ (word40 >> 16) & 0xffff,
+ (word44 >> 4) & 0x0f,
+ word48 >> 2,
+ word48 >> 24,
+ 0);
+ break;
+ case 3:
+ intel_piix_dump_drive("secondary",
+ sitre,
+ is_piix4,
+ (word40 >> 16) & 0xffff,
+ (word44 >> 4) & 0x0f,
+ word48 >> 3,
+ word48 >> 28,
+ 1);
+ break;
+ default:
+ printf("intel_piix_status: bad drive or controller number\n");
+ }
}
+/*
+ * XXX timing values set hereare only good for 30/33MHz buses; should deal
+ * with slower ones too (BTW: you overclock-- you lose)
+ */
+
static int
intel_piix_dmainit(struct ide_pci_cookie *cookie,
- struct wdparams *wp,
- int(*wdcmd)(int, void *),
- void *wdinfo)
+ struct wdparams *wp,
+ int(*wdcmd)(int, void *),
+ void *wdinfo)
{
- int r, pci_id;
-
- pci_id = pci_conf_read(cookie->tag, PCI_CLASS_REG);
-
- /*
- * If the drive is already in mDMA2 or UDMA2, we leave it and the
- * controller alone, on the theory that the BIOS already DTRT.
- *
- * XXX this does not handle the conceivable case where the drive
- * has been left in a the right mode from a previous boot, the
- * BIOS has not reset it, and the BIOS has also not set the modes
- * on the controller. The one case seen so far where the BIOS
- * doesn't dink the drives (Tyan S1563D with Award v4.01) it
- * *does* seem to correctly program the controller.
- *
- * Aren't PC's fun?
- */
-
- /* 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 & 0x404 == 0x404)))
- return 1;
-
- /* If it's a UDMA drive and a PIIX4, set it up */
- if (((wp->wdp_atavalid & 4) == 4) &&
- ((wp->wdp_udmamode & 4) == 4) &&
- pci_id == 0x71118086) {
- /* Set UDMA mode 2 on controller */
- int unitno, mask, new;
-
- if (bootverbose)
- printf("intel_piix_dmainit: setting ultra DMA mode 2\n");
- r = wdcmd(WDDMA_UDMA2, wdinfo);
- if (!r) {
- printf("intel_piix_dmainit: setting DMA mode failed\n");
- return 0;
- }
+ int r;
- unitno = cookie->ctlr * 2 + cookie->unit;
+ /* If it's a UDMA drive and a PIIX4, set it up */
+ if (cookie->type == 0x71118086 && udma_mode(wp) >= 2) {
+ /* Set UDMA mode 2 on controller */
+ int unitno, mask, new;
- mask = 1 << unitno + 3 << (16 + unitno * 4);
- new = 1 << unitno + 2 << (16 + unitno * 4);
+ if (bootverbose)
+ printf("intel_piix_dmainit: setting ultra DMA mode 2\n");
- pci_conf_write(cookie->tag,
- 0x48,
- (pci_conf_read(cookie->tag, 0x48) & ~mask) | new);
- }
- /*
- * if the SITRE bit is not set, indicating independent programming
- * of drive timing, we punt; we're not gonna fuss with trying to
- * coordinate timing modes between drives. if this is you, get a
- * BIOS that does this for us, or get a new motherboard if it's an
- * 82371FB (Triton FX). Or contribute patches :)
- */
- else if ((pci_conf_read(cookie->tag, 0x40) >> (16 * cookie->ctlr))
- & 0x4000 == 0)
- return 0;
- /* otherwise, program it for MW DMA mode 2 */
- else if (((wp->wdp_atavalid & 2) == 2) &&
- ((wp->wdp_dmamword & 4) == 4)) {
- /* Set multiword DMA mode 2 on controller */
- unsigned int mask40, mask44, new40, new44;
-
- if (bootverbose)
- printf("intel_piix_dmainit: setting multiword DMA mode 2\n");
- r = wdcmd(WDDMA_MDMA2, wdinfo);
- if (!r) {
- printf("intel_piix_dmainit: setting DMA mode failed\n");
- return 0;
- }
+ r = wdcmd(WDDMA_UDMA2, wdinfo);
+
+ if (!r) {
+ printf("intel_piix_dmainit: setting DMA mode failed\n");
+ return 0;
+ }
+
+ unitno = cookie->ctlr * 2 + cookie->unit;
+ mask = 1 << unitno + 3 << (16 + unitno * 4);
+ new = 1 << unitno + 2 << (16 + unitno * 4);
+
+ pci_conf_write(cookie->tag, 0x48,
+ (pci_conf_read(cookie->tag, 0x48) & ~mask) | new);
+
+ if (bootverbose)
+ intel_piix_status(cookie);
+ return 1;
+ }
/*
- * backward compatible hardware leaves us with such twisted masses
- * of software (aka twiddle the extremely weird register layout on
- * a PIIX3)
+ * if it's an 82371FB, which can't do independent programming of
+ * drive timing, we punt; we're not going to fuss with trying to
+ * coordinate timing modes between drives. if this is you, get a
+ * new motherboard. or contribute patches :)
+ *
+ * we do now at least see if the modes set are OK to use. this should
+ * satisfy the majority of people, with mwdma mode2 drives.
*/
- if (cookie->unit == 0) {
- mask40 = 0x330f;
- new40 = 0x2307;
- mask44 = 0;
- new44 = 0;
- }
- else {
- mask40 = 0x00f0;
- new40 = 0x0070;
- mask44 = 0x000f;
- new44 = 0x000b;
+ else if (cookie->type == 0x12308086)
+ {
+ u_long word40;
+
+ /* can drive do PIO 4 and MW DMA 2? */
+ if (!(mwdma_mode(wp) >= 4 && pio_mode(wp) >= 4))
+ return 0;
+
+ word40 = pci_conf_read(cookie->tag, 0x40);
+ word40 >>= cookie->ctlr * 16;
+
+ /* Check for timing config usable for DMA on controller */
+ if (!((word40 & 0x3300) == 0x2300 &&
+ ((word40 >> (cookie->unit * 4)) & 1) == 1))
+ return 0;
+
+ /* Set multiword DMA mode 2 on drive */
+ if (bootverbose)
+ printf("intel_piix_dmainit: setting multiword DMA mode 2\n");
+ r = wdcmd(WDDMA_MDMA2, wdinfo);
+ if (!r) {
+ printf("intel_piix_dmainit: setting DMA mode failed\n");
+ return 0;
+ }
+ return 1;
}
- if (cookie->ctlr) {
- mask40 <<= 16;
- new40 <<= 16;
- mask44 <<= 4;
- new44 <<= 4;
+
+ /* otherwise, treat it as a PIIX3 and program it for MW DMA mode 2 */
+ else if (mwdma_mode(wp) >= 2 && pio_mode(wp) >= 4) {
+ u_long mask40, mask44, new40, new44;
+
+ /*
+ * If SITRE is not set, set it and copy the
+ * appropriate bits into the secondary registers. Do
+ * both controllers at once.
+ */
+ if (((pci_conf_read(cookie->tag, 0x40) >> (16 * cookie->ctlr))
+ & 0x4000) == 0) {
+ unsigned int word40, word44;
+
+ word40 = pci_conf_read(cookie->tag, 0x40);
+
+ /* copy bits to secondary register */
+ word44 = pci_conf_read(cookie->tag, 0x44);
+ /*
+ * I've got a Biostar motherboard with Award
+ * BIOS that sets SITRE and secondary timing
+ * on one controller but not the other.
+ * Bizarre.
+ */
+ if ((word40 & 0x4000) == 0) {
+ word44 &= ~0xf;
+ word44 |= ((word40 & 0x3000) >> 10) |
+ ((word40 & 0x0300) >> 8);
+ }
+ if ((word40 & 0x40000000) == 0) {
+ word44 &= ~0xf0;
+ word44 |= ((word40 & 0x30000000) >> 22) |
+ ((word40 & 0x03000000) >> 20);
+ }
+ /* set SITRE */
+ word40 |= 0x40004000;
+
+ pci_conf_write(cookie->tag, 0x40, word40);
+ pci_conf_write(cookie->tag, 0x44, word44);
+ }
+
+ /* Set multiword DMA mode 2 on drive */
+ if (bootverbose)
+ printf("intel_piix_dmainit: setting multiword DMA mode 2\n");
+
+ r = wdcmd(WDDMA_MDMA2, wdinfo);
+
+ if (!r) {
+ printf("intel_piix_dmainit: setting DMA mode failed\n");
+ return 0;
+ }
+
+ /*
+ * backward compatible hardware leaves us with such
+ * twisted masses of software (aka twiddle the
+ * extremely weird register layout on a PIIX3, setting
+ * PIO mode 4 and MWDMA mode 2)
+ */
+ if (cookie->unit == 0) {
+ mask40 = 0x330f;
+ new40 = 0x2307;
+ mask44 = 0;
+ new44 = 0;
+ } else {
+ mask40 = 0x00f0;
+ new40 = 0x0070;
+ mask44 = 0x000f;
+ new44 = 0x000b;
+ }
+
+ if (cookie->ctlr) {
+ mask40 <<= 16;
+ new40 <<= 16;
+ mask44 <<= 4;
+ new44 <<= 4;
+ }
+
+ pci_conf_write(cookie->tag, 0x40,
+ (pci_conf_read(cookie->tag, 0x40) & ~mask40) | new40);
+ pci_conf_write(cookie->tag, 0x44,
+ (pci_conf_read(cookie->tag, 0x44) & ~mask44) | new44);
+
+ if (bootverbose)
+ intel_piix_status(cookie);
+ return 1;
}
- pci_conf_write(cookie->tag,
- 0x40,
- (pci_conf_read(cookie->tag, 0x40) & ~mask40) | new40);
- pci_conf_write(cookie->tag,
- 0x44,
- (pci_conf_read(cookie->tag, 0x44) & ~mask44) | new44);
- }
- if (bootverbose)
- intel_piix_status(cookie);
- return 1;
+ return 0;
}
static struct vendor_fns vs_intel_piix =
{
- intel_piix_dmainit,
- intel_piix_status
+ intel_piix_dmainit,
+ intel_piix_status
};
/* Generic SFF-8038i code-- all code below here, except for PCI probes,
@@ -517,214 +840,343 @@ static struct vendor_fns vs_intel_piix =
static struct ide_pci_cookie *
mkcookie(int iobase_wd,
- int ctlr,
- int unit,
- int iobase_bm,
- pcici_t tag,
- pcidi_t type,
- struct vendor_fns *vp)
+ int ctlr,
+ int unit,
+ int iobase_bm,
+ pcici_t tag,
+ pcidi_t type,
+ struct vendor_fns *vp,
+ int altiobase_wd)
{
- struct ide_pci_cookie *cp;
+ struct ide_pci_cookie *cp;
- cp = malloc(sizeof *cp, M_DEVBUF, M_NOWAIT);
- if (!cp) return cp;
+ cp = malloc(sizeof *cp, M_DEVBUF, M_NOWAIT);
+ if (!cp) return 0;
- cp->iobase_wd = iobase_wd;
- cp->ctlr = ctlr;
- cp->unit = unit;
- cp->tag = tag;
- cp->type = type;
- cp->iobase_bm = iobase_bm;
- bcopy(vp, &cp->vs, sizeof(struct vendor_fns));
+ cp->iobase_wd = iobase_wd;
+ cp->ctlr = ctlr;
+ cp->unit = unit;
+ cp->tag = tag;
+ cp->type = type;
+ cp->iobase_bm = iobase_bm;
+ cp->altiobase_wd = altiobase_wd;
+ 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;
+ 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\n");
+ FREE(cp, M_DEVBUF);
+ FREE(prdbuf, M_DEVBUF);
+ return 0;
+ }
+
+ prdbuf_next = prdbuf;
}
- if (((int)prdbuf >> PAGE_SHIFT) ^
- (((int)prdbuf + PRD_ALLOC_SIZE - 1) >> PAGE_SHIFT)) {
- printf("ide_pci: prdbuf straddles page boundary, no DMA\n");
- FREE(cp, M_DEVBUF);
- FREE(prdbuf, M_DEVBUF);
- return 0;
+ if (((char *)prdbuf_next + PRD_BUF_SIZE) >
+ ((char *)prdbuf + PRD_ALLOC_SIZE)) {
+ printf("ide_pci: mkcookie %04x:%d: no more space for PRDs, no DMA\n",
+ iobase_wd, unit);
+ FREE(cp, 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)) {
- printf("ide_pci: mkcookie %04x:%d: no more space for PRDs, no DMA\n",
- iobase_wd, unit);
- return 0;
- }
+ cp->prd = prdbuf_next;
+ (char *)prdbuf_next += PRD_BUF_SIZE;
-#if 0
- 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);
-#endif
- LIST_INSERT_HEAD(&softc.cookies, cp, le);
- return cp;
+ 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);
-
- if ((data & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE &&
- (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)");
+ u_long data;
+
+ data = pci_conf_read(tag, PCI_CLASS_REG);
+
+ if ((data & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE &&
+ ((data & PCI_SUBCLASS_MASK) == 0x00010000 ||
+ ((data & PCI_SUBCLASS_MASK) == 0x00040000))) {
+ 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 == PROMISE_ULTRA33)
+ return ("Promise Ultra/33 IDE controller");
+ if (type == 0x05711106)
+ return ("VIA 82C586x (Apollo) Bus-master IDE controller");
+ if (data & 0x8000)
+ return ("PCI IDE controller (busmaster capable)");
#ifndef CMD640
- /*
- * XXX the CMD640B hack should be better integrated, or
- * something.
- */
- else
- return ("PCI IDE controller (not busmaster capable)");
+ /*
+ * XXX the CMD640B hack should be better integrated, or
+ * something.
+ */
+ else
+ return ("PCI IDE controller (not busmaster capable)");
#endif
- };
- return ((char*)0);
+ };
+ return ((char*)0);
}
static void
ide_pci_attach(pcici_t tag, int unit)
{
- u_long idetm;
- int class;
- int bmista_1, bmista_2;
- int iobase_wd_1, iobase_wd_2, iobase_bm_1, iobase_bm_2;
- int cmd;
- struct vendor_fns *vp;
- pcidi_t type;
- struct ide_pci_cookie *cookie;
-
- 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;
- }
+ u_long idetm;
+ u_long class, cmd;
+ int bmista_1, bmista_2;
+ int iobase_wd_1, iobase_wd_2, iobase_bm_1, iobase_bm_2;
+ int altiobase_wd_1, altiobase_wd_2;
+ struct vendor_fns *vp;
+ pcidi_t type;
+ struct ide_pci_cookie *cookie;
+ int ctlridx;
+
+ ctlridx = unit * 2;
+
+ /* set up vendor-specific stuff */
+ type = pci_conf_read(tag, PCI_ID_REG);
+
+ if (type != PROMISE_ULTRA33) {
+ /* 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;
+ }
+ }
- iobase_wd_1 = (class & 0x100) ?
- (pci_conf_read(tag, 0x10) & 0xfffc) :
- 0x1f0;
- iobase_bm_1 = pci_conf_read(tag, 0x20) & 0xfffc;
+ 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;
+
+ case PROMISE_ULTRA33:
+ /* Promise controllers */
+ vp = &vs_promise;
+ break;
+
+ default:
+ /* everybody else */
+ vp = &vs_generic;
+ break;
+ }
- iobase_wd_2 = (class & 0x400) ?
- (pci_conf_read(tag, 0x10) & 0xfffc) :
- 0x170;
- iobase_bm_2 = iobase_bm_1 + SFF8038_CTLR_1;
+ if (type != PROMISE_ULTRA33) {
+ if ((class & 0x100) == 0) {
+ iobase_wd_1 = IO_WD1;
+ altiobase_wd_1 = iobase_wd_1 + wd_altsts;
+ } else {
+ iobase_wd_1 = pci_conf_read(tag, 0x10) & 0xfffc;
+ altiobase_wd_1 = pci_conf_read(tag, 0x14) & 0xfffc;
+ }
+
+ if ((class & 0x400) == 0) {
+ iobase_wd_2 = IO_WD2;
+ altiobase_wd_2 = iobase_wd_2 + wd_altsts;
+ } else {
+ iobase_wd_2 = pci_conf_read(tag, 0x18) & 0xfffc;
+ altiobase_wd_2 = pci_conf_read(tag, 0x1c) & 0xfffc;
+ }
+ } else {
+ iobase_wd_1 = pci_conf_read(tag, 0x10) & 0xfffc;
+ altiobase_wd_1 = pci_conf_read(tag, 0x14) & 0xfffc;
+ iobase_wd_2 = pci_conf_read(tag, 0x18) & 0xfffc;
+ altiobase_wd_2 = pci_conf_read(tag, 0x1c) & 0xfffc;
+ }
- if (iobase_bm_1 == 0) {
- printf("ide_pci: BIOS has not configured busmaster I/O address,\n"
- "ide_pci: giving up\n");
- return;
- }
+ iobase_bm_1 = pci_conf_read(tag, 0x20) & 0xfffc;
+ iobase_bm_2 = iobase_bm_1 + SFF8038_CTLR_1;
+ if (iobase_bm_1 == 0) {
+ printf("ide_pci: BIOS has not configured busmaster I/O address,\n\
+ide_pci: giving up\n");
+ return;
+ }
- 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;
+ wddma[unit].wdd_candma = ide_pci_candma;
+ wddma[unit].wdd_dmainit = ide_pci_dmainit;
+ wddma[unit].wdd_dmaverify = ide_pci_dmaverify;
+ wddma[unit].wdd_dmaprep = ide_pci_dmasetup;
+ wddma[unit].wdd_dmastart = ide_pci_dmastart;
+ wddma[unit].wdd_dmadone = ide_pci_dmadone;
+ wddma[unit].wdd_dmastatus = ide_pci_status;
+ wddma[unit].wdd_iobase = ide_pci_iobase;
+ wddma[unit].wdd_altiobase = ide_pci_altiobase;
- bmista_1 = inb(iobase_bm_1 + BMISTA_PORT);
- bmista_2 = inb(iobase_bm_2 + BMISTA_PORT);
-
- if (!ide_pci_softc_cookies_initted) {
- LIST_INIT(&softc.cookies);
- ide_pci_softc_cookies_initted = 1;
- }
+ /*
+ * This code below is mighty bogus. The config entries for the
+ * isa_devtab_bio are plugged in before the standard ISA bios scan.
+ * This is our "hack" way to simulate a dynamic assignment of I/O
+ * addresses, from a PCI device to an ISA probe. Sorry :-).
+ */
+ if (iobase_wd_1 != IO_WD1) {
+ struct isa_device *dvp, *dvp1, *dvup, *dvup1;
+ for( dvp = isa_devtab_bio;
+ dvp->id_id != 0;
+ dvp++) {
+ if ((dvp->id_driver == &wdcdriver) && (dvp->id_iobase == 0)) {
+ int biotabunit;
+ biotabunit = dvp->id_unit * 2;
+ dvp->id_iobase = iobase_wd_1;
+ dvp1 = dvp + 1;
+ dvp1->id_iobase = iobase_wd_2;
+ printf("ide_pci%d: adding drives to controller %d:",
+ unit, biotabunit);
+ for(dvup = isa_biotab_wdc;
+ dvup->id_id != 0;
+ dvup++) {
+ if (dvup->id_driver != &wdcdriver)
+ continue;
+ if (dvup->id_unit != biotabunit)
+ continue;
+
+ dvup->id_iobase = dvp->id_iobase;
+ printf(" %d", dvup->id_unit);
+ dvup++;
+
+ pci_map_int(tag, wdintr, (void *) dvp->id_unit, &bio_imask);
+ if (dvup->id_id == 0)
+ break;
+
+ if (dvup->id_unit == biotabunit + 1) {
+ dvup->id_iobase = dvp->id_iobase;
+ printf(" %d", dvup->id_unit);
+ dvup++;
+ if (dvup->id_id == 0) {
+ iobase_wd_2 = 0;
+ break;
+ }
+ }
+
+ if (dvup->id_unit == biotabunit + 2) {
+ pci_map_int(tag, wdintr, (void *) ((int) dvp->id_unit + 1), &bio_imask);
+ dvup->id_iobase = dvp1->id_iobase;
+ printf(" %d", dvup->id_unit);
+ dvup++;
+ if (dvup->id_id == 0) {
+ break;
+ }
+ }
+
+ if (dvup->id_unit == biotabunit + 3) {
+ pci_map_int(tag, wdintr, (void *) ((int) dvp->id_unit + 1), &bio_imask);
+ dvup->id_iobase = dvp1->id_iobase;
+ printf(" %d", dvup->id_unit);
+ }
+
+ break;
+ }
+ printf("\n");
+ break;
+ }
+ }
+ }
- if (iobase_wd_1 != 0) {
- cookie = mkcookie(iobase_wd_1, 0, 0, iobase_bm_1, tag, type, vp);
- if (bootverbose)
- vp->vendor_status(cookie);
- cookie = mkcookie(iobase_wd_1, 0, 1, iobase_bm_1, tag, type, vp);
- if (bootverbose) {
- vp->vendor_status(cookie);
-
- printf("ide_pci: busmaster 0 status: %02x from port: %08x\n",
- bmista_1, iobase_bm_1+BMISTA_PORT);
-
- if (bmista_1 & BMISTA_DMA0CAP)
- printf("ide_pci: ide0:0 has been configured for DMA by BIOS\n");
- if (bmista_1 & BMISTA_DMA1CAP)
- printf("ide_pci: ide0:1 has been configured for DMA by BIOS\n");
- }
- }
- if (bmista_1 & BMISTA_SIMPLEX || bmista_2 & BMISTA_SIMPLEX) {
- printf("ide_pci: controller is simplex, no DMA on secondary channel\n");
- }
- else if (iobase_wd_2 != 0) {
- cookie = mkcookie(iobase_wd_2, 1, 0, iobase_bm_2, tag, type, vp);
- if (bootverbose)
- vp->vendor_status(cookie);
- cookie = mkcookie(iobase_wd_2, 1, 1, iobase_bm_2, tag, type, vp);
- if (bootverbose) {
- vp->vendor_status(cookie);
-
- printf("ide_pci: busmaster 1 status: %02x from port: %08x\n",
- bmista_2, iobase_bm_2+BMISTA_PORT);
-
- if (bmista_2 & BMISTA_DMA0CAP)
- printf("ide_pci: ide1:0 has been configured for DMA by BIOS\n");
- if (bmista_2 & BMISTA_DMA1CAP)
- printf("ide_pci: ide1:1 has been configured for DMA by BIOS\n");
- }
- }
+ bmista_1 = inb(iobase_bm_1 + BMISTA_PORT);
+ bmista_2 = inb(iobase_bm_2 + BMISTA_PORT);
+
+ if (!ide_pci_softc_cookies_initted) {
+ LIST_INIT(&softc.cookies);
+ ide_pci_softc_cookies_initted = 1;
+ }
+
+ if (iobase_wd_1 != 0) {
+ cookie = mkcookie(iobase_wd_1,
+ ctlridx,
+ 0,
+ iobase_bm_1,
+ tag,
+ type,
+ vp,
+ altiobase_wd_1);
+ if (bootverbose)
+ vp->vendor_status(cookie);
+ cookie = mkcookie(iobase_wd_1,
+ ctlridx,
+ 1,
+ iobase_bm_1,
+ tag,
+ type,
+ vp,
+ altiobase_wd_1);
+ if (bootverbose) {
+ vp->vendor_status(cookie);
+
+ printf("ide_pci: busmaster 0 status: %02x from port: %08x\n",
+ bmista_1, iobase_bm_1+BMISTA_PORT);
+
+ if (bmista_1 & BMISTA_DMA0CAP)
+ printf("ide_pci: ide0:0 has been configured for DMA by BIOS\n");
+ if (bmista_1 & BMISTA_DMA1CAP)
+ printf("ide_pci: ide0:1 has been configured for DMA by BIOS\n");
+ }
+ }
+ if (bmista_1 & BMISTA_SIMPLEX || bmista_2 & BMISTA_SIMPLEX) {
+ printf("ide_pci: controller is simplex, no DMA on secondary channel\n");
+ } else if (iobase_wd_2 != 0) {
+ cookie = mkcookie(iobase_wd_2,
+ ctlridx + 1,
+ 0,
+ iobase_bm_2,
+ tag,
+ type,
+ vp,
+ altiobase_wd_2);
+ if (bootverbose)
+ vp->vendor_status(cookie);
+ cookie = mkcookie(iobase_wd_2,
+ ctlridx + 1,
+ 1,
+ iobase_bm_2,
+ tag,
+ type,
+ vp,
+ altiobase_wd_2);
+ if (bootverbose) {
+ vp->vendor_status(cookie);
+
+ printf("ide_pci: busmaster 1 status: %02x from port: %08x\n",
+ bmista_2, iobase_bm_2+BMISTA_PORT);
+
+ if (bmista_2 & BMISTA_DMA0CAP)
+ printf("ide_pci: ide1:0 has been configured for DMA by BIOS\n");
+ if (bmista_2 & BMISTA_DMA1CAP)
+ printf("ide_pci: ide1:1 has been configured for DMA by BIOS\n");
+ }
+ }
}
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
+ "ide_pci",
+ ide_pci_probe,
+ ide_pci_attach,
+ &ide_pci_count,
+ 0
};
DATA_SET(pcidevice_set, ide_pci_device);
@@ -735,16 +1187,17 @@ DATA_SET(pcidevice_set, ide_pci_device);
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;
- }
+ struct ide_pci_cookie *cp;
+
+ cp = softc.cookies.lh_first;
+ while(cp) {
+ if (cp->ctlr == unit &&
+ ((iobase_wd == 0) || (cp->iobase_wd == iobase_wd)))
+ break;
+ cp = cp->le.le_next;
+ }
- return cp;
+ return cp;
}
/*
@@ -758,19 +1211,19 @@ ide_pci_dmainit(void *cookie,
int(*wdcmd)(int, void *),
void *wdinfo)
{
- struct ide_pci_cookie *cp = cookie;
-
- /*
- * If the controller status indicates that DMA is configured already,
- * we flounce happily away
- */
- if (inb(cp->iobase_bm + BMISTA_PORT) &
+ struct ide_pci_cookie *cp = cookie;
+ /*
+ * If the controller status indicates that DMA is configured already,
+ * we flounce happily away
+ */
+ if (inb(cp->iobase_bm + BMISTA_PORT) &
((cp->unit == 0) ? BMISTA_DMA0CAP : BMISTA_DMA1CAP))
- return 1;
+ return 1;
- /* We take a stab at it with device-dependent code */
- return(cp->vs.vendor_dmainit(cp, wp, wdcmd, wdinfo));
+ /* We take a stab at it with device-dependent code */
+ 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.
@@ -778,19 +1231,19 @@ ide_pci_dmainit(void *cookie,
static int
ide_pci_dmaverify(void *xcp, char *vaddr, u_long count, int dir)
{
- int badfu;
+ int badfu;
- /*
- * check for nonaligned or odd-length Stuff
- */
- badfu = ((unsigned int)vaddr & 1) || (count & 1);
+ /*
+ * check for nonaligned or odd-length Stuff
+ */
+ badfu = ((unsigned int)vaddr & 1) || (count & 1);
#ifdef DIAGNOSTIC
- if (badfu) {
- printf("ide_pci: dmaverify odd vaddr or length, ");
- printf("vaddr = %08x length = %08x\n", (int)vaddr, count);
- }
+ if (badfu) {
+ printf("ide_pci: dmaverify odd vaddr or length, ");
+ printf("vaddr = %08x length = %08x\n", (int)vaddr, count);
+ }
#endif
- return (!badfu);
+ return (!badfu);
}
/*
@@ -801,155 +1254,180 @@ ide_pci_dmaverify(void *xcp, char *vaddr, u_long count, int dir)
static int
ide_pci_dmasetup(void *xcp, char *vaddr, u_long vcount, int dir)
{
- struct ide_pci_cookie *cp = xcp;
- struct ide_pci_prd *prd;
- int i;
- u_long firstpage;
- u_long prd_base, prd_count;
- u_long nbase, ncount, nend;
- int iobase_bm;
- static int trashmore = 0xdeadbeef;
- static int *trashmore_p = 0;
- u_long count, checkcount;
-
- prd = cp->prd;
+ struct ide_pci_cookie *cp = xcp;
+ struct ide_pci_prd *prd;
+ int i;
+ u_long firstpage;
+ u_long prd_base, prd_count;
+ u_long nbase, ncount, nend;
+ int iobase_bm;
+ static int trashmore = 0xdeadbeef;
+ static int *trashmore_p = 0;
+ u_long count, checkcount;
- count = vcount;
+ prd = cp->prd;
- i = 0;
-
- iobase_bm = cp->iobase_bm;
-
- if (count == 0) {
- printf("ide_pci: dmasetup 0-length transfer, ");
- printf("vaddr = %08x length = %08x\n", (int)vaddr, count);
- return 1;
- }
+ count = vcount;
- /* Generate first PRD entry, which may be non-aligned. */
+ i = 0;
- firstpage = PAGE_SIZE - ((u_long)vaddr & PAGE_MASK);
+ iobase_bm = cp->iobase_bm;
- prd_base = vtophys(vaddr);
- prd_count = MIN(count, firstpage);
-
- vaddr += prd_count;
- count -= prd_count;
-
- /* Step through virtual pages, coalescing as needed. */
- while (count) {
-
- nbase = vtophys(vaddr);
- ncount = MIN(count, PAGE_SIZE);
- nend = nbase + ncount;
-
- /* Coalesce if physically contiguous and not crossing 64k boundary. */
- if ((prd_base + prd_count == nbase) &&
- ((((nend - 1) ^ prd_base) & ~0xffff) == 0)) {
- prd_count += ncount;
- } else {
- prd[i].prd_base = prd_base;
- prd[i].prd_count = (prd_count & 0xffff);
- i++;
- if (i >= PRD_MAX_SEGS) {
- printf("wd82371: too many segments in PRD table\n");
+ if (count == 0) {
+ printf("ide_pci: dmasetup 0-length transfer, ");
+ printf("vaddr = %08x length = %08x\n", (int)vaddr, count);
return 1;
- }
- prd_base = nbase;
- prd_count = ncount;
}
- vaddr += ncount;
- count -= ncount;
- }
- /* Write last PRD entry. */
- prd[i].prd_base = prd_base;
- prd[i].prd_count = (prd_count & 0xffff) | PRD_EOT_BIT;
+ /* Generate first PRD entry, which may be non-aligned. */
+
+ firstpage = PAGE_SIZE - ((u_long)vaddr & PAGE_MASK);
+
+ prd_base = vtophys(vaddr);
+ prd_count = MIN(count, firstpage);
+
+ vaddr += prd_count;
+ count -= prd_count;
+
+ /* Step through virtual pages, coalescing as needed. */
+ while (count) {
+ nbase = vtophys(vaddr);
+ ncount = MIN(count, PAGE_SIZE);
+ nend = nbase + ncount;
+
+ /*
+ * Coalesce if physically contiguous and not crossing
+ * 64k boundary.
+ */
+ if ((prd_base + prd_count == nbase) &&
+ ((((nend - 1) ^ prd_base) & ~0xffff) == 0)) {
+ prd_count += ncount;
+ } else {
+ prd[i].prd_base = prd_base;
+ prd[i].prd_count = (prd_count & 0xffff);
+ i++;
+ if (i >= PRD_MAX_SEGS) {
+ printf("wd82371: too many segments in PRD table\n");
+ return 1;
+ }
+ prd_base = nbase;
+ prd_count = ncount;
+ }
+ vaddr += ncount;
+ count -= ncount;
+ }
+
+ /* Write last PRD entry. */
+ prd[i].prd_base = prd_base;
+ prd[i].prd_count = (prd_count & 0xffff) | PRD_EOT_BIT;
#ifdef DIAGNOSTIC
- /* sanity check the transfer for length and page-alignment, at least */
- checkcount = 0;
- for (i = 0;; i++) {
- unsigned int modcount;
-
- modcount = prd[i].prd_count & 0xffffe;
- if (modcount == 0) modcount = 0x10000;
- checkcount += modcount;
- if (i != 0 && ((prd[i].prd_base & PAGE_MASK) != 0)) {
- printf("ide_pci: dmasetup() diagnostic fails-- unaligned page\n");
- return 1;
+ /* sanity check the transfer for length and page-alignment, at least */
+ checkcount = 0;
+ for (i = 0;; i++) {
+ unsigned int modcount;
+
+ modcount = prd[i].prd_count & 0xffffe;
+ if (modcount == 0) modcount = 0x10000;
+ checkcount += modcount;
+ if (i != 0 && ((prd[i].prd_base & PAGE_MASK) != 0)) {
+ printf("ide_pci: dmasetup() diagnostic fails-- unaligned page\n");
+ return 1;
+ }
+ if (prd[i].prd_count & PRD_EOT_BIT)
+ break;
}
- if (prd[i].prd_count & PRD_EOT_BIT)
- break;
- }
- if (checkcount != vcount) {
- printf("ide_pci: dmasetup() diagnostic fails-- bad length\n");
- return 1;
- }
+ if (checkcount != vcount) {
+ printf("ide_pci: dmasetup() diagnostic fails-- bad length\n");
+ return 1;
+ }
#endif
- /* Set up PRD base register */
- outl(iobase_bm + BMIDTP_PORT, vtophys(prd));
+ /* Set up PRD base register */
+ outl(iobase_bm + BMIDTP_PORT, vtophys(prd));
- /* Set direction of transfer */
- outb(iobase_bm + BMICOM_PORT, (dir == B_READ) ? BMICOM_READ_WRITE : 0);
+ /* Set direction of transfer */
+ outb(iobase_bm + BMICOM_PORT, (dir == B_READ) ? BMICOM_READ_WRITE : 0);
- /* Clear interrupt and error bits */
- outb(iobase_bm + BMISTA_PORT,
- (inb(iobase_bm + BMISTA_PORT)
- | (BMISTA_INTERRUPT | BMISTA_DMA_ERROR)));
+ /* Clear interrupt and error bits */
+ outb(iobase_bm + BMISTA_PORT,
+ (inb(iobase_bm + BMISTA_PORT)
+ | (BMISTA_INTERRUPT | BMISTA_DMA_ERROR)));
- return 0;
+ return 0;
}
static void
ide_pci_dmastart(void *xcp)
{
- struct ide_pci_cookie *cp = xcp;
- int iobase_bm;
+ struct ide_pci_cookie *cp = xcp;
+ int iobase_bm;
- iobase_bm = cp->iobase_bm;
+ iobase_bm = cp->iobase_bm;
- outb(iobase_bm + BMICOM_PORT,
- inb(iobase_bm + BMICOM_PORT) | BMICOM_STOP_START);
+ outb(iobase_bm + BMICOM_PORT,
+ inb(iobase_bm + BMICOM_PORT) | BMICOM_STOP_START);
}
static int
ide_pci_dmadone(void *xcp)
{
- struct ide_pci_cookie *cp = xcp;
- int iobase_bm, status;
+ struct ide_pci_cookie *cp = xcp;
+ int iobase_bm, status;
- status = ide_pci_status(xcp);
- iobase_bm = cp->iobase_bm;
+ status = ide_pci_status(xcp);
+ iobase_bm = cp->iobase_bm;
- outb(iobase_bm + BMICOM_PORT,
- inb(iobase_bm + BMICOM_PORT) & ~BMICOM_STOP_START);
+ outb(iobase_bm + BMICOM_PORT,
+ inb(iobase_bm + BMICOM_PORT) & ~BMICOM_STOP_START);
- return status;
+ return status;
}
static int
ide_pci_status(void *xcp)
{
- struct ide_pci_cookie *cp = xcp;
- int iobase_bm, status, bmista;
+ struct ide_pci_cookie *cp = xcp;
+ int iobase_bm, status, bmista;
- status = 0;
- iobase_bm = cp->iobase_bm;
+ status = 0;
+ iobase_bm = cp->iobase_bm;
- bmista = inb(iobase_bm + BMISTA_PORT);
+ bmista = inb(iobase_bm + BMISTA_PORT);
- if (bmista & BMISTA_INTERRUPT)
- status |= WDDS_INTERRUPT;
- if (bmista & BMISTA_DMA_ERROR)
- status |= WDDS_ERROR;
- if (bmista & BMISTA_DMA_ACTIVE)
- status |= WDDS_ACTIVE;
+ if (bmista & BMISTA_INTERRUPT)
+ status |= WDDS_INTERRUPT;
+ if (bmista & BMISTA_DMA_ERROR)
+ status |= WDDS_ERROR;
+ if (bmista & BMISTA_DMA_ACTIVE)
+ status |= WDDS_ACTIVE;
- return status;
+ return status;
}
+static int
+ide_pci_altiobase(void *xcp)
+{
+ struct ide_pci_cookie *cp = xcp;
+ if (cp == 0) {
+ return 0;
+ } else {
+ return cp->altiobase_wd;
+ }
+}
+
+static int
+ide_pci_iobase(void *xcp)
+{
+ struct ide_pci_cookie *cp = xcp;
+ if (cp == 0) {
+ return 0;
+ } else {
+ return cp->iobase_wd;
+ }
+}
+
+#endif
#endif /* NPCI > 0 */
diff --git a/sys/pci/pcireg.h b/sys/pci/pcireg.h
index c24237f..9e8c85e 100644
--- a/sys/pci/pcireg.h
+++ b/sys/pci/pcireg.h
@@ -26,7 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pcireg.h,v 1.17 1997/05/28 20:37:19 se Exp $
+ * $Id: pcireg.h,v 1.18 1997/06/01 16:00:43 peter Exp $
*
*/
@@ -241,6 +241,7 @@
#define PCI_CLASS_REG 0x08
#define PCI_CLASS_MASK 0xff000000
#define PCI_SUBCLASS_MASK 0x00ff0000
+#define PCI_REVISION_MASK 0x000000ff
#define PCI_CLASS_PREHISTORIC 0x00000000
#define PCI_SUBCLASS_PREHISTORIC_VGA 0x00010000
#define PCI_CLASS_MASS_STORAGE 0x01000000
OpenPOWER on IntegriCloud