* 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

View File

@ -1,7 +1,6 @@
/*
* Copyright 2006, Marcus Overhagen. All rights reserved.
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2003, Marcus Overhagen. All rights reserved.
* Copyright 2003-2008, Marcus Overhagen. All rights reserved.
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
@ -19,7 +18,7 @@
#define TRACE_PCI
#ifndef TRACE_PCI
# define TRACE(x)
# define TRACE(x)
#else
# define TRACE(x) dprintf x
#endif
@ -30,104 +29,131 @@
struct PCIDev;
struct PCIBus {
PCIBus *next;
PCIDev *parent;
PCIDev *child;
int domain;
uint8 bus;
PCIBus * next;
PCIDev * parent;
PCIDev * child;
int domain;
uint8 bus;
};
struct PCIDev {
PCIDev *next;
PCIBus *parent;
PCIBus *child;
int domain;
uint8 bus;
uint8 dev;
uint8 func;
pci_info info;
PCIDev * next;
PCIBus * parent;
PCIBus * child;
int domain;
uint8 bus;
uint8 device;
uint8 function;
pci_info info;
};
struct domain_data
{
struct domain_data {
// These two are set in PCI::AddController:
pci_controller * controller;
void * controller_cookie;
// All the rest is set in PCI::InitDomainData
int max_bus_devices;
};
class PCI {
public:
public:
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,
uint8 offset, uint8 size, uint32 *value);
status_t GetNthInfo(long index, pci_info *outInfo);
uint32 ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function,
uint8 offset, uint8 size);
status_t ReadConfig(int domain, uint8 bus, uint8 device,
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,
uint8 offset, uint8 size, uint32 value);
status_t WriteConfig(int domain, uint8 bus, uint8 device,
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);
void ClearDeviceStatus(PCIBus *bus, bool dumpStatus);
status_t FindCapability(int domain, uint8 bus, uint8 device,
uint8 function, uint8 capID, uint8 *offset);
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);
void DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func);
private:
void _EnumerateBus(int domain, uint8 bus,
uint8 *subordinateBus = NULL);
PCIDev *CreateDevice(PCIBus *parent, uint8 dev, uint8 func);
PCIBus *CreateBus(PCIDev *parent, int domain, uint8 bus);
void _FixupDevices(int domain, uint8 bus);
status_t GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInfo);
void ReadPciBasicInfo(PCIDev *dev);
void ReadPciHeaderInfo(PCIDev *dev);
void _DiscoverBus(PCIBus *bus);
void _DiscoverDevice(PCIBus *bus, uint8 dev,
uint8 function);
void ConfigureBridges(PCIBus *bus);
void RefreshDeviceInfo(PCIBus *bus);
PCIDev * _CreateDevice(PCIBus *parent, uint8 dev,
uint8 function);
PCIBus * _CreateBus(PCIDev *parent, int domain, uint8 bus);
uint32 BarSize(uint32 bits, uint32 mask);
void GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size = 0, uint8 *flags = 0);
void GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size = 0, uint8 *flags = 0);
domain_data * GetDomainData(int domain);
status_t CreateVirtualBus(int domain, uint8 bus, uint8 *virtualBus);
status_t _GetNthInfo(PCIBus *bus, long *currentIndex,
long wantIndex, pci_info *outInfo);
void _ReadBasicInfo(PCIDev *dev);
void _ReadHeaderInfo(PCIDev *dev);
private:
PCIBus * fRootBus;
void _ConfigureBridges(PCIBus *bus);
void _RefreshDeviceInfo(PCIBus *bus);
enum { MAX_PCI_DOMAINS = 8 };
domain_data fDomainData[MAX_PCI_DOMAINS];
int fDomainCount;
bool fBusEnumeration;
uint32 _BarSize(uint32 bits, uint32 mask);
void _GetBarInfo(PCIDev *dev, uint8 offset,
uint32 *address, uint32 *size = 0,
uint8 *flags = 0);
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;
int fNextVirtualBus;
status_t _CreateVirtualBus(int domain, uint8 bus,
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
@ -140,8 +166,10 @@ void pci_uninit(void);
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);
void pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value);
uint32 pci_read_config(uint8 virtualBus, uint8 device, uint8 function,
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);

View File

@ -12,12 +12,13 @@
/* 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
* 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
* multifunction (split device) AHCI mode. This will set PCI device at function 0
* 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
* to AHCI, and PCI device at function 1 to IDE controller.
*/
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) {
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);
if (function == 0) {
dprintf("jmicron_fixup_ahci: 0x40: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x40, 4));
dprintf("jmicron_fixup_ahci: 0xdc: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0xdc, 4));
uint32 val = pci->ReadPciConfig(domain, bus, device, function, 0xdc, 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->ReadConfig(domain, bus, device, function, 0xdc, 4));
uint32 val = pci->ReadConfig(domain, bus, device, function, 0xdc, 4);
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");
val &= ~(1 << 24);
val |= (1 << 25) | (1 << 30);
pci->WritePciConfig(domain, bus, device, function, 0xdc, 4, val);
val = pci->ReadPciConfig(domain, bus, device, function, 0x40, 4);
pci->WriteConfig(domain, bus, device, function, 0xdc, 4, val);
val = pci->ReadConfig(domain, bus, device, function, 0x40, 4);
val &= ~(1 << 16);
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)
pci->WritePciConfig(domain, bus, device, 1, 0x3c, 1, irq);
else
pci->WriteConfig(domain, bus, device, 1, 0x3c, 1, irq);
else
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: 0xdc: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0xdc, 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->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",
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: 0x90: 0x%02lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x90, 1));
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->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) {
uint32 bar5 = pci->ReadPciConfig(domain, bus, device, function, 0x24, 4);
uint16 pcicmd = pci->ReadPciConfig(domain, bus, device, function, PCI_command, 2);
uint32 bar5 = pci->ReadConfig(domain, bus, device, function, 0x24, 4);
uint16 pcicmd = pci->ReadConfig(domain, bus, device, function, PCI_command, 2);
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));
pci->WritePciConfig(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));
pci->WritePciConfig(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));
pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff);
dprintf("intel_fixup_ahci: ide-bar5 bits-1: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4));
pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0);
dprintf("intel_fixup_ahci: ide-bar5 bits-0: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4));
map &= ~0x03;
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);
dprintf("intel_fixup_ahci: ahci-bar5 bits-1: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x24, 4));
pci->WritePciConfig(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));
pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff);
dprintf("intel_fixup_ahci: ahci-bar5 bits-1: 0x%08lx\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4));
pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0);
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
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: 0x90: 0x%02lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x90, 1));
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->ReadConfig(domain, bus, device, function, 0x90, 1));
}
void
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 deviceId = pci->ReadPciConfig(domain, bus, device, function, PCI_device_id, 2);
uint16 vendorId = pci->ReadConfig(domain, bus, device, function, PCI_vendor_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);