Re: no root fs in CURRENT kernel

From: Søren Schmidt <sos_at_DeepCore.dk>
Date: Mon, 19 Apr 2004 14:29:31 +0200
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


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
_at__at_ -260,8 +260,8 _at__at_
 
 	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;
_at__at_ -402,7 +402,7 _at__at_
 	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
_at__at_ -824,6 +824,15 _at__at_
 	 */
 	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;

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
_at__at_ -1455,15 +1455,11 _at__at_
 	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);
_at__at_ -1472,16 +1468,18 _at__at_
 	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;
 			}
 		}
_at__at_ -1491,11 +1489,11 _at__at_
 		 * 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)
_at__at_ -1590,11 +1588,12 _at__at_
 		 */
 		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
_at__at_ -2350,15 +2350,15 _at__at_
 	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);
_at__at_ -2662,7 +2662,7 _at__at_
     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
_at__at_ -563,15 +563,15 _at__at_
 	}
     }
 
+    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
_at__at_ -62,6 +62,15 _at__at_
 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)
 {
_at__at_ -155,10 +164,29 _at__at_
 {
     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;
_at__at_ -185,7 +213,7 _at__at_
 
     /* 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);
_at__at_ -227,7 +255,7 _at__at_
     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);
_at__at_ -247,7 +275,7 _at__at_
     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;
_at__at_ -259,9 +287,9 _at__at_
 	    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;
_at__at_ -274,7 +302,7 _at__at_
     }
 
     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
_at__at_ -316,7 +344,7 _at__at_
 	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
_at__at_ -335,7 +363,7 _at__at_
 		   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);
_at__at_ -359,7 +387,7 _at__at_
 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
_at__at_ -402,7 +430,7 _at__at_
 	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
_at__at_ -63,9 +63,6 _at__at_
     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
_at__at_ -295,6 +292,7 _at__at_
 #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 *);
Received on Mon Apr 19 2004 - 03:29:41 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:51 UTC