no root fs in CURRENT kernel

Søren Schmidt sos at DeepCore.dk
Mon Apr 19 05:29:41 PDT 2004


Michael Luetz wrote:
> Hi,
> 
> today's (Apr 19th) CURRENT can't find the root fs anymore

Thats because of the PCI code changes, it does not properly handle the 
BAR's on ATA controllers (they are special and an exception of the 
worser kind :) )

I have two patches that solves this is different ways (both attached 
below). The first one just makes the PCI code aware of the specialness 
of the ATA BAR's and takes the right action on it. The second one is not 
really for mass consumption yet, as it will try to use you ATA 
controller in "native PCI" mode if its possible. This hasn't been tested 
much yet, and I sure there are HW out there that breaks with this, but 
it would be interesting to gain more knowledge on it by getting it 
tested especially on platforms thats broken with the current code.

-- 
-Søren

-------------- next part --------------
Index: ata/ata-pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-pci.c,v
retrieving revision 1.78
diff -u -r1.78 ata-pci.c
--- ata/ata-pci.c	13 Apr 2004 09:44:20 -0000	1.78
+++ ata/ata-pci.c	17 Apr 2004 18:40:10 -0000
@@ -260,8 +260,8 @@
 
 	case ATA_ALTADDR_RID:
 	    if (ATA_MASTERDEV(dev)) {
-		start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET-2;
-		count = 4;
+		start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET;
+		count = ATA_ALTIOSIZE;
 		end = start + count - 1;
 	    }
 	    myrid = 0x14 + 8 * unit;
@@ -402,7 +402,7 @@
 	ch->r_io[i].offset = i;
     }
     ch->r_io[ATA_ALTSTAT].res = altio;
