In message: <cone.1082541195.694771.566.1001_at_phobos.totalterror.net> Niki Denev <nike_d_at_cytexbg.com> writes: : yes, but i was not getting this before, but now, after the last commits to : pci/ata-pci. : maybe i'll try to find the patch and apply it to the latest sources, to see : what will happen. Try to apply this patch to latest sources. Warner --- FreeBSD/src/sys/dev/pci/pci.c Wed Apr 21 05:01:45 2004 +++ p4/newcard/src/sys/dev/pci/pci.c Wed Apr 21 04:52:17 2004 _at__at_ -825,14 +825,6 _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; _at__at_ -846,6 +838,59 _at__at_ return ((ln2range == 64) ? 2 : 1); } +static int +pci_is_ata_legacy(device_t dev) +{ + /* + * ATA PCI in compatibility mode are hard wired to certain + * compatibility addresses. Such entries does not contain + * valid resources as they are at fixed positions to be + * compatible with old ISA requirements. + */ + 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; + return 0; +} + +/* + * The ATA PCI spec specifies that in legacy mode, the device shall + * decode the resources listed below. The ata driver allocates + * resources in this order, and many atapci devices actually have + * values similar to these in the actual underlying bars. Part of the + * problem is that the floppy controller and ata overlap for 1 byte, + * which makes it difficult to properly allocate things. + * + * My reading of the pci spec is such that this appears to be the only + * allowed exception to the rule that devices only decode the addresses + * presented in their BARs. + */ +static void +pci_add_ata_legacy_maps(device_t pcib, device_t bus, device_t dev, int b, + int s, int f, struct resource_list *rl) +{ + int rid; + int type; + + type = SYS_RES_IOPORT; + rid = PCIR_BAR(0); + resource_list_add(rl, type, rid, 0x1f0, 0x1f7, 8); + resource_list_alloc(rl, bus, dev, type, &rid, 0x1f0, 0x1f7, 8, 0); + rid = PCIR_BAR(1); + resource_list_add(rl, type, rid, 0x3f6, 0x3f6, 1); + resource_list_alloc(rl, bus, dev, type, &rid, 0x3f6, 0x3f6, 1, 0); + rid = PCIR_BAR(2); + resource_list_add(rl, type, rid, 0x170, 0x177, 8); + resource_list_alloc(rl, bus, dev, type, &rid, 0x170, 0x177, 8, 0); + rid = PCIR_BAR(3); + resource_list_add(rl, type, rid, 0x376, 0x376, 1); + resource_list_alloc(rl, bus, dev, type, &rid, 0x376, 0x376, 1, 0); + pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(4), rl); +} + static void pci_add_resources(device_t pcib, device_t bus, device_t dev) { _at__at_ -858,8 +903,13 _at__at_ b = cfg->bus; s = cfg->slot; f = cfg->func; - for (i = 0; i < cfg->nummaps;) - i += pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(i), rl); + + if (pci_is_ata_legacy(dev)) + pci_add_ata_legacy_maps(pcib, bus, dev, b, s, f, rl); + else + for (i = 0; i < cfg->nummaps;) + i += pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(i), + rl); for (q = &pci_quirks[0]; q->devid; q++) { if (q->devid == ((cfg->device << 16) | cfg->vendor) _at__at_ -1468,49 +1518,43 _at__at_ /* * 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. + * is. Bars that read back 0 here are bogus and unimplemented. + * Note: atapci in legacy mode are special and handled elsewhere + * in the code. If you have a atapci device in legacy mode and + * it fails here, that other code is broken. */ res = NULL; map = pci_read_config(child, *rid, 4); pci_write_config(child, *rid, 0xffffffff, 4); testval = pci_read_config(child, *rid, 4); - 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); - goto out; - } - } else { - if (type != SYS_RES_IOPORT) { - device_printf(child, - "failed: rid %#x is ioport, requested %d\n", - *rid, type); - goto out; - } + if (testval == 0) + return (NULL); + if (pci_maptype(testval) & PCI_MAPMEM) { + if (type != SYS_RES_MEMORY) { + device_printf(child, + "failed: rid %#x is memory, requested %d\n", + *rid, type); + goto out; } - /* - * For real BARs, we need to override the size that - * the driver requests, because that's what the BAR - * 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) + } else { + if (type != SYS_RES_IOPORT) { device_printf(child, - "ZERO BAR: resource checks suppressed.\n"); + "failed: rid %#x is ioport, requested %d\n", + *rid, type); + goto out; + } } + /* + * For real BARs, we need to override the size that + * the driver requests, because that's what the BAR + * 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); /* * Allocate enough resource, and then write back the --- FreeBSD/src/sys/dev/ata/ata-pci.c Wed Apr 21 05:01:05 2004 +++ p4/newcard/src/sys/dev/ata/ata-pci.c Wed Apr 21 04:44:58 2004 _at__at_ -247,6 +247,15 _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 + * the values here. This will fail on those machines that + * claim to be master but are not wired to these address. + * But claiming to be master defines that they are at the + * traditional addresses. + */ if (ATA_MASTERDEV(dev)) { start = (unit ? ATA_SECONDARY : ATA_PRIMARY); count = ATA_IOSIZE; _at__at_ -259,6 +268,15 _at__at_ break; case ATA_ALTADDR_RID: + /* + * For non-master devices, the ALTADDR is offset by 2 + * into the rid that's returned. Since ALTADDR is also + * offset by 2 for master devices (hence the need to round + * down to the nearest block of 4), both cases have an offset + * of 2. This means that the initial allocation for both + * of these cases, as well as the offset of 2 elsewhere in + * the code should be sufficient. + */ if (ATA_MASTERDEV(dev)) { start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET; count = ATA_ALTIOSIZE; _at__at_ -402,7 +420,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 = ATA_MASTERDEV(device_get_parent(dev)) ? 0:2; ch->r_io[ATA_IDX_ADDR].res = io; if (ctlr->r_res1) {Received on Wed Apr 21 2004 - 05:31:40 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:51 UTC