Date: Thu, 14 Jan 1999 00:54:33 -0500 (EST) From: "Andrew Atrens" <atrens@nortelnetworks.com> To: Parag Patel <parag@cgt.com> Cc: freebsd-current@FreeBSD.ORG Subject: Re: potential ide_pci.c bugster Message-ID: <Pine.BSF.4.05.9901140010100.385-200000@hcarp00g.ca.nortel.com> In-Reply-To: <199901131948.LAA79529@pinhead.parag.codegen.com>
next in thread | previous in thread | raw e-mail | index | archive | help
--==_Exmh_-2445626140
Content-type: TEXT/PLAIN; CHARSET="US-ASCII"
Content-ID: <Pine.BSF.4.05.9901140010102.385@hcarp00g.ca.nortel.com>
On Wed, 13 Jan 1999, Parag Patel wrote:
> I had found and fixed one major problem with the current IDE code. The
> problem is that the pci_ide_candma() routine needs an additional
> argument to correctly identify the drive *and* controller that can
> handle DMA. I suspect this may also be causing trouble with other
> drives and controllers.
Hmm. Though I agree that pci_ide_candma() in its current state is broken,
I'm not convinced that it is the intention of this function to determine
whether the drive can do DMA, therefore a third argument (drive unit) is
_not required_. Here's a relevant passage from wd.c:
1893 * check drive's DMA capability
1894 */
1895 if (wddma[du->dk_interface].wdd_candma) {
1896 du->dk_dmacookie =
wddma[du->dk_interface].wdd_candma(du->dk_port,
du->dk_ctrlr);
1897 /* does user want this? */
1898 if ((du->cfg_flags & WDOPT_DMA) &&
1899 /* have we got a DMA controller? */
1900 du->dk_dmacookie &&
1901 /* can said drive do DMA? */
1902 wddma[du->dk_interface].wdd_dmainit(du->dk_dmacookie,
wp, wdsetmode, du)) {
1903 du->dk_flags |= DKFL_USEDMA;
1904 }
1905 } else {
1906 du->dk_dmacookie = NULL;
1907 }
If you believe the comments, then the call to _candma() on line 1896
ascertains whether or not the _controller_ is capable of DMA.
Then, on line 1902 a call to _dmainit() actually establishes whether the
_drive_ can handle DMA.
> I hope this is of some help.
Yes, thank you. :)
Cheers,
Andrew.
--
+----------------------------------------------------+
= Andrew Atrens - Nortel Networks (atrens@nortel.ca) =
= P.O. Box 3511, Station C Ottawa, Canada =
= =
= All opinions expressed are mine, not Nortel's. =
+----------------------------------------------------+
--==_Exmh_-2445626140
Content-type: TEXT/PLAIN; NAME="ide-diffs"; CHARSET="us-ascii"
Content-ID: <Pine.BSF.4.05.9901140010103.385@hcarp00g.ca.nortel.com>
Content-Description: ide-diffs
Content-Disposition: ATTACHMENT; FILENAME=ide-diffs
Index: pci/ide_pci.c
===================================================================
RCS file: /src/freebsd/src/sys/pci/ide_pci.c,v
retrieving revision 1.23
diff -c -r1.23 ide_pci.c
*** ide_pci.c 1999/01/13 04:40:50 1.23
--- ide_pci.c 1999/01/13 18:59:30
***************
*** 61,66 ****
--- 61,67 ----
#endif
#define PROMISE_ULTRA33 0x4d33105a
+ #define CMD_PCI646U2_ID 0x06461095
struct ide_pci_cookie; /* structs vendor_fns, ide_pci_cookie are recursive */
***************
*** 159,165 ****
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 *),
--- 160,166 ----
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 *),
***************
*** 723,728 ****
--- 724,818 ----
promise_status
};
+ static void
+ cmd646_status(struct ide_pci_cookie *cookie)
+ {
+ /*int iobase_bm = cookie->iobase_bm;*/
+ pcici_t tag = cookie->tag;
+ int i;
+
+ printf("cmd646_status: %d:%d register dump:\n",
+ cookie->ctlr, cookie->unit);
+
+ for (i = 0; i < 0x80; i += 16)
+ {
+ printf(" %2x:%8lx %8lx %8lx %8lx\n",
+ i, pci_conf_read(tag, i), pci_conf_read(tag, i + 4),
+ pci_conf_read(tag, i + 8), pci_conf_read(tag, i + 12));
+ }
+ }
+
+ static int
+ cmd646_dmainit(struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int(*wdcmd)(int, void *),
+ void *wdinfo)
+ {
+ int iobase_bm = cookie->iobase_bm;
+ /*int ctlr = cookie->ctlr;*/
+ int unit = cookie->unit;
+ int mrdmode, bmista, udidetcr, r;
+ #define BMRDMODE 1
+ #define BUDIDETCR 3
+
+ if (udma_mode(wp) >= 2)
+ {
+ mrdmode = inb(iobase_bm + BMRDMODE);
+ udidetcr = inb(iobase_bm + BUDIDETCR);
+ bmista = inb(iobase_bm + BMISTA_PORT);
+
+ outb(iobase_bm + BMRDMODE, mrdmode | 0x08C);
+ outb(iobase_bm + BUDIDETCR, udidetcr | (unit ? 0x2 : 0x1));
+ outb(iobase_bm + BMISTA_PORT,
+ bmista | (unit ? BMISTA_DMA1CAP : BMISTA_DMA0CAP) |
+ BMISTA_DMA_ERROR);
+
+ if (bootverbose)
+ cmd646_status(cookie);
+
+ /* set the drive to Ultra-DMA mode */
+ r = wdcmd(WDDMA_UDMA2, wdinfo);
+
+ if (!r)
+ {
+ printf("cmd646_dmainit: setting DMA mode failed\n");
+ return 0;
+ }
+
+ return 1;
+ }
+
+ if (pio_mode(wp) >= 4 && mwdma_mode(wp) >= 2)
+ {
+ bmista = inb(iobase_bm + BMISTA_PORT);
+ outb(iobase_bm + BMISTA_PORT,
+ bmista | (unit ? BMISTA_DMA1CAP : BMISTA_DMA0CAP) |
+ BMISTA_DMA_ERROR);
+
+ if (bootverbose)
+ cmd646_status(cookie);
+
+ /* set the drive to DMA mode */
+ r = wdcmd(WDDMA_MDMA2, wdinfo);
+
+ if (!r)
+ {
+ printf("cmd646_dmainit: setting DMA mode failed\n");
+ return 0;
+ }
+
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static struct vendor_fns vs_cmd646 =
+ {
+ cmd646_dmainit,
+ cmd646_status
+ };
+
/* Intel PIIX, PIIX3, and PIIX4 IDE controller subfunctions */
static void
intel_piix_dump_drive(char *ctlr,
***************
*** 1170,1175 ****
--- 1260,1267 ----
return ("Cyrix 5530 Bus-master IDE controller");
if (type == 0x522910b9)
return ("Acer Aladdin IV/V (M5229) Bus-master IDE controller");
+ if (type == CMD_PCI646U2_ID)
+ return ("CMD PCI646U2 Ultra/33 IDE controller");
if (data & 0x8000)
return ("PCI IDE controller (busmaster capable)");
#ifndef CMD640
***************
*** 1201,1207 ****
/* 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)) {
--- 1293,1299 ----
/* set up vendor-specific stuff */
type = pci_conf_read(tag, PCI_ID_REG);
! if (type != PROMISE_ULTRA33 && type != CMD_PCI646U2_ID) {
/* is it busmaster capable? bail if not */
class = pci_conf_read(tag, PCI_CLASS_REG);
if (!(class & 0x8000)) {
***************
*** 1237,1252 ****
printf("cyrix 5530\n");
vp = &vs_cyrix_5530;
break;
case 0x522910B9: /* Acer Aladdin IV/V (M5229) */
vp = &vs_acer;
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;
--- 1329,1351 ----
printf("cyrix 5530\n");
vp = &vs_cyrix_5530;
break;
+
case 0x522910B9: /* Acer Aladdin IV/V (M5229) */
vp = &vs_acer;
break;
+
+ case CMD_PCI646U2_ID:
+ /* CMD PCI646U2-based controllers */
+ vp = &vs_cmd646;
+ break;
+
default:
/* everybody else */
vp = &vs_generic;
break;
}
! if (type != PROMISE_ULTRA33 && type != CMD_PCI646U2_ID) {
if ((class & 0x100) == 0) {
iobase_wd_1 = IO_WD1;
altiobase_wd_1 = iobase_wd_1 + wd_altsts;
***************
*** 1321,1327 ****
printf(" %d", dvup->id_unit);
dvup++;
! pci_map_int(tag, wdintr, (void *) dvp->id_unit, &bio_imask);
if (dvup->id_id == 0)
break;
--- 1420,1426 ----
printf(" %d", dvup->id_unit);
dvup++;
! pci_map_int(tag, (pci_inthand_t *)wdintr, (void *) dvp->id_unit, &bio_imask);
if (dvup->id_id == 0)
break;
***************
*** 1336,1342 ****
}
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++;
--- 1435,1441 ----
}
if (dvup->id_unit == biotabunit + 2) {
! pci_map_int(tag, (pci_inthand_t *)wdintr, (void *) ((int) dvp->id_unit + 1), &bio_imask);
dvup->id_iobase = dvp1->id_iobase;
printf(" %d", dvup->id_unit);
dvup++;
***************
*** 1346,1352 ****
}
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);
}
--- 1445,1451 ----
}
if (dvup->id_unit == biotabunit + 3) {
! pci_map_int(tag, (pci_inthand_t *)wdintr, (void *) ((int) dvp->id_unit + 1), &bio_imask);
dvup->id_iobase = dvp1->id_iobase;
printf(" %d", dvup->id_unit);
}
***************
*** 1453,1465 ****
* Return a cookie if we can do DMA on the specified (iobase_wd, unit).
*/
static void *
! ide_pci_candma(int iobase_wd, int unit)
{
struct ide_pci_cookie *cp;
cp = softc.cookies.lh_first;
while(cp) {
! if (cp->unit == unit &&
((iobase_wd == 0) || (cp->iobase_wd == iobase_wd)))
break;
cp = cp->le.le_next;
--- 1552,1564 ----
* Return a cookie if we can do DMA on the specified (iobase_wd, 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;
***************
*** 1483,1491 ****
/*
* 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 */
--- 1582,1592 ----
/*
* If the controller status indicates that DMA is configured already,
* we flounce happily away
+ * [CMD 646 part should always be initialized]
*/
! if (cp->type != CMD_PCI646U2_ID &&
! 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 */
Index: pci/wdc_p.c
===================================================================
RCS file: /src/freebsd/src/sys/pci/wdc_p.c,v
retrieving revision 1.4
diff -c -r1.4 wdc_p.c
*** wdc_p.c 1998/12/14 06:32:57 1.4
--- wdc_p.c 1998/12/14 11:17:24
***************
*** 40,45 ****
--- 40,46 ----
*/
#define CMD640B_PCI_ID 0x06401095
+ #define CMD_PCI646U2_ID 0x06461095
static const char* wdc_pci_probe __P((pcici_t tag, pcidi_t type));
static void wdc_pci_attach __P((pcici_t config_id, int unit));
***************
*** 62,67 ****
--- 63,71 ----
if (type == CMD640B_PCI_ID)
return "CMD 640B IDE";
+ if (type == CMD_PCI646U2_ID)
+ return "CMD 646U2 IDE";
+
return NULL;
}
***************
*** 69,74 ****
--- 73,80 ----
wdc_pci_attach(pcici_t config_id, int unit)
{
if (pci_conf_read(config_id, PCI_ID_REG) == CMD640B_PCI_ID)
+ wdc_pci(Q_CMD640B);
+ if (pci_conf_read(config_id, PCI_ID_REG) == CMD_PCI646U2_ID)
wdc_pci(Q_CMD640B);
}
Index: i386/isa/wd.c
===================================================================
RCS file: /src/freebsd/src/sys/i386/isa/wd.c,v
retrieving revision 1.184
diff -c -r1.184 wd.c
*** wd.c 1999/01/12 01:04:38 1.184
--- wd.c 1999/01/12 11:21:17
***************
*** 315,321 ****
#if !defined(DISABLE_PCI_IDE) && (NPCI > 0)
#ifdef ALI_V
if ((wddma[interface].wdd_candma) &&
! ((du->dk_dmacookie = wddma[interface].wdd_candma(dvp->id_iobase,du->dk_ctrlr)) != NULL))
{
du->dk_port = dvp->id_iobase;
du->dk_altport = wddma[interface].wdd_altiobase(du->dk_dmacookie);
--- 315,321 ----
#if !defined(DISABLE_PCI_IDE) && (NPCI > 0)
#ifdef ALI_V
if ((wddma[interface].wdd_candma) &&
! ((du->dk_dmacookie = wddma[interface].wdd_candma(dvp->id_iobase,du->dk_ctrlr, unit)) != NULL))
{
du->dk_port = dvp->id_iobase;
du->dk_altport = wddma[interface].wdd_altiobase(du->dk_dmacookie);
***************
*** 325,331 ****
}
#endif
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 {
--- 325,331 ----
}
#endif
if (wddma[interface].wdd_candma) {
! du->dk_dmacookie = wddma[interface].wdd_candma(dvp->id_iobase,du->dk_ctrlr, unit);
du->dk_port = dvp->id_iobase;
du->dk_altport = wddma[interface].wdd_altiobase(du->dk_dmacookie);
} else {
***************
*** 1098,1104 ****
du = wddrives[dkunit(bp->b_dev)];
/* finish off DMA */
! if (du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) {
/* XXX SMP boxes sometimes generate an early intr. Why? */
if ((wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie) & WDDS_INTERRUPT)
!= 0)
--- 1098,1104 ----
du = wddrives[dkunit(bp->b_dev)];
/* finish off DMA */
! if ((du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) == (DKFL_DMA|DKFL_USEDMA)) {
/* XXX SMP boxes sometimes generate an early intr. Why? */
if ((wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie) & WDDS_INTERRUPT)
!= 0)
***************
*** 1893,1899 ****
* 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) &&
/* have we got a DMA controller? */
--- 1893,1899 ----
* 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, du->dk_unit);
/* does user want this? */
if ((du->cfg_flags & WDOPT_DMA) &&
/* have we got a DMA controller? */
Index: i386/isa/wdreg.h
===================================================================
RCS file: /src/freebsd/src/sys/i386/isa/wdreg.h,v
retrieving revision 1.24
diff -c -r1.24 wdreg.h
*** wdreg.h 1999/01/12 01:04:38 1.24
--- wdreg.h 1999/01/12 11:21:17
***************
*** 262,268 ****
*/
struct wddma {
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));
int (*wdd_dmaprep) /* prepare DMA hardware */
--- 262,268 ----
*/
struct wddma {
void *(*wdd_candma) /* returns a cookie if PCI */
! __P((int iobase, int ctlr, int drive));
int (*wdd_dmaverify) /* verify that request is DMA-able */
__P((void *cookie, char *vaddr, u_long len, int direction));
int (*wdd_dmaprep) /* prepare DMA hardware */
--==_Exmh_-2445626140--
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.05.9901140010100.385-200000>
