summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2000-03-15 21:58:27 +0000
committerpeter <peter@FreeBSD.org>2000-03-15 21:58:27 +0000
commit45794bc5bd0b30eef05107c5e3c1de51faa62ee1 (patch)
tree5fabc6768818490ce991f820616b44d9841fb20e /sys/pci
parentc79db8767162cd0aed9fbb47c04b0460fdb7d3cb (diff)
downloadFreeBSD-src-45794bc5bd0b30eef05107c5e3c1de51faa62ee1.zip
FreeBSD-src-45794bc5bd0b30eef05107c5e3c1de51faa62ee1.tar.gz
Remove left over pci_ide* after wd removal.
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/ide_pci.c1876
1 files changed, 0 insertions, 1876 deletions
diff --git a/sys/pci/ide_pci.c b/sys/pci/ide_pci.c
deleted file mode 100644
index 1a226b9..0000000
--- a/sys/pci/ide_pci.c
+++ /dev/null
@@ -1,1876 +0,0 @@
-/*
- * Copyright 1996 Massachusetts Institute of Technology
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby
- * granted, provided that both the above copyright notice and this
- * permission notice appear in all copies, that both the above
- * copyright notice and this permission notice appear in all
- * supporting documentation, and that the name of M.I.T. not be used
- * in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. M.I.T. makes
- * no representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied
- * warranty.
- *
- * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
- * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
- * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#include <i386/isa/wdreg.h>
-#ifdef PC98
-#include <pc98/pc98/pc98.h>
-#else
-#include <i386/isa/isa.h>
-#endif
-#include <i386/isa/isa_device.h>
-
-#include <pci/pcivar.h>
-#include <pci/pcireg.h>
-#include <pci/ide_pcireg.h>
-
-#ifndef MIN
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#endif
-
-#define PROMISE_ULTRA33 0x4d33105a
-#define CMD640B_PCI_ID 0x06401095
-
-struct ide_pci_cookie; /* structs vendor_fns, ide_pci_cookie are recursive */
-
-struct vendor_fns {
- int (*vendor_dmainit) /* initialize DMA controller and drive */
- (struct ide_pci_cookie *cookie,
- struct wdparams *wp,
- int (*wdcmd)(int, void *),
- void *);
-
- void (*vendor_status) /* prints off DMA timing info */
- (struct ide_pci_cookie *cookie);
-};
-
-/*
- * XXX the fact that this list keeps all kinds of info on PCI controllers
- * is pretty grotty-- much of this should be replaced by a proper integration
- * of PCI probes into the wd driver.
- * XXX if we're going to support native-PCI controllers, we also need to
- * keep the address of the IDE control block register, which is something wd.c
- * needs to know, which is why this info is in the wrong place.
- */
-
-struct ide_pci_cookie {
- LIST_ENTRY(ide_pci_cookie) le;
- int iobase_wd;
- int 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;
-};
-
-static int
-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 int
-sis_5591_dmainit(struct ide_pci_cookie *cookie,
- struct wdparams *wp,
- int (*wdcmd)(int, void *),
- void *wdinfo);
-
-static void
-sis_5591_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
-acer_status(struct ide_pci_cookie *cookie);
-
-static int
-acer_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);
-
-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);
-
-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 altiobase_wd);
-
-
-
-static void ide_pci_attach(pcici_t tag, int unit);
-static void *ide_pci_candma(int, int, int);
-static int ide_pci_dmainit(void *,
- struct wdparams *,
- int (*)(int, void *),
- void *);
-
-static int ide_pci_dmaverify(void *, char *, u_long, int);
-static int ide_pci_dmasetup(void *, char *, u_long, int);
-static void ide_pci_dmastart(void *);
-static int ide_pci_dmadone(void *);
-static int ide_pci_status(void *);
-static int ide_pci_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 struct isa_driver wdcdriver;
-
-/*
- * PRD_ALLOC_SIZE should be something that will not be allocated across a 64k
- * boundary.
- * PRD_MAX_SEGS is defined to be the maximum number of segments required for
- * a transfer on an IDE drive, for an xfer that is linear in virtual memory.
- * PRD_BUF_SIZE is the size of the buffer needed for a PRD table.
- */
-#define PRD_ALLOC_SIZE PAGE_SIZE
-#define PRD_MAX_SEGS ((256 * 512 / PAGE_SIZE) + 1)
-#define PRD_BUF_SIZE PRD_MAX_SEGS * 8
-
-static void *prdbuf = 0;
-static void *prdbuf_next = 0;
-
-/*
- * Hardware specific IDE controller code. All vendor-specific code
- * for handling IDE timing and other chipset peculiarities should be
- * encapsulated here.
- */
-
-/* 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
-generic_dmainit(struct ide_pci_cookie *cookie,
- struct wdparams *wp,
- 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 there are examples where this approach is now known to be
- * broken, at least on systems based on Intel chipsets.
- */
-
- 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);
- /* If we're here, then this controller is most likely not set
- for UDMA, even if the drive may be. Make the drive wise
- up. */
-
- if(!wdcmd(WDDMA_MDMA2, wdinfo))
- printf("generic_dmainit: could not set multiword DMA mode!\n");
- 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");
-}
-
-static struct vendor_fns vs_generic =
-{
- generic_dmainit,
- generic_status
-};
-
-/* VIA Technologies "82C571" PCI-IDE controller core */
-
-static void
-via_571_status(struct ide_pci_cookie *cookie)
-{
- 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);
- }
-
- 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");
-
- printf("via_571_status: busmaster status read retry %s\n",
- (word40[1] & 0x08) ? "enabled" : "disabled");
-
-
- printf("via_571_status: %s drive %d data setup=%d active=%d recovery=%d\n",
- unitno < 2 ? "primary" : "secondary",
- unitno & 1,
- ((u_int)(word40[3] >> ((3 - unitno) * 2)) & 3) + 1,
- ((u_int)(word40[2] >> (((3 - unitno) * 8) + 4)) & 0x0f) + 1,
- ((u_int)(word40[2] >> ((3 - unitno) * 8)) & 0x0f) + 1);
-
- if (ctlr == 0)
- printf("via_571_status: primary ctrl active=%d recovery=%d\n",
- ((u_int)(word40[3] >> 28) & 0x0f) + 1,
- ((u_int)(word40[2] >> 24) & 0x0f) + 1);
- else
- printf("via_571_status: secondary ctrl active=%d recovery=%d\n",
- ((u_int)(word40[3] >> 20) & 0x0f) + 1,
- ((u_int)(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)
-{
- 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 = 0x40000000 >> (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("via_571_dmainit: setting ultra DMA mode 2\n");
- if (!wdcmd(WDDMA_UDMA2, wdinfo)) {
- printf("via_571_dmainit: setting DMA mode failed\n");
- return 0;
- }
-
- if (bootverbose)
- via_571_status(cookie);
- return 1;
-
- }
-
- /* 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("via_571_dmainit: setting multiword DMA mode 2\n");
- if (!wdcmd(WDDMA_MDMA2, wdinfo)) {
- printf("via_571_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 |= 0xc000 >> (cookie->ctlr * 2);
-
- /* 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
-};
-
-/* Cyrix Cx5530 Courtesy of Whistle Communications */
-
-/*
- * Verify that controller can handle a dma request for cp. Should
- * not affect any hardware or driver state.
- * Special version for 5530 that allows only transfers on 16 byte boundaries.(!)
- * (Yes the Cyrix 5530 can only UDMA to cache-line boundaries.(bleh!))
- * Luckily nearly all disk IO is to kernel bufers which are page alligned.
- * They may fix this in some other version of the chip, but it's in the latest
- * at this time (Jan 1999).
- */
-static int
-cyrix_5530_dmaverify(void *xcp, char *vaddr, u_long count, int dir)
-{
- int badfu;
-
- /*
- * check for nonaligned or odd-length Stuff
- */
- badfu = ((unsigned int)vaddr & 0xf) || (count & 0xf);
-#ifdef DIAGNOSTIC
- if (badfu) {
- printf("ide_pci: dmaverify odd vaddr or length, ");
- printf("vaddr = %p length = %08lx\n", (void *)vaddr, count);
- }
-#endif
- return (!badfu);
-}
-
-/*
- * XXX Unit number handling may be broken in the Cx5530 modules.
- * It has only been checked with a single drive.
- * 12MByte/Sec transfer rates were seen with Quantum Fireball drives
- * with negligable CPU usage.
- */
-static void
-cyrix_5530_status(struct ide_pci_cookie *cookie)
-{
- int iobase_wd;
- int ctlr, unit;
- int iobase_bm;
- pcici_t tag;
- pcidi_t type;
- u_long PIO_config;
- u_long DMA_config;
- int 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;
-
- PIO_config = inl(iobase_bm + (unit * 0x10) + 0x20);
- DMA_config = inl(iobase_bm + (unit * 0x10) + 0x24);
-
-
- printf("cyrix_5530_status: %s:%u IDE PIO cfg: 0x%08lx\n",
- (ctlr ? "Secondary" : "Primary"), unit, PIO_config);
- printf("cyrix_5530_status: %s:%u IDE DMA cfg: 0x%08lx\n",
- (ctlr ? "Secondary" : "Primary"), unit, DMA_config);
-}
-
-/*
- * 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
-cyrix_5530_dmainit(struct ide_pci_cookie *cookie,
- struct wdparams *wp,
- int(*wdcmd)(int, void *),
- void *wdinfo)
-{
- u_long pci_revision;
- int unitno;
- int iobase_bm;
- int unit;
- int drivemode;
- int mode;
- int regval;
-
- /*cookie->unit = 0; */ /* XXX */
- unit = cookie->unit;
- pci_revision = pci_conf_read(cookie->tag, PCI_CLASS_REG) &
- PCI_REVISION_MASK;
-
- unitno = cookie->ctlr * 2 + unit;
- iobase_bm = cookie->iobase_bm;
-
- printf("Setting using 0x%x\n", iobase_bm);
- if ((cookie->ctlr == 0) && (unit == 0)) /* XXX */
- outb(iobase_bm + (unit * 0x10) + BMISTA_PORT, 0xe6);
- /* If it's a UDMA drive on a '5530, set it up */
- /*
- * depending on what the drive can do,
- * set the correct modes,
- */
- printf("wd%d: mw=0x%x, pio=0x%x, pcirev=0x%lx, udma=0x%x\n",
- unitno,
- mwdma_mode(wp), pio_mode(wp),
- pci_revision, udma_mode(wp));
- if (/* pci_revision >= 1 && */ udma_mode(wp) >= 0) {
- switch(udma_mode(wp)) {
- case 0:
- mode = 0;
- drivemode = WDDMA_UDMA0;
- regval = 0x00921250;
- break;
- default: /* newer modes not supported */
- case 2:
-#if 0
-/*
- * XXX The 5530 can do mode 2 but if you do use it, it will block all
- * access to the PCI bus (and thus the ISA bus, PICs, PIT, etc. etc.) until the
- * transfer is complete. Mode 2 swamps the 5530 so much it can't really cope
- * with any other operations. Therefore, use mode 1 for drives that can
- * do mode 2 (or more). (FALL THROUGH)
- */
-
-
- mode = 2;
- drivemode = WDDMA_UDMA2;
- regval = 0x00911030;
- break;
-#endif
- case 1:
- mode = 1;
- drivemode = WDDMA_UDMA1;
- regval = 0x00911140;
- break;
- }
- /*
- * With the Cx5530, drive configuration
- * should come *after* the controller configuration,
- * to make sure the controller sees
- * the command and does the right thing.
- */
- /* Set UDMA mode on drive */
- if (bootverbose)
- printf("cyrix_5530_dmainit: set UDMA mode %d\n", mode);
- outl(iobase_bm+0x24 + (unit * 16), regval);
- if (!wdcmd(drivemode, wdinfo)) {
- printf("cyrix_5530_dmainit: setting DMA mode failed\n");
- return 0;
- }
-
- if (bootverbose)
- cyrix_5530_status(cookie);
- return 1;
-
- }
-
- /* otherwise, try and program it for MW DMA mode 2 */
- else if (mwdma_mode(wp) >= 0 && pio_mode(wp) >= 4) {
-
- switch(mwdma_mode(wp)) {
- case 0:
- mode = 0;
- drivemode = WDDMA_MDMA0;
- regval = 0x00017771;
- break;
- case 1:
- mode = 1;
- drivemode = WDDMA_MDMA1;
- regval = 0x00012121;
- break;
- default: /* newer modes not supported */
- case 2:
- mode = 2;
- drivemode = WDDMA_MDMA2;
- regval = 0x00002020;
-
- break;
- }
- /* Set multiword DMA mode 2 on drive */
- if (bootverbose)
- printf("cyrix_5530_dmainit: multiword DMA mode %d\n",
- mode);
- if (!wdcmd(drivemode, wdinfo)) {
- printf("cyrix_5530_dmainit: setting DMA mode failed\n");
- return 0;
- }
-
- /* Configure the controller appropriately for MWDMA mode */
-
- outl(iobase_bm + 0x24 + (unit * 16), regval);
-
- if (bootverbose)
- cyrix_5530_status(cookie);
-
- return 1;
-
- }
- /*
- * Always set the PIO mode values.
- */
- switch(pio_mode(wp)) {
- case 0:
- mode = 0;
- drivemode = WDDMA_MDMA0;
- regval = 0x0000E132;
- break;
- case 1:
- mode = 1;
- drivemode = WDDMA_MDMA1;
- regval = 0x00001812;
- break;
- case 2:
- mode = 2;
- drivemode = WDDMA_MDMA1;
- regval = 0x00024020;
- break;
- case 3:
- mode = 3;
- drivemode = WDDMA_MDMA1;
- regval = 0x00032010;
- break;
- default: /* newer modes not supported */
- case 4:
- mode = 4;
- drivemode = WDDMA_MDMA2;
- regval = 0x00040010;
-
- break;
- }
- outl(iobase_bm + 0x20 + (unit * 16), regval);
- printf("cyrix_5530_dmainit: setting PIO mode %d\n", mode);
- return 0;
-}
-
-
-static struct vendor_fns vs_cyrix_5530 =
-{
- cyrix_5530_dmainit,
- cyrix_5530_status
-};
-
-
-static void
-promise_status(struct ide_pci_cookie *cookie)
-{
- pcici_t tag;
- int i;
- 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",
- (u_long)port0_command, (u_long)port0_altstatus, (u_long)port1_command,
- (u_long)port1_altstatus);
- printf(
- "promise_status: dma control blk address: 0x%lx, int: %d, irq: %d\n",
- (u_long)dma_block, (u_int)(lat_and_interrupt >> 8) & 0xff,
- (u_int)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,
- promise_status
-};
-
-/* Intel PIIX, PIIX3, and PIIX4 IDE controller subfunctions */
-static void
-intel_piix_dump_drive(char *ctlr,
- int sitre,
- int is_piix4,
- int word40,
- int word44,
- int word48,
- int word4a,
- int drive)
-{
- char *ms;
-
- if (!sitre)
- ms = "master/slave";
- else if (drive == 0)
- ms = "master";
- else
- ms = "slave";
-
- printf("intel_piix_status: %s %s sample = %d, %s recovery = %d\n",
- ctlr,
- ms,
- 5 - ((sitre && drive) ?
- ((word44 >> 2) & 3) :
- ((word40 >> 12) & 3)),
- ms,
- 4 - ((sitre && drive) ?
- ((word44 >> 0) & 3) :
- ((word40 >> 8) & 3)));
-
- word40 >>= (drive * 4);
- printf("intel_piix_status: %s %s fastDMAonly %s, pre/post %s,\n\
-intel_piix_status: IORDY sampling %s,\n\
-intel_piix_status: fast PIO %s%s\n",
- ctlr,
- (drive == 0) ? "master" : "slave",
- (word40 & 8) ? "enabled" : "disabled",
- (word40 & 4) ? "enabled" : "disabled",
- (word40 & 2) ? "enabled" : "disabled",
- (word40 & 1) ? "enabled" : "disabled",
- ((word40 & 9) == 9) ? " (overridden by fastDMAonly)" : "" );
-
- 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;
- 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)
-{
-
- /* 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;
-
- if (bootverbose)
- printf("intel_piix_dmainit: setting ultra DMA mode 2\n");
-
- if (!wdcmd(WDDMA_UDMA2, wdinfo)) {
- 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;
- }
- /*
- * 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.
- */
- else if (cookie->type == 0x12308086)
- {
- u_long word40;
-
- /* can drive do PIO 4 and MW DMA 2? */
- if (!(mwdma_mode(wp) >= 2 && 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");
- if (!wdcmd(WDDMA_MDMA2, wdinfo)) {
- printf("intel_piix_dmainit: setting DMA mode failed\n");
- return 0;
- }
- return 1;
- }
-
- /* 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");
-
- if (!wdcmd(WDDMA_MDMA2, wdinfo)) {
- 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;
- }
- return 0;
-}
-
-static struct vendor_fns vs_intel_piix =
-{
- intel_piix_dmainit,
- intel_piix_status
-};
-
-
-static void
-acer_status(struct ide_pci_cookie *cookie) {
- /* XXX does not do anything right now */
-}
-
-static int
-acer_dmainit(struct ide_pci_cookie *cookie,
- struct wdparams *wp,
- int(*wdcmd)(int, void *),
- void *wdinfo)
-{
- /* Acer Aladdin DMA setup code. UDMA looks to be sinfully easy to set
- on this thing - just one register. */
-
- u_long word54 = pci_conf_read(cookie->tag, 0x54);
-
- /* Set the default Acer FIFO settings (0x55 = 13-word depth and
- slave operation mode 1) */
-
- word54 |= 0x5555;
-
- /* Is this drive UDMA? Set it up if so... */
- if(udma_mode(wp) >= 2) {
- /* This is really easy to do. Just write 0xa (enable
- UDMA mode with 2T timing) into the word at the right
- places. */
- word54 |= (0xA << (16 + (cookie->ctlr * 8) + (cookie->unit * 4)));
-
- /* Now set the drive for UDMA2. */
- if(!wdcmd(WDDMA_UDMA2, wdinfo)) {
- printf("acer_dmainit: could not set UDMA2 mode on wdc%d:%d!\n", cookie->ctlr, cookie->unit);
- return 0;
- }
-
- /* Write the new config into the registers. I'm not
- sure if I'm doing this in the right order. */
-
- pci_conf_write(cookie->tag, 0x54, word54);
-
- } else if(mwdma_mode(wp) >= 2 && pio_mode(wp) >=4) {
-
-
- /* Otherwise, we're already set for regular DMA. */
-
- if(!wdcmd(WDDMA_MDMA2, wdinfo)) {
- printf("acer_dmainit: could not set MWDMA2 mode on wdc%d:%d!\n",
- cookie->ctlr, cookie->unit);
- return 0;
- }
- return 1;
- }
-
- return 0;
-}
-
-static struct vendor_fns vs_acer =
-{
- acer_dmainit,
- acer_status
-};
-
-/* SiS 5591 */
-
-static void
-sis_5591_status(struct ide_pci_cookie *cookie)
-{
- int iobase_wd;
- int ctlr, unit;
- int iobase_bm;
- pcici_t tag;
- pcidi_t type;
- u_int word40[5];
- int i, unitno;
- int DRTC, DATC;
- int val;
-
- 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);
- }
-
- DRTC = word40[ctlr] >> (16 * unit);
- DATC = word40[ctlr] >> (8 + 16*unit);
-
- if (unitno == 0) {
- if ((word40[4] & 0x80000) == 0) {
- val = word40[2] & 0xf;
- if (val == 0)
- val = 12;
- else if (val > 11)
- val++;
- printf ("SiS 5591 status: CRTC %d PCICLK, ", val);
- val = (word40[2] >> 8) & 0x7;
- if (val == 0)
- val = 8 ;
- else if (val > 6)
- val = 12;
- printf ("CATC %d PCICLK, applies to all IDE devices\n", val);
- } else {
- printf ("SiS 5591 status: CRTC and CATC timings are per device, taken from DRTC and DATC\n");
- }
- printf ("SiS 5591 status: burst cycles %s, fast post write control %s\n",
- ((word40[2] >> 16) & 0x80) ? "enabled" : "disabled",
- ((word40[2] >> 16) & 0x20) ? "enabled" : "disabled");
-
- }
- val = DRTC & 0xf;
- if (val == 0)
- val = 12;
- else if (val > 11)
- val++;
- printf ("SiS 5591 status: %s drive %d DRTC %d PCICLK,",
- unitno < 2 ? "primary" : "secondary",
- unitno & 1,
- val);
- val = DATC & 0x7;
- if (val == 0)
- val = 8 ;
- else if (val > 6)
- val = 12;
- printf (" DATC %d PCICLK\n", val);
- printf ("SiS 5591 status: %s drive %d Ultra DMA %s",
- unitno < 2 ? "primary" : "secondary",
- unitno & 1,
- (DATC & 0x80) ? "disabled\n" : "enabled");
- if ((DATC & 0x80) == 0)
- printf (", %d PCICLK data out\n", ((DATC >> 5) & 0x3) + 1);
- printf ("SiS 5591 status: %s drive %d postwrite %s, prefetch %s prefetch count is %d\n",
- unitno < 2 ? "primary" : "secondary",
- unitno & 1,
- ((word40[2] >> (28 + unitno)) & 1) ? "enabled" : "disabled",
- ((word40[2] >> (24 + unitno)) & 1) ? "enabled" : "disabled",
- (word40[3] >> (16 * ctlr)) & 0xffff);
- printf ("SiS 5591 status: %s drive %d has%s been configured for DMA\n",
- unitno < 2 ? "primary" : "secondary",
- unitno & 1,
- (inb(iobase_bm + BMISTA_PORT) & ((unit == 0) ? BMISTA_DMA0CAP : BMISTA_DMA1CAP)) ?
- " " : " not");
-}
-
-static int
-sis_5591_dmainit(struct ide_pci_cookie *cookie,
- struct wdparams *wp,
- int(*wdcmd)(int, void *),
- void *wdinfo)
-{
- int r;
- unsigned int workword, new, mask;
- int ctlr, unit;
- int iobase_bm;
- pcici_t tag;
- int unitno;
-
- unit = cookie->unit;
- ctlr = cookie->ctlr;
- iobase_bm = cookie->iobase_bm;
- tag = cookie->tag;
-
- unitno = ctlr * 2 + unit;
-
- if (udma_mode(wp) >= 2) {
- workword = pci_conf_read(tag, ctlr * 4 + 0x40);
-
- /* These settings are a little arbitrary. They're taken from my
- * system, where the BIOS has already set the values, but where
- * we don't detect that we're initialized because the
- * BMISTA_DMA?CAP values aren't set by the BIOS.
- * 0x8000 turns on UDMA
- * 0x2000 sets UDMA cycle time to 2 PCI clocks for data out
- * 0x0300 sets DATC to 3 PCI clocks
- * 0x0001 sets DRTC to 1 PCI clock
- */
- if (unit) {
- mask = 0x0000ffff;
- new = 0xa3010000;
- } else {
- mask = 0xffff0000;
- new = 0x0000a301;
- }
-
- workword &= mask;
- workword |= new;
-
- pci_conf_write(tag, ctlr * 4 + 0x40, workword);
-
- outb(iobase_bm + BMISTA_PORT,
- (inb(iobase_bm + BMISTA_PORT) | ((unit == 0) ? BMISTA_DMA0CAP : BMISTA_DMA1CAP)));
-
- if (bootverbose)
- printf("SiS 5591 dmainit: %s drive %d setting ultra DMA mode 2\n",
- unitno < 2 ? "primary" : "secondary",
- unitno & 1);
- r = wdcmd(WDDMA_UDMA2, wdinfo);
- if (!r) {
- printf("SiS 5591 dmainit: %s drive %d setting DMA mode failed\n",
- unitno < 2 ? "primary" : "secondary",
- unitno & 1);
- return 0;
- }
-
- if (bootverbose)
- sis_5591_status(cookie);
-
- return 1;
-
- }
-
- /* otherwise, try and program it for MW DMA mode 2 */
- else if (mwdma_mode(wp) >= 2 && pio_mode(wp) >= 4) {
- workword = pci_conf_read(tag, ctlr * 4 + 0x40);
-
- /* These settings are a little arbitrary. They're taken from my
- * system, where the BIOS has already set the values, but where
- * we don't detect that we're initialized because the
- * BMISTA_DMA?CAP values aren't set by the BIOS.
- * 0x0300 sets DATC to 3 PCI clocks
- * 0x0001 sets DRTC to 1 PCI clock
- */
- if (unit) {
- mask = 0x0000ffff;
- new = 0x03010000;
- } else {
- mask = 0xffff0000;
- new = 0x00000301;
- }
-
- workword &= mask;
- workword |= new;
-
- pci_conf_write(tag, ctlr * 4 + 0x40, workword);
-
- outb(iobase_bm + BMISTA_PORT,
- (inb(iobase_bm + BMISTA_PORT) | ((unit == 0) ? BMISTA_DMA0CAP : BMISTA_DMA1CAP)));
-
- /* Set multiword DMA mode 2 on drive */
- if (bootverbose)
- printf("SiS 5591 dmainit: %s drive %d setting multiword DMA mode 2\n",
- unitno < 2 ? "primary" : "secondary",
- unitno & 1);
- r = wdcmd(WDDMA_MDMA2, wdinfo);
- if (!r) {
- printf("SiS 5591 dmainit: %s drive %d setting DMA mode failed\n",
- unitno < 2 ? "primary" : "secondary",
- unitno & 1);
- return 0;
- }
-
- if (bootverbose)
- sis_5591_status(cookie);
-
- return 1;
-
- }
- return 0;
-}
-
-static struct vendor_fns vs_sis_5591 =
-{
- sis_5591_dmainit,
- sis_5591_status
-};
-
-/* Generic SFF-8038i code-- all code below here, except for PCI probes,
- * more or less conforms to the SFF-8038i spec as extended for PCI.
- * There should be no code that goes beyond that feature set below.
- */
-
-/* XXX mkcookie is overloaded with too many parameters */
-
-static struct ide_pci_cookie *
-mkcookie(int iobase_wd,
- int ctlr,
- int unit,
- int iobase_bm,
- pcici_t tag,
- pcidi_t type,
- struct vendor_fns *vp,
- int altiobase_wd)
-{
- struct ide_pci_cookie *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;
- 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;
- }
- 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 (((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;
- }
-
- cp->prd = prdbuf_next;
- (char *)prdbuf_next += PRD_BUF_SIZE;
-
- LIST_INSERT_HEAD(&softc.cookies, cp, le);
- return cp;
-}
-
-static const char *
-ide_pci_probe(pcici_t tag, pcidi_t type)
-{
- 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 (type == 0x01021078)
- return ("Cyrix 5530 Bus-master IDE controller");
- if (type == 0x522910b9)
- return ("Acer Aladdin IV/V (M5229) Bus-master IDE controller");
- if (type == 0x55131039)
- return ("SiS 5591 Bus-master IDE Controller");
- if (type == CMD640B_PCI_ID)
- return "CMD 640B IDE controller";
- if (data & 0x8000)
- return ("PCI IDE controller (busmaster capable)");
- else
- return ("PCI IDE controller (not busmaster capable)");
- };
- return ((char*)0);
-}
-
-static void
-ide_pci_attach(pcici_t tag, int unit)
-{
- u_long class = 0, 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 == CMD640B_PCI_ID) {
- wdc_pci(Q_CMD640B);
- return;
- }
-
- 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;
- }
- }
-
- 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;
-
- case 0x01021078: /* cyrix 5530 */
- printf("cyrix 5530\n");
- vp = &vs_cyrix_5530;
- break;
- case 0x522910B9: /* Acer Aladdin IV/V (M5229) */
- vp = &vs_acer;
- break;
- case 0x55131039: /* SiS 5591 */
- vp = &vs_sis_5591;
- break;
- default:
- /* everybody else */
- vp = &vs_generic;
- break;
- }
-
- 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;
- }
-
- iobase_bm_1 = pci_conf_read(tag, 0x20) & 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_2 = iobase_bm_1 + SFF8038_CTLR_1;
-
- wddma[unit].wdd_candma = ide_pci_candma;
- wddma[unit].wdd_dmainit = ide_pci_dmainit;
- if (type == 0x01021078 /*CYRIX_5530*/)
- wddma[unit].wdd_dmaverify = cyrix_5530_dmaverify;
- else
- 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;
- }
-
- 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);
-
- bmista_1 = inb(iobase_bm_1 + BMISTA_PORT);
- bmista_2 = inb(iobase_bm_2 + BMISTA_PORT);
- 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 (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);
-
- bmista_1 = inb(iobase_bm_1 + BMISTA_PORT);
- bmista_2 = inb(iobase_bm_2 + BMISTA_PORT);
- 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
-};
-
-COMPAT_PCI_DRIVER(ide_pci, ide_pci_device);
-
-/*
- * Return a cookie if we may be able to do DMA on the specified
- * (iobase_wd, ctlr, unit).
- */
-static void *
-ide_pci_candma(int iobase_wd, int ctlr, int unit)
-{
- struct ide_pci_cookie *cp;
-
- cp = softc.cookies.lh_first;
- while(cp) {
- if (cp->ctlr == ctlr && cp->unit == unit &&
- ((iobase_wd == 0) || (cp->iobase_wd == iobase_wd)))
- break;
- cp = cp->le.le_next;
- }
-
- return cp;
-}
-
-/*
- * Initialize controller and drive for DMA operation, including timing modes.
- * Uses data passed from the wd driver and a callback function to initialize
- * timing modes on the drive.
- */
-static int
-ide_pci_dmainit(void *cookie,
- struct wdparams *wp,
- int(*wdcmd)(int, void *),
- void *wdinfo)
-{
- struct ide_pci_cookie *cp = cookie;
- /*
- * 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;
-
- /* 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.
- */
-static int
-ide_pci_dmaverify(void *xcp, char *vaddr, u_long count, int dir)
-{
- int badfu;
-
- /*
- * check for nonaligned or odd-length Stuff
- */
- badfu = ((unsigned int)vaddr & 1) || (count & 1);
-#ifdef DIAGNOSTIC
- if (badfu) {
- printf("ide_pci: dmaverify odd vaddr or length, ");
- printf("vaddr = %p length = %08lx\n", (void *)vaddr, count);
- }
-#endif
- return (!badfu);
-}
-
-/*
- * Set up DMA for cp. It is the responsibility of the caller
- * to ensure that the controller is idle before this routine
- * is called.
- */
-static int
-ide_pci_dmasetup(void *xcp, char *vaddr, u_long 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;
- u_long count;
-
- prd = cp->prd;
-
- count = vcount;
-
- i = 0;
-
- iobase_bm = cp->iobase_bm;
-
- if (count == 0) {
- printf("ide_pci: dmasetup 0-length transfer, ");
- printf("vaddr = %p length = %08lx\n", (void *)vaddr, count);
- return 1;
- }
-
- /* Generate first PRD entry, which may be non-aligned. */
-
- firstpage = PAGE_SIZE - ((uintptr_t)vaddr & PAGE_MASK);
-
- prd_base = vtophys(vaddr);
- prd_count = MIN(count, firstpage);
-
- vaddr += prd_count;
- count -= prd_count;
-
- /*
- * Step through virtual pages.
- * Note that it is not worth trying to coalesce pages that are
- * next to each other physically, and some DMA engines (e.g.
- * Cyrix Cx5530) actually blow up if you do.
- */
- while (count) {
- nbase = vtophys(vaddr);
- ncount = MIN(count, PAGE_SIZE);
- nend = nbase + ncount;
-
- 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;
-
- /* 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);
-
- /* Clear interrupt and error bits */
- outb(iobase_bm + BMISTA_PORT,
- (inb(iobase_bm + BMISTA_PORT)
- | (BMISTA_INTERRUPT | BMISTA_DMA_ERROR)));
-
- return 0;
-}
-
-static void
-ide_pci_dmastart(void *xcp)
-{
- struct ide_pci_cookie *cp = xcp;
- int iobase_bm;
-
- iobase_bm = cp->iobase_bm;
-
- outb(iobase_bm + BMICOM_PORT,
- inb(iobase_bm + BMICOM_PORT) | BMICOM_STOP_START);
-
-}
-
-static int
-ide_pci_dmadone(void *xcp)
-{
- struct ide_pci_cookie *cp = xcp;
- int iobase_bm, status;
-
- status = ide_pci_status(xcp);
- iobase_bm = cp->iobase_bm;
-
- outb(iobase_bm + BMICOM_PORT,
- inb(iobase_bm + BMICOM_PORT) & ~BMICOM_STOP_START);
-
- return status;
-}
-
-static int
-ide_pci_status(void *xcp)
-{
- int iobase_bm, status, bmista;
-
- status = 0;
- iobase_bm = ((struct ide_pci_cookie *)xcp)->iobase_bm;
-
- 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;
- 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;
- }
-}
OpenPOWER on IntegriCloud