Date: Sun, 11 Apr 2004 23:19:27 -0600 (MDT) From: "M. Warner Losh" <imp@bsdimp.com> To: ler@lerctr.org Cc: current@freebsd.org Subject: Re: HEADS UP: PCI Chnages Message-ID: <20040411.231927.71088677.imp@bsdimp.com> In-Reply-To: <446170000.1081743884@lerlaptop.lerctr.org> References: <20040412040524.851D65D07@ptavv.es.net> <446170000.1081743884@lerlaptop.lerctr.org>
next in thread | previous in thread | raw e-mail | index | archive | help
In message: <446170000.1081743884@lerlaptop.lerctr.org> Larry Rosenman <ler@lerctr.org> writes: : : : --On Sunday, April 11, 2004 21:05:24 -0700 Kevin Oberman <oberman@es.net> : wrote: : : >> Date: Sun, 11 Apr 2004 18:34:55 -0600 (MDT) : >> From: "M. Warner Losh" <imp@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 @@ -246,48 +246,55 @@ 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; } @@ -431,7 +429,7 @@ 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040411.231927.71088677.imp>