summaryrefslogtreecommitdiffstats
path: root/sys/pci
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 /sys/pci
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>
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/ide_pci.c1698
-rw-r--r--sys/pci/pcireg.h3
2 files changed, 1090 insertions, 611 deletions
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