/* * In the tables below, the first two line (8 longwords) are the * size masks that are used when the higher level PCI code determines * the size of the region by writing ~0 to a base address register * and reading back the result. * * The following lines are the values that are read during normal * PCI config access cycles, i.e. not after just having written * ~0 to a base address register.
*/
static uint32_t *hdr_addr(const uint32_t *hdr, int reg)
{
uint32_t addr;
/* * This is a little bit tricky. The header maps consist of * 0x20 bytes of size masks, followed by 0x70 bytes of header data. * In the normal case, when not probing a BAR's size, we want * to access the header data, so we add 0x20 to the reg offset, * thus skipping the size mask area. * In the BAR probing case, we want to access the size mask for * the BAR, so we subtract 0x10 (the config header offset for * BAR0), and don't skip the size mask area.
*/
staticint pci_olpc_read(unsignedint seg, unsignedint bus, unsignedint devfn, int reg, int len, uint32_t *value)
{
uint32_t *addr;
WARN_ON(seg);
/* Use the hardware mechanism for non-simulated devices */ if (!is_simulated(bus, devfn)) return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
/* * No device has config registers past 0x70, so we save table space * by not storing entries for the nonexistent registers
*/ if (reg >= 0x70)
addr = &zero_loc; else { switch (devfn) { case 0x8:
addr = hdr_addr(is_lx ? lxnb_hdr : gxnb_hdr, reg); break; case 0x9:
addr = hdr_addr(is_lx ? lxfb_hdr : gxfb_hdr, reg); break; case 0xa:
addr = is_lx ? hdr_addr(aes_hdr, reg) : &ff_loc; break; case 0x78:
addr = hdr_addr(isa_hdr, reg); break; case 0x7b:
addr = hdr_addr(ac97_hdr, reg); break; case 0x7c:
addr = hdr_addr(ohci_hdr, reg); break; case 0x7d:
addr = hdr_addr(ehci_hdr, reg); break; default:
addr = &ff_loc; break;
}
} switch (len) { case 1:
*value = *(uint8_t *)addr; break; case 2:
*value = *(uint16_t *)addr; break; case 4:
*value = *addr; break; default:
BUG();
}
return 0;
}
staticint pci_olpc_write(unsignedint seg, unsignedint bus, unsignedint devfn, int reg, int len, uint32_t value)
{
WARN_ON(seg);
/* Use the hardware mechanism for non-simulated devices */ if (!is_simulated(bus, devfn)) return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
/* XXX we may want to extend this to simulate EHCI power management */
/* * Mostly we just discard writes, but if the write is a size probe * (i.e. writing ~0 to a BAR), we remember it and arrange to return * the appropriate size mask on the next read. This is cheating * to some extent, because it depends on the fact that the next * access after such a write will always be a read to the same BAR.
*/
if ((reg >= 0x10) && (reg < 0x2c)) { /* write is to a BAR */ if (value == ~0)
bar_probing = 1;
} else { /* * No warning on writes to ROM BAR, CMD, LATENCY_TIMER, * CACHE_LINE_SIZE, or PM registers.
*/ if ((reg != PCI_ROM_ADDRESS) && (reg != PCI_COMMAND_MASTER) &&
(reg != PCI_LATENCY_TIMER) &&
(reg != PCI_CACHE_LINE_SIZE) && (reg != 0x44))
printk(KERN_WARNING "OLPC PCI: Config write to devfn" " %x reg %x value %x\n", devfn, reg, value);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.