vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / bus_managers / pci / pci_fixup.cpp
blobd25e96f9e1ff093aa6fe52fdadbee41136f575c3
1 /*
2 * Copyright 2007, Marcus Overhagen. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
6 #include "pci.h"
7 #include "pci_fixup.h"
9 #include <arch/int.h>
11 #include <KernelExport.h>
15 * We need to force controllers that have both SATA and PATA controllers to use
16 * the split mode with the SATA controller at function 0 and the PATA
17 * controller at function 1. This way the SATA controller will be picked up by
18 * the AHCI driver and the IDE controller by the generic IDE driver.
20 * TODO(bga): This does not work when the SATA controller is configured for IDE
21 * mode but this seems to be a problem with the device manager (it tries to load
22 * the IDE driver for the AHCI controller for some reason).
24 static void
25 jmicron_fixup_ahci(PCI *pci, uint8 domain, uint8 bus, uint8 device,
26 uint8 function, uint16 deviceId)
28 // We only care about function 0.
29 if (function != 0)
30 return;
32 // And only devices with combined SATA/PATA.
33 switch (deviceId) {
34 case 0x2361: // 1 SATA, 1 PATA
35 case 0x2363: // 2 SATA, 1 PATA
36 case 0x2366: // 2 SATA, 2 PATA
37 break;
38 default:
39 return;
42 dprintf("jmicron_fixup_ahci: domain %u, bus %u, device %u, function %u, "
43 "deviceId 0x%04x\n", domain, bus, device, function, deviceId);
45 // Read controller control register (0x40).
46 uint32 val = pci->ReadConfig(domain, bus, device, function, 0x40, 4);
47 dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08" B_PRIx32 "\n", val);
49 // Clear bits.
50 val &= ~(1 << 1);
51 val &= ~(1 << 9);
52 val &= ~(1 << 13);
53 val &= ~(1 << 15);
54 val &= ~(1 << 16);
55 val &= ~(1 << 17);
56 val &= ~(1 << 18);
57 val &= ~(1 << 19);
58 val &= ~(1 << 22);
60 //Set bits.
61 val |= (1 << 0);
62 val |= (1 << 4);
63 val |= (1 << 5);
64 val |= (1 << 7);
65 val |= (1 << 8);
66 val |= (1 << 12);
67 val |= (1 << 14);
68 val |= (1 << 23);
70 dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08" B_PRIx32 "\n", val);
71 pci->WriteConfig(domain, bus, device, function, 0x40, 4, val);
73 // Read IRQ from controller at function 0 and assign this IRQ to the
74 // controller at function 1.
75 uint8 irq = pci->ReadConfig(domain, bus, device, function, 0x3c, 1);
76 dprintf("jmicron_fixup_ahci: Assigning IRQ %d at device "
77 "function 1.\n", irq);
78 pci->WriteConfig(domain, bus, device, 1, 0x3c, 1, irq);
82 static void
83 intel_fixup_ahci(PCI *pci, uint8 domain, uint8 bus, uint8 device,
84 uint8 function, uint16 deviceId)
86 // TODO(bga): disabled until the PCI manager can assign new resources.
87 return;
89 switch (deviceId) {
90 case 0x2825: // ICH8 Desktop when in IDE emulation mode
91 dprintf("intel_fixup_ahci: WARNING found ICH8 device id 0x2825\n");
92 return;
93 case 0x2926: // ICH9 Desktop when in IDE emulation mode
94 dprintf("intel_fixup_ahci: WARNING found ICH9 device id 0x2926\n");
95 return;
97 case 0x27c0: // ICH7 Desktop non-AHCI and non-RAID mode
98 case 0x27c4: // ICH7 Mobile non-AHCI and non-RAID mode
99 case 0x2820: // ICH8 Desktop non-AHCI and non-RAID mode
100 case 0x2828: // ICH8 Mobile non-AHCI and non-RAID mode
101 case 0x2920: // ICH9 Desktop non-AHCI and non-RAID mode (4 ports)
102 case 0x2921: // ICH9 Desktop non-AHCI and non-RAID mode (2 ports)
103 break;
104 default:
105 return;
108 dprintf("intel_fixup_ahci: domain %u, bus %u, device %u, function %u, "
109 "deviceId 0x%04x\n", domain, bus, device, function, deviceId);
111 dprintf("intel_fixup_ahci: 0x24: 0x%08" B_PRIx32 "\n",
112 pci->ReadConfig(domain, bus, device, function, 0x24, 4));
113 dprintf("intel_fixup_ahci: 0x90: 0x%02" B_PRIx32 "\n",
114 pci->ReadConfig(domain, bus, device, function, 0x90, 1));
116 uint8 map = pci->ReadConfig(domain, bus, device, function, 0x90, 1);
117 if ((map >> 6) == 0) {
118 uint32 bar5 = pci->ReadConfig(domain, bus, device, function, 0x24, 4);
119 uint16 pcicmd = pci->ReadConfig(domain, bus, device, function,
120 PCI_command, 2);
122 dprintf("intel_fixup_ahci: switching from IDE to AHCI mode\n");
124 pci->WriteConfig(domain, bus, device, function, PCI_command, 2,
125 pcicmd & ~(PCI_command_io | PCI_command_memory));
127 pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff);
128 dprintf("intel_fixup_ahci: ide-bar5 bits-1: 0x%08" B_PRIx32 "\n",
129 pci->ReadConfig(domain, bus, device, function, 0x24, 4));
130 pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0);
131 dprintf("intel_fixup_ahci: ide-bar5 bits-0: 0x%08" B_PRIx32 "\n",
132 pci->ReadConfig(domain, bus, device, function, 0x24, 4));
134 map &= ~0x03;
135 map |= 0x40;
136 pci->WriteConfig(domain, bus, device, function, 0x90, 1, map);
138 pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff);
139 dprintf("intel_fixup_ahci: ahci-bar5 bits-1: 0x%08" B_PRIx32 "\n",
140 pci->ReadConfig(domain, bus, device, function, 0x24, 4));
141 pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0);
142 dprintf("intel_fixup_ahci: ahci-bar5 bits-0: 0x%08" B_PRIx32 "\n",
143 pci->ReadConfig(domain, bus, device, function, 0x24, 4));
145 if (deviceId == 0x27c0 || deviceId == 0x27c4) // restore on ICH7
146 pci->WriteConfig(domain, bus, device, function, 0x24, 4, bar5);
148 pci->WriteConfig(domain, bus, device, function, PCI_command, 2, pcicmd);
151 dprintf("intel_fixup_ahci: 0x24: 0x%08" B_PRIx32 "\n",
152 pci->ReadConfig(domain, bus, device, function, 0x24, 4));
153 dprintf("intel_fixup_ahci: 0x90: 0x%02" B_PRIx32 "\n",
154 pci->ReadConfig(domain, bus, device, function, 0x90, 1));
158 static void
159 ati_fixup_ixp(PCI *pci, uint8 domain, uint8 bus, uint8 device, uint8 function,
160 uint16 deviceId)
162 #if defined(__INTEL__) || defined(__x86_64__)
163 /* ATI Technologies Inc, IXP chipset:
164 * This chipset seems broken, at least on my laptop I must force
165 * the timer IRQ trigger mode, else no interrupt comes in.
166 * mmu_man.
168 // XXX: should I use host or isa bridges for detection ??
169 switch (deviceId) {
170 // Host bridges
171 case 0x5950: // RS480 Host Bridge
172 case 0x5830:
173 break;
174 // ISA bridges
175 case 0x4377: // IXP SB400 PCI-ISA Bridge
176 default:
177 return;
179 dprintf("ati_fixup_ixp: domain %u, bus %u, device %u, function %u, deviceId 0x%04x\n",
180 domain, bus, device, function, deviceId);
182 dprintf("ati_fixup_ixp: found IXP chipset, forcing IRQ 0 as level triggered.\n");
183 // XXX: maybe use pic_*() ?
184 arch_int_configure_io_interrupt(0, B_LEVEL_TRIGGERED);
186 #endif
190 void
191 pci_fixup_device(PCI *pci, uint8 domain, uint8 bus, uint8 device,
192 uint8 function)
194 uint16 vendorId = pci->ReadConfig(domain, bus, device, function,
195 PCI_vendor_id, 2);
196 uint16 deviceId = pci->ReadConfig(domain, bus, device, function,
197 PCI_device_id, 2);
199 // dprintf("pci_fixup_device: domain %u, bus %u, device %u, function %u\n",
200 // domain, bus, device, function);
202 switch (vendorId) {
203 case 0x197b:
204 jmicron_fixup_ahci(pci, domain, bus, device, function, deviceId);
205 break;
207 case 0x8086:
208 intel_fixup_ahci(pci, domain, bus, device, function, deviceId);
209 break;
211 case 0x1002:
212 ati_fixup_ixp(pci, domain, bus, device, function, deviceId);
213 break;