* Some preparations for the new driver architecture: added FindCapability(),

and {Read|Write}Config() that get a PCIDev structure, added a FindDevice()
  method.
* Made sPCI a global gPCI, since the new PCI root/device modules will be using
  it directly.
* Moved the functionality of pci_find_capability() into a new
  PCI::FindCapability() method.
* Removed the redundant "Pci" from PCI::{Read|Write}PciConfig(), and
  GetNthPciInfo().
* Added PCI::_NumFunctions() that returns the number of functions instead of
  doing it manually every time.
* Tried to honour the 80 character limit, as well as other coding style things
  a bit more.
* Added '_' prefix for private method names.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25575 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-05-20 17:53:54 +00:00
parent 0f0fba6373
commit 705263f5b3
3 changed files with 757 additions and 525 deletions
File diff suppressed because it is too large Load Diff
+95 -67
View File
@@ -1,7 +1,6 @@
/* /*
* Copyright 2006, Marcus Overhagen. All rights reserved. * Copyright 2003-2008, Marcus Overhagen. All rights reserved.
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2003, Marcus Overhagen. All rights reserved.
* *
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -19,7 +18,7 @@
#define TRACE_PCI #define TRACE_PCI
#ifndef TRACE_PCI #ifndef TRACE_PCI
# define TRACE(x) # define TRACE(x)
#else #else
# define TRACE(x) dprintf x # define TRACE(x) dprintf x
#endif #endif
@@ -30,104 +29,131 @@
struct PCIDev; struct PCIDev;
struct PCIBus { struct PCIBus {
PCIBus *next; PCIBus * next;
PCIDev *parent; PCIDev * parent;
PCIDev *child; PCIDev * child;
int domain; int domain;
uint8 bus; uint8 bus;
}; };
struct PCIDev { struct PCIDev {
PCIDev *next; PCIDev * next;
PCIBus *parent; PCIBus * parent;
PCIBus *child; PCIBus * child;
int domain; int domain;
uint8 bus; uint8 bus;
uint8 dev; uint8 device;
uint8 func; uint8 function;
pci_info info; pci_info info;
}; };
struct domain_data struct domain_data {
{
// These two are set in PCI::AddController: // These two are set in PCI::AddController:
pci_controller * controller; pci_controller * controller;
void * controller_cookie; void * controller_cookie;
// All the rest is set in PCI::InitDomainData // All the rest is set in PCI::InitDomainData
int max_bus_devices; int max_bus_devices;
}; };
class PCI { class PCI {
public: public:
PCI(); PCI();
~PCI(); ~PCI();
void InitDomainData();
void InitBus();
status_t AddController(pci_controller *controller, void *controller_cookie); void InitDomainData();
void InitBus();
status_t GetNthPciInfo(long index, pci_info *outInfo); status_t AddController(pci_controller *controller,
void *controller_cookie);
status_t ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function, status_t GetNthInfo(long index, pci_info *outInfo);
uint8 offset, uint8 size, uint32 *value);
uint32 ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function, status_t ReadConfig(int domain, uint8 bus, uint8 device,
uint8 offset, uint8 size); uint8 function, uint8 offset, uint8 size,
uint32 *value);
uint32 ReadConfig(int domain, uint8 bus, uint8 device,
uint8 function, uint8 offset, uint8 size);
uint32 ReadConfig(PCIDev *device, uint8 offset,
uint8 size);
status_t WritePciConfig(int domain, uint8 bus, uint8 device, uint8 function, status_t WriteConfig(int domain, uint8 bus, uint8 device,
uint8 offset, uint8 size, uint32 value); uint8 function, uint8 offset, uint8 size,
uint32 value);
status_t WriteConfig(PCIDev *device, uint8 offset,
uint8 size, uint32 value);
status_t ResolveVirtualBus(uint8 virtualBus, int *domain, uint8 *bus); status_t FindCapability(int domain, uint8 bus, uint8 device,
uint8 function, uint8 capID, uint8 *offset);
void ClearDeviceStatus(PCIBus *bus, bool dumpStatus); status_t FindCapability(PCIDev *device, uint8 capID,
uint8 *offset);
private: status_t ResolveVirtualBus(uint8 virtualBus, int *domain,
uint8 *bus);
void EnumerateBus(int domain, uint8 bus, uint8 *subordinate_bus = NULL); PCIDev * FindDevice(int domain, uint8 bus, uint8 device,
uint8 function);
void FixupDevices(int domain, uint8 bus); void ClearDeviceStatus(PCIBus *bus, bool dumpStatus);
void DiscoverBus(PCIBus *bus); private:
void DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func); void _EnumerateBus(int domain, uint8 bus,
uint8 *subordinateBus = NULL);
PCIDev *CreateDevice(PCIBus *parent, uint8 dev, uint8 func); void _FixupDevices(int domain, uint8 bus);
PCIBus *CreateBus(PCIDev *parent, int domain, uint8 bus);
status_t GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInfo); void _DiscoverBus(PCIBus *bus);
void ReadPciBasicInfo(PCIDev *dev); void _DiscoverDevice(PCIBus *bus, uint8 dev,
void ReadPciHeaderInfo(PCIDev *dev); uint8 function);
void ConfigureBridges(PCIBus *bus); PCIDev * _CreateDevice(PCIBus *parent, uint8 dev,
void RefreshDeviceInfo(PCIBus *bus); uint8 function);
PCIBus * _CreateBus(PCIDev *parent, int domain, uint8 bus);
uint32 BarSize(uint32 bits, uint32 mask); status_t _GetNthInfo(PCIBus *bus, long *currentIndex,
void GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size = 0, uint8 *flags = 0); long wantIndex, pci_info *outInfo);
void GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size = 0, uint8 *flags = 0); void _ReadBasicInfo(PCIDev *dev);
void _ReadHeaderInfo(PCIDev *dev);
domain_data * GetDomainData(int domain);
status_t CreateVirtualBus(int domain, uint8 bus, uint8 *virtualBus);
private: void _ConfigureBridges(PCIBus *bus);
PCIBus * fRootBus; void _RefreshDeviceInfo(PCIBus *bus);
enum { MAX_PCI_DOMAINS = 8 }; uint32 _BarSize(uint32 bits, uint32 mask);
void _GetBarInfo(PCIDev *dev, uint8 offset,
domain_data fDomainData[MAX_PCI_DOMAINS]; uint32 *address, uint32 *size = 0,
int fDomainCount; uint8 *flags = 0);
bool fBusEnumeration; void _GetRomBarInfo(PCIDev *dev, uint8 offset,
uint32 *address, uint32 *size = 0,
uint8 *flags = 0);
typedef VectorMap<uint8, uint16> VirtualBusMap; domain_data * _GetDomainData(int domain);
VirtualBusMap fVirtualBusMap; status_t _CreateVirtualBus(int domain, uint8 bus,
int fNextVirtualBus; uint8 *virtualBus);
int _NumFunctions(int domain, uint8 bus, uint8 device);
PCIDev * _FindDevice(PCIBus *current, int domain, uint8 bus,
uint8 device, uint8 function);
private:
PCIBus * fRootBus;
enum { MAX_PCI_DOMAINS = 8 };
domain_data fDomainData[MAX_PCI_DOMAINS];
int fDomainCount;
bool fBusEnumeration;
typedef VectorMap<uint8, uint16> VirtualBusMap;
VirtualBusMap fVirtualBusMap;
int fNextVirtualBus;
}; };
extern PCI *gPCI;
#endif // __cplusplus #endif // __cplusplus
@@ -140,8 +166,10 @@ void pci_uninit(void);
long pci_get_nth_pci_info(long index, pci_info *outInfo); long pci_get_nth_pci_info(long index, pci_info *outInfo);
uint32 pci_read_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, uint8 size); uint32 pci_read_config(uint8 virtualBus, uint8 device, uint8 function,
void pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value); uint8 offset, uint8 size);
void pci_write_config(uint8 virtualBus, uint8 device, uint8 function,
uint8 offset, uint8 size, uint32 value);
void __pci_resolve_virtual_bus(uint8 virtualBus, int *domain, uint8 *bus); void __pci_resolve_virtual_bus(uint8 virtualBus, int *domain, uint8 *bus);
@@ -12,12 +12,13 @@
/* The Jmicron AHCI controller has a mode that combines IDE and AHCI functionality /* The Jmicron AHCI controller has a mode that combines IDE and AHCI functionality
* into a single PCI device at function 0. This happens when the controller is set * into a single PCI device at function 0. This happens when the controller is set
* in the BIOS to "basic" or "IDE" mode (but not in "RAID" or "AHCI" mode). * in the BIOS to "basic" or "IDE" mode (but not in "RAID" or "AHCI" mode).
* To avoid needing two drivers to handle a single PCI device, we switch to the * To avoid needing two drivers to handle a single PCI device, we switch to the
* multifunction (split device) AHCI mode. This will set PCI device at function 0 * multifunction (split device) AHCI mode. This will set PCI device at function 0
* to AHCI, and PCI device at function 1 to IDE controller. * to AHCI, and PCI device at function 1 to IDE controller.
*/ */
static void static void
jmicron_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function, uint16 deviceId) jmicron_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device,
uint8 function, uint16 deviceId)
{ {
switch (deviceId) { switch (deviceId) {
case 0x2361: // 1 SATA, 1 PATA case 0x2361: // 1 SATA, 1 PATA
@@ -34,26 +35,26 @@ jmicron_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function
domain, bus, device, function, deviceId); domain, bus, device, function, deviceId);
if (function == 0) { if (function == 0) {
dprintf("jmicron_fixup_ahci: 0x40: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x40, 4)); dprintf("jmicron_fixup_ahci: 0x40: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x40, 4));
dprintf("jmicron_fixup_ahci: 0xdc: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0xdc, 4)); dprintf("jmicron_fixup_ahci: 0xdc: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0xdc, 4));
uint32 val = pci->ReadPciConfig(domain, bus, device, function, 0xdc, 4); uint32 val = pci->ReadConfig(domain, bus, device, function, 0xdc, 4);
if (!(val & (1 << 30))) { if (!(val & (1 << 30))) {
uint8 irq = pci->ReadPciConfig(domain, bus, device, function, 0x3c, 1); uint8 irq = pci->ReadConfig(domain, bus, device, function, 0x3c, 1);
dprintf("jmicron_fixup_ahci: enabling split device mode\n"); dprintf("jmicron_fixup_ahci: enabling split device mode\n");
val &= ~(1 << 24); val &= ~(1 << 24);
val |= (1 << 25) | (1 << 30); val |= (1 << 25) | (1 << 30);
pci->WritePciConfig(domain, bus, device, function, 0xdc, 4, val); pci->WriteConfig(domain, bus, device, function, 0xdc, 4, val);
val = pci->ReadPciConfig(domain, bus, device, function, 0x40, 4); val = pci->ReadConfig(domain, bus, device, function, 0x40, 4);
val &= ~(1 << 16); val &= ~(1 << 16);
val |= (1 << 1) | (1 << 17) | (1 << 22); val |= (1 << 1) | (1 << 17) | (1 << 22);
pci->WritePciConfig(domain, bus, device, function, 0x40, 4, val); pci->WriteConfig(domain, bus, device, function, 0x40, 4, val);
if (function == 0) if (function == 0)
pci->WritePciConfig(domain, bus, device, 1, 0x3c, 1, irq); pci->WriteConfig(domain, bus, device, 1, 0x3c, 1, irq);
else else
dprintf("jmicron_fixup_ahci: can't assign IRQ\n"); dprintf("jmicron_fixup_ahci: can't assign IRQ\n");
} }
dprintf("jmicron_fixup_ahci: 0x40: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x40, 4)); dprintf("jmicron_fixup_ahci: 0x40: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x40, 4));
dprintf("jmicron_fixup_ahci: 0xdc: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0xdc, 4)); dprintf("jmicron_fixup_ahci: 0xdc: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0xdc, 4));
} }
} }
@@ -85,49 +86,49 @@ intel_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function,
dprintf("intel_fixup_ahci: domain %u, bus %u, device %u, function %u, deviceId 0x%04x\n", dprintf("intel_fixup_ahci: domain %u, bus %u, device %u, function %u, deviceId 0x%04x\n",
domain, bus, device, function, deviceId); domain, bus, device, function, deviceId);
dprintf("intel_fixup_ahci: 0x24: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x24, 4)); dprintf("intel_fixup_ahci: 0x24: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4));
dprintf("intel_fixup_ahci: 0x90: 0x%02lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x90, 1)); dprintf("intel_fixup_ahci: 0x90: 0x%02lx\n", pci->ReadConfig(domain, bus, device, function, 0x90, 1));
uint8 map = pci->ReadPciConfig(domain, bus, device, function, 0x90, 1); uint8 map = pci->ReadConfig(domain, bus, device, function, 0x90, 1);
if ((map >> 6) == 0) { if ((map >> 6) == 0) {
uint32 bar5 = pci->ReadPciConfig(domain, bus, device, function, 0x24, 4); uint32 bar5 = pci->ReadConfig(domain, bus, device, function, 0x24, 4);
uint16 pcicmd = pci->ReadPciConfig(domain, bus, device, function, PCI_command, 2); uint16 pcicmd = pci->ReadConfig(domain, bus, device, function, PCI_command, 2);
dprintf("intel_fixup_ahci: switching from IDE to AHCI mode\n"); dprintf("intel_fixup_ahci: switching from IDE to AHCI mode\n");
pci->WritePciConfig(domain, bus, device, function, PCI_command, 2, pci->WriteConfig(domain, bus, device, function, PCI_command, 2,
pcicmd & ~(PCI_command_io | PCI_command_memory)); pcicmd & ~(PCI_command_io | PCI_command_memory));
pci->WritePciConfig(domain, bus, device, function, 0x24, 4, 0xffffffff); pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff);
dprintf("intel_fixup_ahci: ide-bar5 bits-1: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x24, 4)); dprintf("intel_fixup_ahci: ide-bar5 bits-1: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4));
pci->WritePciConfig(domain, bus, device, function, 0x24, 4, 0); pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0);
dprintf("intel_fixup_ahci: ide-bar5 bits-0: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x24, 4)); dprintf("intel_fixup_ahci: ide-bar5 bits-0: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4));
map &= ~0x03; map &= ~0x03;
map |= 0x40; map |= 0x40;
pci->WritePciConfig(domain, bus, device, function, 0x90, 1, map); pci->WriteConfig(domain, bus, device, function, 0x90, 1, map);
pci->WritePciConfig(domain, bus, device, function, 0x24, 4, 0xffffffff); pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff);
dprintf("intel_fixup_ahci: ahci-bar5 bits-1: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x24, 4)); dprintf("intel_fixup_ahci: ahci-bar5 bits-1: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4));
pci->WritePciConfig(domain, bus, device, function, 0x24, 4, 0); pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0);
dprintf("intel_fixup_ahci: ahci-bar5 bits-0: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x24, 4)); dprintf("intel_fixup_ahci: ahci-bar5 bits-0: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4));
if (deviceId == 0x27c0 || deviceId == 0x27c4) // restore on ICH7 if (deviceId == 0x27c0 || deviceId == 0x27c4) // restore on ICH7
pci->WritePciConfig(domain, bus, device, function, 0x24, 4, bar5); pci->WriteConfig(domain, bus, device, function, 0x24, 4, bar5);
pci->WritePciConfig(domain, bus, device, function, PCI_command, 2, pcicmd); pci->WriteConfig(domain, bus, device, function, PCI_command, 2, pcicmd);
} }
dprintf("intel_fixup_ahci: 0x24: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x24, 4)); dprintf("intel_fixup_ahci: 0x24: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4));
dprintf("intel_fixup_ahci: 0x90: 0x%02lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x90, 1)); dprintf("intel_fixup_ahci: 0x90: 0x%02lx\n", pci->ReadConfig(domain, bus, device, function, 0x90, 1));
} }
void void
pci_fixup_device(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function) pci_fixup_device(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function)
{ {
uint16 vendorId = pci->ReadPciConfig(domain, bus, device, function, PCI_vendor_id, 2); uint16 vendorId = pci->ReadConfig(domain, bus, device, function, PCI_vendor_id, 2);
uint16 deviceId = pci->ReadPciConfig(domain, bus, device, function, PCI_device_id, 2); uint16 deviceId = pci->ReadConfig(domain, bus, device, function, PCI_device_id, 2);
// dprintf("pci_fixup_device: domain %u, bus %u, device %u, function %u\n", domain, bus, device, function); // dprintf("pci_fixup_device: domain %u, bus %u, device %u, function %u\n", domain, bus, device, function);