New PCI quirk/fixup support.

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 AHCI, and PCI device at function 1 to IDE controller.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22868 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2007-11-10 15:51:40 +00:00
parent 83274b7115
commit 65621982c9
4 changed files with 90 additions and 6 deletions

View File

@ -5,6 +5,7 @@ UsePrivateHeaders [ FDirName kernel util ] ;
KernelAddon pci :
pci.cpp
pci_fixup.cpp
pci_info.cpp
pci_module.c
pci_device.c

View File

@ -13,6 +13,7 @@
#include <PCI.h>
#include "util/kernel_cpp.h"
#include "pci_fixup.h"
#include "pci_priv.h"
#include "pci.h"
@ -328,12 +329,8 @@ PCI::InitBus()
ppnext = &bus->next;
}
bool bus_enumeration = true;
if (bus_enumeration) {
for (int i = 0; i < fDomainCount; i++) {
EnumerateBus(i, 0);
}
for (int i = 0; i < fDomainCount; i++) {
EnumerateBus(i, 0);
}
if (fRootBus) {
@ -511,6 +508,8 @@ PCI::EnumerateBus(int domain, uint8 bus, uint8 *subordinate_bus)
if (device_id == 0xffff)
continue;
pci_fixup_device(this, domain, bus, dev, func);
uint8 base_class = ReadPciConfig(domain, bus, dev, func, PCI_class_base, 1);
uint8 sub_class = ReadPciConfig(domain, bus, dev, func, PCI_class_sub, 1);
if (base_class != PCI_bridge || sub_class != PCI_pci)

View File

@ -0,0 +1,70 @@
/*
* Copyright 2007, Marcus Overhagen. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#include "pci.h"
#include "pci_fixup.h"
#include <KernelExport.h>
/* 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 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)
{
if (deviceId != 0x2360 && deviceId != 0x2361 && deviceId != 0x2362 && deviceId != 0x2363 && deviceId != 0x2366)
return;
dprintf("jmicron_fixup_ahci: domain %u, bus %u, device %u, function %u, deviceId 0x%04x\n",
domain, bus, device, function, deviceId);
if (function == 0) {
dprintf("0x40: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x40, 4));
dprintf("0xdc: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0xdc, 4));
uint32 val = pci->ReadPciConfig(domain, bus, device, function, 0xdc, 4);
if (!(val & (1 << 30))) {
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);
val &= ~(1 << 16);
val |= (1 << 1) | (1 << 17) | (1 << 22);
pci->WritePciConfig(domain, bus, device, function, 0x40, 4, val);
}
dprintf("0x40: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0x40, 4));
dprintf("0xdc: 0x%08lx\n", pci->ReadPciConfig(domain, bus, device, function, 0xdc, 4));
}
}
static void
intel_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function, uint16 deviceId)
{
}
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);
switch (vendorId) {
case 0x197b:
jmicron_fixup_ahci(pci, domain, bus, device, function, deviceId);
break;
case 0x8086:
intel_fixup_ahci(pci, domain, bus, device, function, deviceId);
break;
}
}

View File

@ -0,0 +1,14 @@
/*
* Copyright 2007, Marcus Overhagen. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _PCI_FIXUP_H
#define _PCI_FIXUP_H
class PCI;
void
pci_fixup_device(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function);
#endif