17,12 → 17,265 |
static struct pci_bus pci_root; |
static struct pci_dev *pci_devices = NULL; |
|
#if 0 |
/* scan the bus to find all the connected devices */ |
DWORD pci_scan_bus(struct pci_bus *bus) |
{ |
int ndev; |
DWORD tmp; |
DWORD max; |
DWORD max, class; |
BYTE hdr; |
int ok; |
WORD dev; |
struct pci_dev **bus_last; |
struct pci_dev *device = NULL; |
int present; |
|
max = bus->secondary; |
bus_last = &bus->devices; |
|
if (pcibios_present() == 0) return -1; |
ndev = 0; |
|
for (dev = 0; dev <= 0xFF; dev++) { |
present = 0; |
if ((dev & 0x07) == 0) { |
present = pcibios_read_config_byte(bus->number, dev, 0x0e, &hdr); |
} |
if (hdr & 0x80) { |
present = 1; |
} |
if (present) { |
ok = pcibios_read_config_dword(bus->number, dev, 0, &tmp); |
if ( ok && (((tmp & 0xFFFF) != 0xFFFF) && ((tmp >> 16) != 0xFFFF))) { |
/* Got a PCI Device!!! */ |
device = &(pci_devs[ndev++]); |
device->bus = bus; |
device->devfn = dev; |
device->vendor = tmp & 0xffff; |
device->device = (tmp >> 16) & 0xffff; |
|
/* PJ: non-destructively determine if device can be a master: */ |
pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &cmd); |
pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd | PCI_COMMAND_MASTER); |
pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &tmp); |
dev->master = ((tmp & PCI_COMMAND_MASTER) != 0); |
pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd); |
|
/* This is by Luca... We need to set base_addr */ |
pcibios_read_config_dword(bus->number, dev, PCI_BASE_ADDRESS_0, &(device->base_address[0])); |
|
|
|
pcibios_read_config_byte(bus->number, dev, PCI_INTERRUPT_LINE, &irq1); |
device->irq = irq1; |
|
pcibios_read_config_dword(bus->number, dev, PCI_CLASS_REVISION, &class); |
class >>= 8; /* upper 3 bytes */ |
//printk(KERN_INFO "pci_scan_bus: dev=%d, class=%ld", dev, class); |
device->class = class; |
class >>= 8; |
device->hdr_type = hdr; |
|
|
|
|
#if 0 |
switch (hdr & 0x7f) { /* header type */ |
case PCI_HEADER_TYPE_NORMAL: /* standard header */ |
if (class == PCI_CLASS_BRIDGE_PCI) |
goto bad; |
/* |
* If the card generates interrupts, read IRQ number |
* (some architectures change it during pcibios_fixup()) |
*/ |
pcibios_read_config_byte(bus->number, device->devfn, PCI_INTERRUPT_PIN, &irq1); |
if (irq1) |
pcibios_read_config_byte(bus->number, device->devfn, PCI_INTERRUPT_LINE, &irq1); |
device->irq = irq1; |
/* |
* read base address registers, again pcibios_fixup() can |
* tweak these |
*/ |
pci_read_bases(device, 6); |
pcibios_read_config_dword(bus->number, dev, PCI_ROM_ADDRESS, &l); |
device->rom_address = (l == 0xffffffff) ? 0 : l; |
break; |
case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ |
if (class != PCI_CLASS_BRIDGE_PCI) |
goto bad; |
pci_read_bases(device, 2); |
pcibios_read_config_dword(bus->number, dev, PCI_ROM_ADDRESS1, &l); |
device->rom_address = (l == 0xffffffff) ? 0 : l; |
break; |
case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ |
if (class != PCI_CLASS_BRIDGE_CARDBUS) |
goto bad; |
pci_read_bases(device, 1); |
break; |
default: /* unknown header */ |
bad: |
printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n", |
bus->number, device->devfn, device->vendor, device->device, class, hdr); |
continue; |
} |
#endif |
|
|
|
|
//printk(KERN_DEBUG "PCI: %02x:%02x [%04x/%04x]\n", bus->number, device->devfn, device->vendor, device->device); |
|
device->next = pci_devices; |
pci_devices = device; |
|
/* |
* Now insert it into the list of devices held |
* by the parent bus. |
*/ |
*bus_last = device; |
bus_last = &device->sibling; |
|
|
|
} |
} |
} |
|
// PJ: PCI bridges not supported??? |
#if 0 |
for(device = bus->devices; device; device = device->sibling) { |
/* |
* If it's a bridge, scan the bus behind it. |
*/ |
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { |
unsigned int buses; |
unsigned int devfn = dev->devfn; |
unsigned short cr; |
|
/* |
* Insert it into the tree of buses. |
*/ |
child = kmalloc(sizeof(*child), GFP_ATOMIC); |
if(child==NULL) { |
#ifdef DEBUG_PCISCAN |
printk(KERN_ERR "pci: out of memory for bridge.\n"); |
#endif |
continue; |
} |
memset(child, 0, sizeof(*child)); |
child->next = bus->children; |
bus->children = child; |
child->self = dev; |
child->parent = bus; |
|
/* |
* Set up the primary, secondary and subordinate |
* bus numbers. |
*/ |
child->number = child->secondary = ++max; |
child->primary = bus->secondary; |
child->subordinate = 0xff; |
/* |
* Clear all status bits and turn off memory, |
* I/O and master enables. |
*/ |
pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr); |
pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000); |
pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff); |
/* |
* Read the existing primary/secondary/subordinate bus |
* number configuration to determine if the PCI bridge |
* has already been configured by the system. If so, |
* do not modify the configuration, merely note it. |
*/ |
pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); |
if ((buses & 0xFFFFFF) != 0) { |
unsigned int cmax; |
|
child->primary = buses & 0xFF; |
child->secondary = (buses >> 8) & 0xFF; |
child->subordinate = (buses >> 16) & 0xFF; |
child->number = child->secondary; |
cmax = pci_scan_bus(child); |
if (cmax > max) max = cmax; |
} else { |
/* |
* Configure the bus numbers for this bridge: |
*/ |
buses &= 0xff000000; |
buses |= (((unsigned int)(child->primary) << 0) | |
((unsigned int)(child->secondary) << 8) | |
((unsigned int)(child->subordinate) << 16)); |
pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
/* |
* Now we can scan all subordinate buses: |
*/ |
max = pci_scan_bus(child); |
/* |
* Set the subordinate bus number to its real |
* value: |
*/ |
child->subordinate = max; |
buses = (buses & 0xff00ffff) |
| ((unsigned int)(child->subordinate) << 16); |
pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
} |
pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr); |
} |
} |
#endif |
|
return max; |
} |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* scan the bus to find all the connected devices */ |
DWORD pci_scan_bus(struct pci_bus *bus) |
{ |
int ndev; |
DWORD tmp; |
DWORD max, class; |
BYTE hdr, irq1; |
int ok; |
WORD dev; |
63,13 → 316,13 |
pcibios_read_config_byte(bus->number, dev, PCI_INTERRUPT_LINE, &irq1); |
device->irq = irq1; |
|
#if 0 |
pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class); |
pcibios_read_config_dword(bus->number, dev, PCI_CLASS_REVISION, &class); |
class >>= 8; /* upper 3 bytes */ |
dev->class = class; |
device->class = class; |
class >>= 8; |
dev->hdr_type = hdr; |
device->hdr_type = hdr; |
|
#if 0 |
switch (hdr_type & 0x7f) { /* header type */ |
case PCI_HEADER_TYPE_NORMAL: /* standard header */ |
if (class == PCI_CLASS_BRIDGE_PCI) |
273,3 → 526,25 |
cprintf("PCI_FIND_SLOT: found %p at bus %d\n", dev, dev->bus->number); |
return dev; |
} |
|
|
void |
pci_set_master(struct pci_dev *dev) |
{ |
unsigned short cmd; // was: u16 |
unsigned char lat; // was: u8 |
|
pci_read_config_word(dev, PCI_COMMAND, &cmd); |
if (! (cmd & PCI_COMMAND_MASTER)) { |
printk("PCI: Enabling bus mastering for device %02x:%02x\n", |
dev->bus->number, dev->devfn); |
cmd |= PCI_COMMAND_MASTER; |
pci_write_config_word(dev, PCI_COMMAND, cmd); |
} |
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); |
if (lat < 16) { |
printk("PCI: Increasing latency timer of device %02x:%02x to 64\n", |
dev->bus->number, dev->devfn); |
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); |
} |
} |