-    ch->r_io[ATA_ALTSTAT].offset = 2;
+    ch->r_io[ATA_ALTSTAT].offset = 0;
     ch->r_io[ATA_IDX_ADDR].res = io;
 
     if (ctlr->r_res1) {
Index: pci/pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/pci/pci.c,v
retrieving revision 1.245
diff -u -r1.245 pci.c
--- pci/pci.c	16 Apr 2004 15:01:54 -0000	1.245
+++ pci/pci.c	17 Apr 2004 18:59:20 -0000
@@ -824,6 +824,15 @@
 	 */
 	if (base == 0)
 		return 1;
+
+	/* if this is an ATA MASTERDEV on std addresses, resources are bogus */
+	if ((pci_get_class(dev) == PCIC_STORAGE) &&
+	    (pci_get_subclass(dev) == PCIS_STORAGE_IDE) &&
+	    (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) &&
+	    !(pci_get_progif(dev) &
+	      (PCIP_STORAGE_IDE_MODEPRIM | PCIP_STORAGE_IDE_MODESEC)))
+		return 1;
+
 	start = base;
 	end = base + (1 << ln2size) - 1;
 	count = 1 << ln2size;
-------------- next part --------------
Index: pci/pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/pci/pci.c,v
retrieving revision 1.245
diff -u -r1.245 pci.c
--- pci/pci.c	16 Apr 2004 15:01:54 -0000	1.245
+++ pci/pci.c	19 Apr 2004 06:17:37 -0000
@@ -1455,15 +1455,11 @@
 	struct resource_list_entry *rle;
 	struct resource *res;
 	uint32_t map, testval;
-	int mapsize;
+	//int mapsize;
 
 	/*
-	 * Weed out the bogons, and figure out how large the BAR/map
-	 * is.  Note: some devices have been found that are '0' after
-	 * a write of 0xffffffff.  We view these as 'special' and
-	 * allow drivers to allocate whatever they want with them.  So
-	 * far, these BARs have only appeared in certain south bridges
-	 * and ata controllers made by VIA, nVidia and AMD.
+	 * Weed out the bogons, and figure out how large the BAR/map is.
+	 * Note: we must skip these checks on ZERO BAR's.
 	 */
 	res = NULL;
 	map = pci_read_config(child, *rid, 4);
@@ -1472,16 +1468,18 @@
 	if (testval != 0) {
 		if (pci_maptype(testval) & PCI_MAPMEM) {
 			if (type != SYS_RES_MEMORY) {
-				device_printf(child,
-				    "failed: rid %#x is memory, requested %d\n",
-				    *rid, type);
+				if (bootverbose)
+					device_printf(child,
+					    "failed: rid %#x is memory, "
+					    "requested %d\n", *rid, type);
 				goto out;
 			}
 		} else {
 			if (type != SYS_RES_IOPORT) {
-				device_printf(child,
-				    "failed: rid %#x is ioport, requested %d\n",
-				    *rid, type);
+				if (bootverbose)
+					device_printf(child,
+					    "failed: rid %#x is ioport, "
+					    "requested %d\n", *rid, type);
 				goto out;
 			}
 		}
@@ -1491,11 +1489,11 @@
 		 * actually uses and we would otherwise have a
 		 * situation where we might allocate the excess to
 		 * another driver, which won't work.
-		 */
 		mapsize = pci_mapsize(testval);
 		count = 1 << mapsize;
 		if (RF_ALIGNMENT(flags) < mapsize)
 	    		flags = (flags & ~RF_ALIGNMENT_MASK) | RF_ALIGNMENT_LOG2(mapsize);
+		 */
 	}
 	else {
 		if (bootverbose)
@@ -1590,11 +1588,12 @@
 		 */
 		rle = resource_list_find(rl, type, *rid);
 		if (rle != NULL && rle->res != NULL) {
-			/* if (bootverbose) */
-			device_printf(child,
-			    "Reserved %#lx bytes for rid %#x type %d at %#lx\n",
-			    rman_get_size(rle->res), *rid, type,
-			    rman_get_start(rle->res));
+			if (bootverbose)
+				device_printf(child,
+				    "Reserved %#lx bytes for rid %#x "
+				    "type %d at %#lx\n",
+				    rman_get_size(rle->res), *rid, type,
+				    rman_get_start(rle->res));
 			if ((flags & RF_ACTIVE) && 
 			    bus_generic_activate_resource(dev, child, type,
 			    *rid, rle->res) != 0)
Index: ata/ata-chipset.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-chipset.c,v
retrieving revision 1.68
diff -u -r1.68 ata-chipset.c
--- ata/ata-chipset.c	13 Apr 2004 09:44:20 -0000	1.68
+++ ata/ata-chipset.c	18 Apr 2004 15:36:56 -0000
@@ -2350,15 +2350,15 @@
 	break;
     case SIS66:
     case SIS100OLD:
-	pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 1) | 0x04, 1);
+	pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 1) & ~0x04, 1);
 	break;
     case SIS100NEW:
     case SIS133OLD:
-	pci_write_config(dev, 0x49, pci_read_config(dev, 0x49, 1) | 0x01, 1);
+	pci_write_config(dev, 0x49, pci_read_config(dev, 0x49, 1) & ~0x01, 1);
 	break;
     case SIS133NEW:
-	pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 2) & 0xfff7, 2);
-	pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 2) & 0xfff7, 2);
+	pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 2) | 0x0008, 2);
+	pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 2) | 0x0008, 2);
 	break;
     case SISSATA:
 	pci_write_config(dev, 0x04, pci_read_config(dev, 0x04, 2) & ~0x0400, 2);
@@ -2662,7 +2662,7 @@
     struct ata_pci_controller *ctlr = device_get_softc(dev);
     int rid = ATA_IRQ_RID;
 
-    if (!ATA_MASTERDEV(dev)) {
+    if (!ata_pci_compat(dev)) {
 	if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
 						   RF_SHAREABLE | RF_ACTIVE))) {
 	    device_printf(dev, "unable to map interrupt\n");
Index: ata/ata-lowlevel.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-lowlevel.c,v
retrieving revision 1.32
diff -u -r1.32 ata-lowlevel.c
--- ata/ata-lowlevel.c	13 Apr 2004 09:44:20 -0000	1.32
+++ ata/ata-lowlevel.c	18 Apr 2004 13:16:39 -0000
@@ -563,15 +563,15 @@
 	}
     }
 
