* 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:
parent
0f0fba6373
commit
705263f5b3
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user