From owner-freebsd-current Wed Jan 13 11:49:47 1999 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id LAA14441 for freebsd-current-outgoing; Wed, 13 Jan 1999 11:49:47 -0800 (PST) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from pinhead.parag.codegen.com (ppp-sfx201--103.sirius.net [205.134.235.103]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id LAA14433 for ; Wed, 13 Jan 1999 11:49:41 -0800 (PST) (envelope-from parag@cgt.com) Received: from pinhead.parag.codegen.com (localhost.parag.codegen.com [127.0.0.1]) by pinhead.parag.codegen.com (8.9.1/8.8.8) with ESMTP id LAA79529 for ; Wed, 13 Jan 1999 11:48:33 -0800 (PST) (envelope-from parag@pinhead.parag.codegen.com) Message-Id: <199901131948.LAA79529@pinhead.parag.codegen.com> X-Mailer: exmh version 2.0.2 2/24/98 To: freebsd-current@FreeBSD.ORG Subject: Re: potential ide_pci.c bugster In-Reply-To: Message from "Joseph T. Lee" of "Wed, 13 Jan 1999 02:19:08 PST." <19990113021908.A11598@la.best.com> X-Face: =O'Kj74icvU|oS*<7gS/8'\Pbpm}okVj*@UC!IgkmZQAO!W[|iBiMs*|)n*`X ]pW%m>Oz_mK^Gdazsr.Z0/JsFS1uF8gBVIoChGwOy{EK=<6g?aHE`[\S]C]T0Wm X-URL: http://www.codegen.com Mime-Version: 1.0 Content-Type: multipart/mixed ; boundary="==_Exmh_-2445626140" Date: Wed, 13 Jan 1999 11:48:32 -0800 From: Parag Patel Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG This is a multipart MIME message. --==_Exmh_-2445626140 Content-Type: text/plain; charset=us-ascii In another aside, I still haven't seen my patches for the CMD PCI646U2 UDMA IDE controller come by in the main sources. 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. The extra argument requires mods to i386/isa/wd.c and wdreg.h to pass in the extra argument to pci_ide_candma(). I've appended the latest patches from the kernel sources (as off last night) to this note, if anyone wants to give them a try. Some controllers like the CMD may require that DMA be always initialized regardless of whatever the bit settings are. BTW - the folks who are wiring magic numbers in the file for various chipsets - please create a macro at the top for each one to more easily identify them. It makes the code quite a bit more readable and prevents typo errors. Thank-you. I hope this is of some help. -- Parag Patel --==_Exmh_-2445626140 Content-Type: text/plain ; name="ide-diffs"; charset=us-ascii 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