#include "pci.h"
#include "pci_fixup.h"
#include <arch/int.h>
#include <KernelExport.h>
static void
jmicron_fixup_ahci(PCI *pci, uint8 domain, uint8 bus, uint8 device,
uint8 function, uint16 deviceId)
{
if (function != 0)
return;
switch (deviceId) {
case 0x2361:
case 0x2363:
case 0x2366:
break;
default:
return;
}
dprintf("jmicron_fixup_ahci: domain %u, bus %u, device %u, function %u, "
"deviceId 0x%04x\n", domain, bus, device, function, deviceId);
uint32 val = pci->ReadConfig(domain, bus, device, function, 0x40, 4);
dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08" B_PRIx32 "\n", val);
val &= ~(1 << 1);
val &= ~(1 << 9);
val &= ~(1 << 13);
val &= ~(1 << 15);
val &= ~(1 << 16);
val &= ~(1 << 17);
val &= ~(1 << 18);
val &= ~(1 << 19);
val &= ~(1 << 22);
val |= (1 << 0);
val |= (1 << 4);
val |= (1 << 5);
val |= (1 << 7);
val |= (1 << 8);
val |= (1 << 12);
val |= (1 << 14);
val |= (1 << 23);
dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08" B_PRIx32 "\n", val);
pci->WriteConfig(domain, bus, device, function, 0x40, 4, val);
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);
}
static void
intel_fixup_ahci(PCI *pci, uint8 domain, uint8 bus, uint8 device,
uint8 function, uint16 deviceId)
{
return;
switch (deviceId) {
case 0x2825:
dprintf("intel_fixup_ahci: WARNING found ICH8 device id 0x2825\n");
return;
case 0x2926:
dprintf("intel_fixup_ahci: WARNING found ICH9 device id 0x2926\n");
return;
case 0x27c0:
case 0x27c4:
case 0x2820:
case 0x2828:
case 0x2920:
case 0x2921:
break;
default:
return;
}
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%08" B_PRIx32 "\n",
pci->ReadConfig(domain, bus, device, function, 0x24, 4));
dprintf("intel_fixup_ahci: 0x90: 0x%02" B_PRIx32 "\n",
pci->ReadConfig(domain, bus, device, function, 0x90, 1));
uint8 map = pci->ReadConfig(domain, bus, device, function, 0x90, 1);
if ((map >> 6) == 0) {
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->WriteConfig(domain, bus, device, function, PCI_command, 2,
pcicmd & ~(PCI_command_io | PCI_command_memory));
pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff);
dprintf("intel_fixup_ahci: ide-bar5 bits-1: 0x%08" B_PRIx32 "\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%08" B_PRIx32 "\n",
pci->ReadConfig(domain, bus, device, function, 0x24, 4));
map &= ~0x03;
map |= 0x40;
pci->WriteConfig(domain, bus, device, function, 0x90, 1, map);
pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff);
dprintf("intel_fixup_ahci: ahci-bar5 bits-1: 0x%08" B_PRIx32 "\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%08" B_PRIx32 "\n",
pci->ReadConfig(domain, bus, device, function, 0x24, 4));
if (deviceId == 0x27c0 || deviceId == 0x27c4)
pci->WriteConfig(domain, bus, device, function, 0x24, 4, bar5);
pci->WriteConfig(domain, bus, device, function, PCI_command, 2, pcicmd);
}
dprintf("intel_fixup_ahci: 0x24: 0x%08" B_PRIx32 "\n",
pci->ReadConfig(domain, bus, device, function, 0x24, 4));
dprintf("intel_fixup_ahci: 0x90: 0x%02" B_PRIx32 "\n",
pci->ReadConfig(domain, bus, device, function, 0x90, 1));
}
static void
ati_fixup_ixp(PCI *pci, uint8 domain, uint8 bus, uint8 device, uint8 function,
uint16 deviceId)
{
#if defined(__i386__) || defined(__x86_64__)
switch (deviceId) {
case 0x5950:
case 0x5830:
break;
case 0x4377:
default:
return;
}
dprintf("ati_fixup_ixp: domain %u, bus %u, device %u, function %u, deviceId 0x%04x\n",
domain, bus, device, function, deviceId);
dprintf("ati_fixup_ixp: found IXP chipset, forcing IRQ 0 as level triggered.\n");
arch_int_configure_io_interrupt(0, B_LEVEL_TRIGGERED);
#endif
}
void
pci_fixup_device(PCI *pci, uint8 domain, uint8 bus, uint8 device,
uint8 function)
{
uint16 vendorId = pci->ReadConfig(domain, bus, device, function,
PCI_vendor_id, 2);
uint16 deviceId = pci->ReadConfig(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;
case 0x1002:
ati_fixup_ixp(pci, domain, bus, device, function, deviceId);
break;
}
}