Re: HEADS UP: PCI Chnages

From: M. Warner Losh <imp_at_bsdimp.com>
Date: Sun, 11 Apr 2004 23:19:27 -0600 (MDT)
In message: <446170000.1081743884_at_lerlaptop.lerctr.org>
            Larry Rosenman <ler_at_lerctr.org> writes:
: 
: 
: --On Sunday, April 11, 2004 21:05:24 -0700 Kevin Oberman <oberman_at_es.net> 
: wrote:
: 
: >> Date: Sun, 11 Apr 2004 18:34:55 -0600 (MDT)
: >> From: "M. Warner Losh" <imp_at_bsdimp.com>
: >>
: >> Try this patch
: >
: > Bingo! I am running with the new kernel as I type this.
: as soon as OOo-1.1.1 finishes building, I'll try the new kernel waiting
: in the wings on this box (probably in the AM at this point), but this is a 
: good sign :)

You might also try
	http://people.freebsd.org/~imp/ata-patch

This patch is also discected here, to make sure I have my analysis
right.

Index: ata-pci.c
===================================================================
RCS file: /cache/ncvs/src/sys/dev/ata/ata-pci.c,v
retrieving revision 1.77
diff -u -r1.77 ata-pci.c
--- ata-pci.c	17 Mar 2004 17:50:27 -0000	1.77
+++ ata-pci.c	12 Apr 2004 04:54:18 -0000
_at__at_ -246,48 +246,55 _at__at_
     if (type == SYS_RES_IOPORT) {
 	switch (*rid) {
 	case ATA_IOADDR_RID:
+	    /*
+	     * ATA master devices are hard wired to the traditional ata
+	     * I/O addresses.  Some devices have these resources wired to
+	     * their BARs, while others do not, hence the need to hardwire
+	     */
 	    if (ATA_MASTERDEV(dev)) {
-		myrid = 0;
 		start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
 		end = start + ATA_IOSIZE - 1;
 		count = ATA_IOSIZE;
-		res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
-					 SYS_RES_IOPORT, &myrid,
-					 start, end, count, flags);
-	    }
-	    else {
-		myrid = 0x10 + 8 * unit;
-		res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
-					 SYS_RES_IOPORT, &myrid,
-					 start, end, count, flags);
 	    }
+	    myrid = 0x10 + 8 * unit;
+	    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+				     SYS_RES_IOPORT, &myrid,
+				     start, end, count, flags);
 	    break;
 

OK.  What I'm doing above is changing how we do the allocation a
little.  Before, one had to play 'tricks' to get the resources
allocated correctly.  There was code in the pci bus that prevented
most allocations like this from succeeding, as well as other
complications.

This simplifies these past workarounds now that the PCI bus allocation
has been tightened up.  The old ata code would work with the those
devices that did NOT have the resources encoded in the BARs.  This is
because the new PCI code reserves BAR resources for the exclusive use
of that device.



 	case ATA_ALTADDR_RID:
 	    if (ATA_MASTERDEV(dev)) {
-		myrid = 0;
+#if 0
 		start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET;
 		end = start + ATA_ALTIOSIZE - 1;
 		count = ATA_ALTIOSIZE;
-		res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
-					 SYS_RES_IOPORT, &myrid,
-					 start, end, count, flags);
+#else
+		start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET - 2;
+		count = 4;
+		end = start + count - 1;
+#endif
 	    }
-	    else {
-		myrid = 0x14 + 8 * unit;
+printf("ata altaddr start %#lx end %#lx count %#lx\n", start, end, count);
+	    myrid = 0x14 + 8 * unit;
+	    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+	                             SYS_RES_IOPORT, &myrid,
+				     start, end, count, flags);
+
+	    /*
+	     * I don't understand why we need to do this dance.  If we get
+	     * the resource, then we release it and allocated something
+	     * else.  This makes little sense to me, and might, in fact
+	     * be a bug.
+	     */
+	    if (res && !ATA_MASTERDEV(dev)) {
+		start = rman_get_start(res) + 2;
+		end = start + ATA_ALTIOSIZE - 1;
+		count = ATA_ALTIOSIZE;
+		BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
+		                     SYS_RES_IOPORT, myrid, res);
 		res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
 					 SYS_RES_IOPORT, &myrid,
 					 start, end, count, flags);
-		if (res) {
-			start = rman_get_start(res) + 2;
-			end = start + ATA_ALTIOSIZE - 1;
-			count = ATA_ALTIOSIZE;
-			BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
-					     SYS_RES_IOPORT, myrid, res);
-			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
-						 SYS_RES_IOPORT, &myrid,
-						 start, end, count, flags);
-		}
 	    }
 	    break;
 	}

_at__at_ -431,7 +429,7 _at__at_
 	ch->r_io[i].offset = i;
     }
     ch->r_io[ATA_ALTSTAT].res = altio;
-    ch->r_io[ATA_ALTSTAT].offset = 0;
+    ch->r_io[ATA_ALTSTAT].offset = 2;
     ch->r_io[ATA_IDX_ADDR].res = io;
 
     if (ctlr->r_res1) {

These are more complicated.  We want to allocate 0x376 and 0x3f6 (Each
for a length of 1).  However, there's a problem with that.  The
problem is that this resource isn't encodable in a PCI bar.  BARs must
be at least 4 in size, and aligned to the size of the resource.  So
the above code tries to round correctly to copensate.  I'm not sure
that I'm entirely happy with it, but it works for me.

Warner
Received on Sun Apr 11 2004 - 20:18:46 UTC

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