+    if (bootverbose)
+	ata_printf(ch, -1, "reset tp1 mask=%02x ostat0=%02x ostat1=%02x\n",
+		   mask, ostat0, ostat1);
+
     /* if nothing showed up there is no need to get any further */
     /* SOS is that too strong?, we just might loose devices here XXX */
     ch->devices = 0;
     if (!mask)
 	return;
-
-    if (bootverbose)
-	ata_printf(ch, -1, "reset tp1 mask=%02x ostat0=%02x ostat1=%02x\n",
-		   mask, ostat0, ostat1);
 
     /* reset (both) devices on this channel */
     ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
Index: ata/ata-pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-pci.c,v
retrieving revision 1.78
diff -u -r1.78 ata-pci.c
--- ata/ata-pci.c	13 Apr 2004 09:44:20 -0000	1.78
+++ ata/ata-pci.c	19 Apr 2004 06:15:35 -0000
@@ -62,6 +62,15 @@
 static void ata_pci_dmainit(struct ata_channel *);
 static void ata_pci_locknoop(struct ata_channel *, int);
 
+int
+ata_pci_compat(device_t dev)
+{
+    return ((pci_read_config(dev, PCIR_PROGIF, 1)&PCIP_STORAGE_IDE_MASTERDEV) &&
+            ((pci_read_config(dev, PCIR_PROGIF, 1) &
+	      (PCIP_STORAGE_IDE_MODEPRIM | PCIP_STORAGE_IDE_MODESEC)) !=
+	     (PCIP_STORAGE_IDE_MODEPRIM | PCIP_STORAGE_IDE_MODESEC)));
+}
+
 static int
 ata_pci_probe(device_t dev)
 {
@@ -155,10 +164,29 @@
 {
     struct ata_pci_controller *ctlr = device_get_softc(dev);
     u_int32_t cmd;
-    int unit;
+    u_int8_t progif;
+    int unit, prisec = 0;
+
+    /* if this device supports PCI native addressing use it */
+    progif = pci_read_config(dev, PCIR_PROGIF, 1);
+    if ((progif & 0x85) == 0x80)
+	prisec = 1;
+    if ((progif & 0x8a) == 0x8a) {
+	if (pci_read_config(dev, PCIR_BAR(0), 4) &&
+ 	    pci_read_config(dev, PCIR_BAR(2), 4)) {
+	    device_printf(dev, "setting native PCI addressing mode ");
+	    pci_write_config(dev, PCIR_PROGIF, progif | 0x05, 1);
+	    if ((pci_read_config(dev, PCIR_PROGIF, 1) & 0x05) != 0x05) {
+	        pci_write_config(dev, PCIR_PROGIF, progif & ~0x05, 1);
+		printf("failed, using compat method\n");
+	    }
+	    else
+		printf("succeded\n");
+	}
+    }
 
     /* do chipset specific setups only needed once */
-    if (ATA_MASTERDEV(dev) || pci_read_config(dev, 0x18, 4) & IOMASK)
+    if (ata_pci_compat(dev) || pci_read_config(dev, 0x18, 4) & IOMASK)
 	ctlr->channels = 2;
     else
 	ctlr->channels = 1;
@@ -185,7 +213,7 @@
 
     /* attach all channels on this controller */
     for (unit = 0; unit < ctlr->channels; unit++)
-	device_add_child(dev, "ata", ATA_MASTERDEV(dev) ?
+	device_add_child(dev, "ata", prisec ?
 			 unit : devclass_find_free_unit(ata_devclass, 2));
 
     return bus_generic_attach(dev);
@@ -227,7 +255,7 @@
     retval += bus_print_child_header(dev, child);
     retval += printf(": at 0x%lx", rman_get_start(ch->r_io[ATA_IDX_ADDR].res));
 
-    if (ATA_MASTERDEV(dev))
+    if (ata_pci_compat(dev))
 	retval += printf(" irq %d", 14 + ch->unit);
     
     retval += bus_print_child_footer(dev, child);
@@ -247,7 +275,7 @@
     if (type == SYS_RES_IOPORT) {
 	switch (*rid) {
 	case ATA_IOADDR_RID:
-	    if (ATA_MASTERDEV(dev)) {
+	    if (ata_pci_compat(dev)) {
 		start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
 		count = ATA_IOSIZE;
 		end = start + count - 1;
@@ -259,9 +287,9 @@
 	    break;
 
 	case ATA_ALTADDR_RID:
-	    if (ATA_MASTERDEV(dev)) {
-		start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET-2;
-		count = 4;
+	    if (ata_pci_compat(dev)) {
+		start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET;
+		count = ATA_ALTIOSIZE;
 		end = start + count - 1;
 	    }
 	    myrid = 0x14 + 8 * unit;
@@ -274,7 +302,7 @@
     }
 
     if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
-	if (ATA_MASTERDEV(dev)) {
+	if (ata_pci_compat(dev)) {
 #ifdef __alpha__
 	    return alpha_platform_alloc_ide_intr(unit);
 #else
@@ -316,7 +344,7 @@
 	if (rid != ATA_IRQ_RID)
 	    return ENOENT;
 
-	if (ATA_MASTERDEV(dev)) {
+	if (ata_pci_compat(dev)) {
 #ifdef __alpha__
 	    return alpha_platform_release_ide_intr(unit, r);
 #else
@@ -335,7 +363,7 @@
 		   int flags, driver_intr_t *function, void *argument,
 		   void **cookiep)
 {
-    if (ATA_MASTERDEV(dev)) {
+    if (ata_pci_compat(dev)) {
 #ifdef __alpha__
 	return alpha_platform_setup_ide_intr(child, irq, function, argument,
 					     cookiep);
@@ -359,7 +387,7 @@
 ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
 		      void *cookie)
 {
-    if (ATA_MASTERDEV(dev)) {
+    if (ata_pci_compat(dev)) {
 #ifdef __alpha__
 	return alpha_platform_teardown_ide_intr(child, irq, cookie);
 #else
@@ -402,7 +430,7 @@
 	ch->r_io[i].offset = i;
     }
     ch->r_io[ATA_ALTSTAT].res = altio;
-    ch->r_io[ATA_ALTSTAT].offset = 2;
+    ch->r_io[ATA_ALTSTAT].offset = ata_pci_compat(device_get_parent(dev)) ? 0:2;
     ch->r_io[ATA_IDX_ADDR].res = io;
 
     if (ctlr->r_res1) {
Index: ata/ata-pci.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-pci.h,v
retrieving revision 1.29
diff -u -r1.29 ata-pci.h
--- ata/ata-pci.h	13 Apr 2004 09:44:20 -0000	1.29
+++ ata/ata-pci.h	18 Apr 2004 15:39:37 -0000
@@ -63,9 +63,6 @@
     void		 *driver;
 };
 
-#define ATA_MASTERDEV(dev)	((pci_get_progif(dev) & 0x80) && \
-				 (pci_get_progif(dev) & 0x05) != 0x05)
-
 /* defines for known chipset PCI id's */
 #define ATA_ACARD_ID		0x1191
 #define ATA_ATP850		0x00021191
@@ -295,6 +292,7 @@
 #define VIABUG		0x10
 
 /* global prototypes */
+int ata_pci_compat(device_t);
 void ata_dmainit(struct ata_channel *);
 int ata_dmastart(struct ata_channel *, caddr_t, int32_t, int);
 int ata_dmastop(struct ata_channel *);


More information about the freebsd-current mailing list