Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Jan 1999 11:48:32 -0800
From:      Parag Patel <parag@cgt.com>
To:        freebsd-current@FreeBSD.ORG
Subject:   Re: potential ide_pci.c bugster 
Message-ID:  <199901131948.LAA79529@pinhead.parag.codegen.com>
In-Reply-To: Message from "Joseph T. Lee" <nugundam@la.best.com>  of "Wed, 13 Jan 1999 02:19:08 PST." <19990113021908.A11598@la.best.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199901131948.LAA79529>