Force multi-device mode for JMicron controllers supporting SATA/PATA
interfaces. This fixes bug #2227. Note that when the SATA interface is in AHCI mode it is still failing due to what seems to be a device manager problem. I will open a separate bug for it. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26902 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -8,18 +8,22 @@
|
|||||||
|
|
||||||
#include <KernelExport.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
|
* We need to force controllers that have both SATA and PATA controllers to use
|
||||||
* "AHCI" mode). To avoid needing two drivers to handle a single PCI device, we
|
* the split mode with the SATA controller at function 0 and the PATA
|
||||||
* switch to the multifunction (split device) AHCI mode. This will set PCI
|
* controller at function 1. This way the SATA controller will be picked up by
|
||||||
* device at function 0 to AHCI, and PCI device at function 1 to IDE controller.
|
* the AHCI driver and the IDE controller by the generic IDE driver.
|
||||||
|
*
|
||||||
|
* TODO(bga): This does not work when the SATA controller is configured for IDE
|
||||||
|
* mode but this seems to be a problem with the device manager (it tries to load
|
||||||
|
* the IDE driver for the AHCI controller for some reason).
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
jmicron_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device,
|
jmicron_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device,
|
||||||
uint8 function, uint16 deviceId)
|
uint8 function, uint16 deviceId)
|
||||||
{
|
{
|
||||||
// We only care about devices with function 0.
|
// We only care about function 0.
|
||||||
if (function != 0)
|
if (function != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -36,42 +40,40 @@ jmicron_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device,
|
|||||||
dprintf("jmicron_fixup_ahci: domain %u, bus %u, device %u, function %u, "
|
dprintf("jmicron_fixup_ahci: domain %u, bus %u, device %u, function %u, "
|
||||||
"deviceId 0x%04x\n", domain, bus, device, function, deviceId);
|
"deviceId 0x%04x\n", domain, bus, device, function, deviceId);
|
||||||
|
|
||||||
uint32 val = pci->ReadConfig(domain, bus, device, function, 0xdc, 4);
|
// Read controller control register (0x40).
|
||||||
if (!(val & (1 << 30))) {
|
uint32 val = pci->ReadConfig(domain, bus, device, function, 0x40, 4);
|
||||||
// IDE controller at function 1 is configured in IDE mode (as opposed
|
dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08lx\n", val);
|
||||||
// to AHCI or RAID). So we want to handle it.
|
|
||||||
dprintf("jmicron_fixup_ahci: PATA controller in IDE mode.\n");
|
|
||||||
|
|
||||||
// TODO(bga): It seems that with recent BIOS revisions no special code
|
// Clear bits.
|
||||||
// is needed here. We still want to handle IRQ assignment as seen
|
val &= ~(1 << 1);
|
||||||
// below.
|
val &= ~(1 << 9);
|
||||||
|
val &= ~(1 << 13);
|
||||||
|
val &= ~(1 << 15);
|
||||||
|
val &= ~(1 << 16);
|
||||||
|
val &= ~(1 << 17);
|
||||||
|
val &= ~(1 << 18);
|
||||||
|
val &= ~(1 << 19);
|
||||||
|
val &= ~(1 << 22);
|
||||||
|
|
||||||
// Read IRQ from controller at function 0 and assign this IRQ to the
|
//Set bits.
|
||||||
// controller at function 1.
|
val |= (1 << 0);
|
||||||
uint8 irq = pci->ReadConfig(domain, bus, device, function, 0x3c, 1);
|
val |= (1 << 4);
|
||||||
pci->WriteConfig(domain, bus, device, 1, 0x3c, 1, irq);
|
val |= (1 << 5);
|
||||||
} else {
|
val |= (1 << 7);
|
||||||
// TODO(bga): If the PATA controller is set to AHCI mode, the IDE
|
val |= (1 << 8);
|
||||||
// driver will try to pick it up and will fail either because there is
|
val |= (1 << 12);
|
||||||
// no assigned IRQ or, if we assign an IRQ, because it errors-out when
|
val |= (1 << 14);
|
||||||
// detecting devices (probably because of the AHCI mode). Then the AHCI
|
val |= (1 << 23);
|
||||||
// driver picks the device up but fail to find the attached devices.
|
|
||||||
// Maybe fixing this would be as simple as changing the device class to
|
|
||||||
// Serial ATA Controller instead of IDE Controller (even in AHCI mode
|
|
||||||
// it reports being a standard IDE controller)?
|
|
||||||
dprintf("jmicron_fixup_ahci: PATA controller in AHCI or RAID mode.\n");
|
|
||||||
|
|
||||||
// Read controller control register (0x40). This should contain all the
|
|
||||||
// bits we need to change.
|
|
||||||
val = pci->ReadConfig(domain, bus, device, function, 0x40, 4);
|
|
||||||
dprintf("jmicron_fixup_ahci: Register 0x40 : %0x%08lx\n", val);
|
|
||||||
|
|
||||||
// TODO(bga): Do some bit shuffling here to set the controller to split
|
dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08lx\n", val);
|
||||||
// mode. Right now, the write operation bellow is a no-op.
|
pci->WriteConfig(domain, bus, device, function, 0x40, 4, val);
|
||||||
|
|
||||||
// Write controller control register (0x40).
|
// Read IRQ from controller at function 0 and assign this IRQ to the
|
||||||
pci->WriteConfig(domain, bus, device, function, 0x40, 4, val);
|
// controller at function 1.
|
||||||
}
|
uint8 irq = pci->ReadConfig(domain, bus, device, function, 0x3c, 1);
|
||||||
|
dprintf("jmicron_fixup_ahci: Assigning IRQ %d at device "
|
||||||
|
"function 1.\n", irq);
|
||||||
|
pci->WriteConfig(domain, bus, device, 1, 0x3c, 1, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user