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>
This commit is contained in:
parent
ab71361364
commit
e871e61fcf
@ -2,7 +2,7 @@
|
||||
# LINT -- config file for checking all the sources, tries to pull in
|
||||
# as much of the source tree as it can.
|
||||
#
|
||||
# $Id: LINT,v 1.366 1997/09/16 07:45:31 joerg Exp $
|
||||
# $Id: LINT,v 1.367 1997/09/19 15:25:48 jmg Exp $
|
||||
#
|
||||
# NB: You probably don't want to try running a kernel built from this
|
||||
# file. Instead, you should start from GENERIC, and add options from
|
||||
@ -763,8 +763,23 @@ controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr
|
||||
# allowed to probe for 32 bit transfers, but will allow multi-sector
|
||||
# transfers up to the maximum that the drive supports.
|
||||
#
|
||||
|
||||
# If you are using a PCI controller that is not running in compatibility
|
||||
# mode (for example, it is a 2nd IDE PCI interface), then use config line(s)
|
||||
# such as:
|
||||
#
|
||||
#controller wdc2 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
|
||||
#disk wd4 at wdc2 drive 0
|
||||
#disk wd5 at wdc2 drive 1
|
||||
#
|
||||
#controller wdc3 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
|
||||
#disk wd6 at wdc3 drive 0
|
||||
#disk wd7 at wdc3 drive 1
|
||||
#
|
||||
# Note that the above config would be useful for a Promise card, when used
|
||||
# on a MB that already has a PIIX controller. Note the bogus irq and port
|
||||
# entries. These are automatically filled in by the IDE/PCI support.
|
||||
#
|
||||
|
||||
controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr
|
||||
disk wd0 at wdc0 drive 0
|
||||
disk wd1 at wdc0 drive 1
|
||||
|
@ -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
|
||||
|
@ -2,7 +2,7 @@
|
||||
# LINT -- config file for checking all the sources, tries to pull in
|
||||
# as much of the source tree as it can.
|
||||
#
|
||||
# $Id: LINT,v 1.366 1997/09/16 07:45:31 joerg Exp $
|
||||
# $Id: LINT,v 1.367 1997/09/19 15:25:48 jmg Exp $
|
||||
#
|
||||
# NB: You probably don't want to try running a kernel built from this
|
||||
# file. Instead, you should start from GENERIC, and add options from
|
||||
@ -763,8 +763,23 @@ controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr
|
||||
# allowed to probe for 32 bit transfers, but will allow multi-sector
|
||||
# transfers up to the maximum that the drive supports.
|
||||
#
|
||||
|
||||
# If you are using a PCI controller that is not running in compatibility
|
||||
# mode (for example, it is a 2nd IDE PCI interface), then use config line(s)
|
||||
# such as:
|
||||
#
|
||||
#controller wdc2 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
|
||||
#disk wd4 at wdc2 drive 0
|
||||
#disk wd5 at wdc2 drive 1
|
||||
#
|
||||
#controller wdc3 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
|
||||
#disk wd6 at wdc3 drive 0
|
||||
#disk wd7 at wdc3 drive 1
|
||||
#
|
||||
# Note that the above config would be useful for a Promise card, when used
|
||||
# on a MB that already has a PIIX controller. Note the bogus irq and port
|
||||
# entries. These are automatically filled in by the IDE/PCI support.
|
||||
#
|
||||
|
||||
controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr
|
||||
disk wd0 at wdc0 drive 0
|
||||
disk wd1 at wdc0 drive 1
|
||||
|
@ -2,7 +2,7 @@
|
||||
# LINT -- config file for checking all the sources, tries to pull in
|
||||
# as much of the source tree as it can.
|
||||
#
|
||||
# $Id: LINT,v 1.366 1997/09/16 07:45:31 joerg Exp $
|
||||
# $Id: LINT,v 1.367 1997/09/19 15:25:48 jmg Exp $
|
||||
#
|
||||
# NB: You probably don't want to try running a kernel built from this
|
||||
# file. Instead, you should start from GENERIC, and add options from
|
||||
@ -763,8 +763,23 @@ controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr
|
||||
# allowed to probe for 32 bit transfers, but will allow multi-sector
|
||||
# transfers up to the maximum that the drive supports.
|
||||
#
|
||||
|
||||
# If you are using a PCI controller that is not running in compatibility
|
||||
# mode (for example, it is a 2nd IDE PCI interface), then use config line(s)
|
||||
# such as:
|
||||
#
|
||||
#controller wdc2 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
|
||||
#disk wd4 at wdc2 drive 0
|
||||
#disk wd5 at wdc2 drive 1
|
||||
#
|
||||
#controller wdc3 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr
|
||||
#disk wd6 at wdc3 drive 0
|
||||
#disk wd7 at wdc3 drive 1
|
||||
#
|
||||
# Note that the above config would be useful for a Promise card, when used
|
||||
# on a MB that already has a PIIX controller. Note the bogus irq and port
|
||||
# entries. These are automatically filled in by the IDE/PCI support.
|
||||
#
|
||||
|
||||
controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr
|
||||
disk wd0 at wdc0 drive 0
|
||||
disk wd1 at wdc0 drive 1
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
|
||||
* $Id: wd.c,v 1.137 1997/09/10 12:31:38 joerg Exp $
|
||||
* $Id: wd.c,v 1.138 1997/09/13 16:12:12 joerg Exp $
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
@ -66,6 +66,7 @@
|
||||
|
||||
#if NWDC > 0
|
||||
|
||||
#include "pci.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/dkbad.h>
|
||||
#include <sys/systm.h>
|
||||
@ -157,11 +158,13 @@ struct disk {
|
||||
#endif
|
||||
int dk_unit; /* physical unit number */
|
||||
int dk_lunit; /* logical unit number */
|
||||
int dk_interface; /* interface (two ctrlrs per interface) */
|
||||
char dk_state; /* control state */
|
||||
u_char dk_status; /* copy of status reg. */
|
||||
u_char dk_error; /* copy of error reg. */
|
||||
u_char dk_timeout; /* countdown to next timeout */
|
||||
int dk_port; /* i/o port base */
|
||||
int dk_altport; /* altstatus port base */
|
||||
#ifdef DEVFS
|
||||
void *dk_bdev; /* devfs token for whole disk */
|
||||
void *dk_cdev; /* devfs token for raw whole disk */
|
||||
@ -204,7 +207,7 @@ static struct {
|
||||
int b_active;
|
||||
} wdtab[NWDC];
|
||||
|
||||
struct wddma wddma;
|
||||
struct wddma wddma[NWDC];
|
||||
|
||||
#ifdef notyet
|
||||
static struct buf rwdbuf[NWD]; /* buffers for raw IO */
|
||||
@ -276,6 +279,8 @@ static int
|
||||
wdprobe(struct isa_device *dvp)
|
||||
{
|
||||
int unit = dvp->id_unit;
|
||||
void *cookie;
|
||||
int interface;
|
||||
struct disk *du;
|
||||
|
||||
if (unit >= NWDC)
|
||||
@ -286,8 +291,21 @@ wdprobe(struct isa_device *dvp)
|
||||
return (0);
|
||||
bzero(du, sizeof *du);
|
||||
du->dk_ctrlr = dvp->id_unit;
|
||||
interface = du->dk_ctrlr / 2;
|
||||
du->dk_interface = interface;
|
||||
#if !defined(DISABLE_PCI_IDE) && (NPCI > 0)
|
||||
if (wddma[interface].wdd_candma) {
|
||||
du->dk_dmacookie = wddma[interface].wdd_candma(dvp->id_iobase, du->dk_ctrlr);
|
||||
du->dk_port = dvp->id_iobase;
|
||||
du->dk_altport = wddma[interface].wdd_altiobase(du->dk_dmacookie);
|
||||
} else {
|
||||
du->dk_port = dvp->id_iobase;
|
||||
du->dk_altport = du->dk_port + wd_ctlr;
|
||||
}
|
||||
#else
|
||||
du->dk_port = dvp->id_iobase;
|
||||
|
||||
du->dk_altport = du->dk_port + wd_ctlr;
|
||||
#endif
|
||||
|
||||
/* check if we have registers that work */
|
||||
outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */
|
||||
@ -317,14 +335,16 @@ wdprobe(struct isa_device *dvp)
|
||||
goto reset_ok;
|
||||
#endif
|
||||
DELAY(RECOVERYTIME);
|
||||
if (wdreset(du) != 0)
|
||||
if (wdreset(du) != 0) {
|
||||
goto nodevice;
|
||||
}
|
||||
reset_ok:
|
||||
|
||||
/* execute a controller only command */
|
||||
if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0
|
||||
|| wdwait(du, 0, TIMEOUT) < 0)
|
||||
|| wdwait(du, 0, TIMEOUT) < 0) {
|
||||
goto nodevice;
|
||||
}
|
||||
|
||||
/*
|
||||
* drive(s) did not time out during diagnostic :
|
||||
@ -338,7 +358,6 @@ reset_ok:
|
||||
* drive 2. (This seems to contradict the ATA spec.)
|
||||
*/
|
||||
du->dk_error = inb(du->dk_port + wd_error);
|
||||
/* printf("Error : %x\n", du->dk_error); */
|
||||
if(du->dk_error != 0x01) {
|
||||
if(du->dk_error & 0x80) { /* drive 1 failure */
|
||||
|
||||
@ -776,7 +795,7 @@ wdstart(int ctrlr)
|
||||
(bp->b_flags & B_READ) ? "read" : "write",
|
||||
bp->b_bcount, blknum);
|
||||
else
|
||||
printf(" %d)%x", du->dk_skip, inb(du->dk_port + wd_altsts));
|
||||
printf(" %d)%x", du->dk_skip, inb(du->dk_altport));
|
||||
#endif
|
||||
|
||||
lp = &du->dk_dd;
|
||||
@ -844,7 +863,7 @@ wdstart(int ctrlr)
|
||||
du->dk_currentiosize = 1;
|
||||
} else {
|
||||
if((du->dk_flags & DKFL_USEDMA) &&
|
||||
wddma.wdd_dmaverify(du->dk_dmacookie,
|
||||
wddma[du->dk_interface].wdd_dmaverify(du->dk_dmacookie,
|
||||
(void *)((int)bp->b_un.b_addr +
|
||||
du->dk_skip * DEV_BSIZE),
|
||||
du->dk_bc,
|
||||
@ -893,7 +912,7 @@ wdstart(int ctrlr)
|
||||
}
|
||||
|
||||
if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) {
|
||||
wddma.wdd_dmaprep(du->dk_dmacookie,
|
||||
wddma[du->dk_interface].wdd_dmaprep(du->dk_dmacookie,
|
||||
(void *)((int)bp->b_un.b_addr +
|
||||
du->dk_skip * DEV_BSIZE),
|
||||
du->dk_bc,
|
||||
@ -909,7 +928,7 @@ wdstart(int ctrlr)
|
||||
printf("cylin %ld head %ld sector %ld addr %x sts %x\n",
|
||||
cylin, head, sector,
|
||||
(int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE,
|
||||
inb(du->dk_port + wd_altsts));
|
||||
inb(du->dk_altport));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -937,7 +956,7 @@ wdstart(int ctrlr)
|
||||
|
||||
/* if this is a DMA op, start DMA and go away until it's done. */
|
||||
if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) {
|
||||
wddma.wdd_dmastart(du->dk_dmacookie);
|
||||
wddma[du->dk_interface].wdd_dmastart(du->dk_dmacookie);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1049,10 +1068,10 @@ wdintr(int unit)
|
||||
/* finish off DMA */
|
||||
if (du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) {
|
||||
/* XXX SMP boxes sometimes generate an early intr. Why? */
|
||||
if ((wddma.wdd_dmastatus(du->dk_dmacookie) & WDDS_INTERRUPT)
|
||||
if ((wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie) & WDDS_INTERRUPT)
|
||||
== 0)
|
||||
return;
|
||||
dmastat = wddma.wdd_dmadone(du->dk_dmacookie);
|
||||
dmastat = wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie);
|
||||
}
|
||||
|
||||
du->dk_timeout = 0;
|
||||
@ -1834,20 +1853,22 @@ failed:
|
||||
du->dk_multi = wp->wdp_nsecperint & 0xff;
|
||||
wdsetmulti(du);
|
||||
|
||||
du->dk_dmacookie = NULL;
|
||||
/*
|
||||
* check drive's DMA capability
|
||||
*/
|
||||
if (wddma[du->dk_interface].wdd_candma) {
|
||||
du->dk_dmacookie = wddma[du->dk_interface].wdd_candma(du->dk_port, du->dk_ctrlr);
|
||||
/* does user want this? */
|
||||
if ((du->cfg_flags & WDOPT_DMA) &&
|
||||
if ((du->cfg_flags & WDOPT_DMA) &&
|
||||
/* have we got a DMA controller? */
|
||||
(wddma.wdd_candma &&
|
||||
(du->dk_dmacookie = wddma.wdd_candma(du->dk_port,
|
||||
du->dk_unit))) &&
|
||||
/* can said drive do DMA? */
|
||||
(wddma.wdd_dmainit(du->dk_dmacookie, wp, wdsetmode, du)))
|
||||
|
||||
du->dk_flags |= DKFL_USEDMA;
|
||||
du->dk_dmacookie &&
|
||||
/* can said drive do DMA? */
|
||||
wddma[du->dk_interface].wdd_dmainit(du->dk_dmacookie, wp, wdsetmode, du)) {
|
||||
du->dk_flags |= DKFL_USEDMA;
|
||||
}
|
||||
} else {
|
||||
du->dk_dmacookie = NULL;
|
||||
}
|
||||
|
||||
#ifdef WDDEBUG
|
||||
printf(
|
||||
@ -2210,28 +2231,28 @@ wdflushirq(struct disk *du, int old_ipl)
|
||||
static int
|
||||
wdreset(struct disk *du)
|
||||
{
|
||||
int wdc, err = 0;
|
||||
int err = 0;
|
||||
|
||||
if ((du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) && du->dk_dmacookie)
|
||||
wddma.wdd_dmadone(du->dk_dmacookie);
|
||||
wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie);
|
||||
|
||||
wdc = du->dk_port;
|
||||
(void)wdwait(du, 0, TIMEOUT);
|
||||
outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST);
|
||||
outb(du->dk_altport, WDCTL_IDS | WDCTL_RST);
|
||||
DELAY(10 * 1000);
|
||||
outb(wdc + wd_ctlr, WDCTL_IDS);
|
||||
outb(du->dk_altport, WDCTL_IDS);
|
||||
#ifdef ATAPI
|
||||
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0)
|
||||
err = 1; /* no IDE drive found */
|
||||
du->dk_error = inb(wdc + wd_error);
|
||||
du->dk_error = inb(du->dk_port + wd_error);
|
||||
if (du->dk_error != 0x01)
|
||||
err = 1; /* the drive is incompatible */
|
||||
#else
|
||||
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
|
||||
|| (du->dk_error = inb(wdc + wd_error)) != 0x01)
|
||||
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0) {
|
||||
printf("wdreset: error1: 0x%x\n", du->dk_error);
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
outb(wdc + wd_ctlr, WDCTL_4BIT);
|
||||
outb(du->dk_altport, WDCTL_4BIT);
|
||||
return (err);
|
||||
}
|
||||
|
||||
@ -2273,7 +2294,7 @@ wdtimeout(void *cdu)
|
||||
if (du->dk_dmacookie)
|
||||
printf("wd%d: wdtimeout() DMA status %b\n",
|
||||
du->dk_lunit,
|
||||
wddma.wdd_dmastatus(du->dk_dmacookie),
|
||||
wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie),
|
||||
WDDS_BITS);
|
||||
}
|
||||
wdunwedge(du);
|
||||
@ -2384,8 +2405,9 @@ wdwait(struct disk *du, u_char bits_wanted, int timeout)
|
||||
* command completion.
|
||||
*/
|
||||
}
|
||||
if ((status & bits_wanted) == bits_wanted)
|
||||
if ((status & bits_wanted) == bits_wanted) {
|
||||
return (status & WDCS_ERR);
|
||||
}
|
||||
}
|
||||
if (timeout < TIMEOUT)
|
||||
/*
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)wdreg.h 7.1 (Berkeley) 5/9/91
|
||||
* $Id: wdreg.h,v 1.12.2.3 1997/01/14 17:32:07 bde Exp $
|
||||
* $Id: wdreg.h,v 1.19 1997/09/04 18:49:48 sos Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -260,7 +260,7 @@ int wdformat(struct buf *bp);
|
||||
* WDDS_* constants below.
|
||||
*/
|
||||
struct wddma {
|
||||
void *(*wdd_candma) /* returns a cookie if can do DMA */
|
||||
void *(*wdd_candma) /* returns a cookie if PCI */
|
||||
__P((int ctlr, int drive));
|
||||
int (*wdd_dmaverify) /* verify that request is DMA-able */
|
||||
__P((void *cookie, char *vaddr, u_long len, int direction));
|
||||
@ -277,6 +277,10 @@ struct wddma {
|
||||
struct wdparams *wp,
|
||||
int(wdcmd)__P((int mode, void *wdinfo)),
|
||||
void *wdinfo));
|
||||
int (*wdd_iobase) /* returns iobase address */
|
||||
__P((void *cookie));
|
||||
int (*wdd_altiobase) /* returns altiobase address */
|
||||
__P((void *cookie));
|
||||
};
|
||||
|
||||
/* logical status bits returned by wdd_dmastatus */
|
||||
@ -305,6 +309,6 @@ struct wddma {
|
||||
#define WDDMA_UDMA1 0x41
|
||||
#define WDDMA_UDMA2 0x42
|
||||
|
||||
extern struct wddma wddma;
|
||||
extern struct wddma wddma[];
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
1648
sys/pci/ide_pci.c
1648
sys/pci/ide_pci.c
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user