Root/
Source at commit HEAD created 5 years 6 days ago. By ifabio, Few update to kernelPatcher (Credits to CrazyBirdy) | |
---|---|
1 | /*␊ |
2 | * usb.c␊ |
3 | * ␊ |
4 | *␊ |
5 | * Created by mackerintel on 12/20/08.␊ |
6 | * Copyright 2008 mackerintel. All rights reserved.␊ |
7 | *␊ |
8 | */␊ |
9 | ␊ |
10 | #include "config.h"␊ |
11 | #include "libsaio.h"␊ |
12 | #include "boot.h"␊ |
13 | #include "bootstruct.h"␊ |
14 | #include "pci.h"␊ |
15 | ␊ |
16 | #if DEBUG_USB␊ |
17 | ␉#define DBG(x...)␉printf(x)␊ |
18 | #else␊ |
19 | ␉#define DBG(x...)␊ |
20 | #endif␊ |
21 | ␊ |
22 | ␊ |
23 | struct pciList␊ |
24 | {␊ |
25 | ␉pci_dt_t* pciDev;␊ |
26 | ␉struct pciList* next;␊ |
27 | };␊ |
28 | ␊ |
29 | struct pciList* usbList = NULL;␊ |
30 | ␊ |
31 | static int legacy_off (pci_dt_t *pci_dev);␊ |
32 | static int ehci_acquire (pci_dt_t *pci_dev);␊ |
33 | static int uhci_reset (pci_dt_t *pci_dev);␊ |
34 | static int xhci_legacy_off(pci_dt_t *pci_dev);␊ |
35 | ␊ |
36 | // Add usb device to the list␊ |
37 | void notify_usb_dev(pci_dt_t *pci_dev)␊ |
38 | {␊ |
39 | ␉struct pciList *current = usbList;␊ |
40 | ␉if(!usbList)␊ |
41 | ␉{␊ |
42 | ␉␉usbList = (struct pciList*)malloc(sizeof(struct pciList));␊ |
43 | ␉␉usbList->next = NULL;␊ |
44 | ␉␉usbList->pciDev = pci_dev;␊ |
45 | ␉␉␊ |
46 | ␉}␊ |
47 | ␉else␊ |
48 | ␉{␊ |
49 | ␉␉while(current != NULL && current->next != NULL)␊ |
50 | ␉␉{␊ |
51 | ␉␉␉current = current->next;␊ |
52 | ␉␉}␊ |
53 | ␉␉current->next = (struct pciList*)malloc(sizeof(struct pciList));␊ |
54 | ␉␉current = current->next;␊ |
55 | ␉␉␊ |
56 | ␉␉current->pciDev = pci_dev;␊ |
57 | ␉␉current->next = NULL;␊ |
58 | ␉}␊ |
59 | }␊ |
60 | ␊ |
61 | // Loop through the list and call the apropriate patch function␊ |
62 | int usb_loop()␊ |
63 | {␊ |
64 | ␉int retVal = 1;␊ |
65 | ␉bool fix_xhci, fix_ehci, fix_uhci, fix_usb, fix_legacy;␊ |
66 | ␉fix_xhci = fix_ehci = fix_uhci = fix_usb = fix_legacy = false;␊ |
67 | ␉␊ |
68 | ␉if (getBoolForKey(kUSBBusFix, &fix_usb, &bootInfo->chameleonConfig))␊ |
69 | ␉{␊ |
70 | ␉␉fix_xhci = fix_ehci = fix_uhci = fix_legacy = fix_usb;␉// Disable all if none set␊ |
71 | ␉}␊ |
72 | ␉else ␊ |
73 | ␉{␊ |
74 | ␉␉getBoolForKey(kXHCILegacyOff, &fix_xhci, &bootInfo->chameleonConfig);␊ |
75 | ␉␉getBoolForKey(kEHCIacquire, &fix_ehci, &bootInfo->chameleonConfig);␊ |
76 | ␉␉getBoolForKey(kUHCIreset, &fix_uhci, &bootInfo->chameleonConfig);␊ |
77 | ␉␉getBoolForKey(kLegacyOff, &fix_legacy, &bootInfo->chameleonConfig);␊ |
78 | ␉}␊ |
79 | ␉␊ |
80 | ␉struct pciList *current = usbList;␊ |
81 | ␉␊ |
82 | ␉while(current)␊ |
83 | ␉{␊ |
84 | ␉␉switch (pci_config_read8(current->pciDev->dev.addr, PCI_CLASS_PROG))␊ |
85 | ␉␉{␊ |
86 | ␉␉␉// XHCI␊ |
87 | ␉␉␉case PCI_IF_XHCI:␊ |
88 | ␉␉␉␉if(fix_xhci || fix_legacy) retVal &= xhci_legacy_off(current->pciDev);␊ |
89 | ␉␉␉␉break;␊ |
90 | ␊ |
91 | ␉␉␉// EHCI␊ |
92 | ␉␉␉case PCI_IF_EHCI:␊ |
93 | ␉␉ ␉if(fix_ehci) retVal &= ehci_acquire(current->pciDev);␊ |
94 | ␉␉ ␉if(fix_legacy) retVal &= legacy_off(current->pciDev);␊ |
95 | ␉␉␉␉␊ |
96 | ␉␉␉␉break;␊ |
97 | ␉␉␉␉␊ |
98 | ␉␉␉// UHCI␊ |
99 | ␉␉␉case PCI_IF_UHCI:␊ |
100 | ␉␉␉␉if (fix_uhci) retVal &= uhci_reset(current->pciDev);␊ |
101 | ␊ |
102 | ␉␉␉␉break;␊ |
103 | ␉␉}␊ |
104 | ␉␉␊ |
105 | ␉␉current = current->next;␊ |
106 | ␉}␊ |
107 | ␉return retVal;␊ |
108 | }␊ |
109 | ␊ |
110 | static int legacy_off (pci_dt_t *pci_dev)␊ |
111 | {␊ |
112 | ␉// Set usb legacy off modification by Signal64␊ |
113 | ␉// NOTE: This *must* be called after the last file is loaded from the drive in the event that we are booting form usb.␊ |
114 | ␉// NOTE2: This should be called after any getc()/getchar() call. (aka, after the Wait=y keyworkd is used)␊ |
115 | ␉// AKA: Make this run immediatly before the kernel is called␊ |
116 | ␉uint32_t␉capaddr, opaddr; ␉␉␊ |
117 | ␉uint8_t␉␉eecp;␉␉␉␊ |
118 | ␉uint32_t␉usbcmd, usbsts, usbintr;␉␉␉␊ |
119 | ␉uint32_t␉usblegsup, usblegctlsts;␉␉␊ |
120 | ␉␊ |
121 | ␉int isOSowned;␊ |
122 | ␉int isBIOSowned;␊ |
123 | ␉␊ |
124 | ␉verbose("\tSetting Legacy USB Off on controller [%04x:%04x] at %02x:%2x.%x\n", ␊ |
125 | ␉␉␉pci_dev->vendor_id, pci_dev->device_id,␊ |
126 | ␉␉␉pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func);␊ |
127 | ␉␊ |
128 | ␉␊ |
129 | ␉// capaddr = Capability Registers = dev.addr + offset stored in dev.addr + 0x10 (USBBASE)␊ |
130 | ␉capaddr = pci_config_read32(pci_dev->dev.addr, 0x10);␉␊ |
131 | ␉␊ |
132 | ␉// opaddr = Operational Registers = capaddr + offset (8bit CAPLENGTH in Capability Registers + offset 0)␊ |
133 | ␉opaddr = capaddr + *((unsigned char*)(capaddr)); ␉␉␊ |
134 | ␉␊ |
135 | ␉// eecp = EHCI Extended Capabilities offset = capaddr HCCPARAMS bits 15:8␊ |
136 | ␉eecp=*((unsigned char*)(capaddr + 9));␊ |
137 | ␉␊ |
138 | ␉DBG("\tcapaddr=%x opaddr=%x eecp=%x\n", capaddr, opaddr, eecp);␊ |
139 | ␉␊ |
140 | ␉usbcmd = *((unsigned int*)(opaddr));␉␉␉// Command Register␊ |
141 | ␉usbsts = *((unsigned int*)(opaddr + 4));␉␉// Status Register␊ |
142 | ␉usbintr = *((unsigned int*)(opaddr + 8));␉␉// Interrupt Enable Register␊ |
143 | ␉␊ |
144 | ␉DBG("\tusbcmd=%08x usbsts=%08x usbintr=%08x\n", usbcmd, usbsts, usbintr);␊ |
145 | ␉␊ |
146 | ␉// read PCI Config 32bit USBLEGSUP (eecp+0) ␊ |
147 | ␉usblegsup = pci_config_read32(pci_dev->dev.addr, eecp);␊ |
148 | ␉␊ |
149 | ␉// informational only␊ |
150 | ␉isBIOSowned = !!((usblegsup) & (1 << (16)));␊ |
151 | ␉isOSowned = !!((usblegsup) & (1 << (24)));␊ |
152 | ␉␊ |
153 | ␉// read PCI Config 32bit USBLEGCTLSTS (eecp+4) ␊ |
154 | ␉usblegctlsts = pci_config_read32(pci_dev->dev.addr, eecp + 4);␊ |
155 | ␉␊ |
156 | ␉DBG("\tusblegsup=%08x isOSowned=%d isBIOSowned=%d usblegctlsts=%08x\n", usblegsup, isOSowned, isBIOSowned, usblegctlsts);␊ |
157 | ␉␊ |
158 | ␉// Reset registers to Legacy OFF␊ |
159 | ␉DBG("\tClearing USBLEGCTLSTS\n");␊ |
160 | ␉pci_config_write32(pci_dev->dev.addr, eecp + 4, 0);␉//usblegctlsts␊ |
161 | ␉␊ |
162 | ␉delay(100000);␊ |
163 | ␉␊ |
164 | ␉usbcmd = *((unsigned int*)(opaddr));␊ |
165 | ␉usbsts = *((unsigned int*)(opaddr + 4));␊ |
166 | ␉usbintr = *((unsigned int*)(opaddr + 8));␊ |
167 | ␉␊ |
168 | ␉DBG("\tusbcmd=%08x usbsts=%08x usbintr=%08x\n", usbcmd, usbsts, usbintr);␊ |
169 | ␉␊ |
170 | ␉DBG("\tClearing Registers\n");␊ |
171 | ␉␊ |
172 | ␉// clear registers to default␊ |
173 | ␉usbcmd = (usbcmd & 0xffffff00);␊ |
174 | ␉*((unsigned int*)(opaddr)) = usbcmd;␊ |
175 | ␉*((unsigned int*)(opaddr + 8)) = 0;␉␉␉␉␉//usbintr - clear interrupt registers␊ |
176 | ␉*((unsigned int*)(opaddr + 4)) = 0x1000;␉␉␉//usbsts - clear status registers ␉␊ |
177 | ␉pci_config_write32(pci_dev->dev.addr, eecp, 1);␉␉//usblegsup␊ |
178 | ␉␊ |
179 | ␉// get the results␊ |
180 | ␉usbcmd = *((unsigned int*)(opaddr));␊ |
181 | ␉usbsts = *((unsigned int*)(opaddr + 4));␊ |
182 | ␉usbintr = *((unsigned int*)(opaddr + 8));␊ |
183 | ␉␊ |
184 | ␉DBG("usbcmd=%08x usbsts=%08x usbintr=%08x\n", usbcmd, usbsts, usbintr);␊ |
185 | ␉␊ |
186 | ␉// read 32bit USBLEGSUP (eecp+0) ␊ |
187 | ␉usblegsup = pci_config_read32(pci_dev->dev.addr, eecp);␊ |
188 | ␉␊ |
189 | ␉// informational only␊ |
190 | ␉isBIOSowned = !!((usblegsup) & (1 << (16)));␊ |
191 | ␉isOSowned = !!((usblegsup) & (1 << (24)));␊ |
192 | ␉␊ |
193 | ␉// read 32bit USBLEGCTLSTS (eecp+4) ␊ |
194 | ␉usblegctlsts = pci_config_read32(pci_dev->dev.addr, eecp + 4);␊ |
195 | ␉␊ |
196 | ␉DBG("\tusblegsup=%08x isOSowned=%d isBIOSowned=%d usblegctlsts=%08x\n", usblegsup, isOSowned, isBIOSowned, usblegctlsts);␊ |
197 | ␉␊ |
198 | ␉verbose("\tLegacy USB Off Done\n");␉␊ |
199 | ␉return 1;␊ |
200 | }␊ |
201 | ␊ |
202 | static int ehci_acquire (pci_dt_t *pci_dev)␊ |
203 | {␊ |
204 | ␉int␉␉j, k;␊ |
205 | ␉uint32_t␉base;␊ |
206 | ␉uint8_t␉␉eecp;␊ |
207 | ␉uint8_t␉␉legacy[8];␊ |
208 | ␉bool␉␉isOwnershipConflict;␉␊ |
209 | ␉bool␉␉alwaysHardBIOSReset;␊ |
210 | ␊ |
211 | ␉alwaysHardBIOSReset = false;␉␊ |
212 | ␉if (!getBoolForKey(kEHCIhard, &alwaysHardBIOSReset, &bootInfo->chameleonConfig)) {␊ |
213 | ␉␉alwaysHardBIOSReset = true;␊ |
214 | ␉}␊ |
215 | ␊ |
216 | ␉pci_config_write16(pci_dev->dev.addr, 0x04, 0x0002);␊ |
217 | ␉base = pci_config_read32(pci_dev->dev.addr, 0x10);␊ |
218 | ␊ |
219 | ␉verbose("\tEHCI controller [%04x:%04x] at %02x:%2x.%x DMA @%x\n", ␊ |
220 | ␉␉pci_dev->vendor_id, pci_dev->device_id,␊ |
221 | ␉␉pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func, ␊ |
222 | ␉␉base);␊ |
223 | ␊ |
224 | ␉if (*((unsigned char*)base) < 0xc)␊ |
225 | ␉{␊ |
226 | ␉␉DBG("Config space too small: no legacy implementation\n");␊ |
227 | ␉␉return 1;␊ |
228 | ␉}␊ |
229 | ␉eecp = *((unsigned char*)(base + 9));␊ |
230 | ␉if (!eecp) {␊ |
231 | ␉␉DBG("No extended capabilities: no legacy implementation\n");␊ |
232 | ␉␉return 1;␊ |
233 | ␉}␊ |
234 | ␊ |
235 | ␉DBG("\teecp=%x\n",eecp);␊ |
236 | ␊ |
237 | ␉// bad way to do it␊ |
238 | ␉// pci_conf_write(pci_dev->dev.addr, eecp, 4, 0x01000001);␊ |
239 | ␉for (j = 0; j < 8; j++) {␊ |
240 | ␉␉legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);␊ |
241 | ␉␉DBG("\t%02x ", legacy[j]);␊ |
242 | ␉}␊ |
243 | ␉DBG("\n");␊ |
244 | ␊ |
245 | ␉//Real Job: based on orByte's AppleUSBEHCI.cpp␊ |
246 | ␉//We try soft reset first - some systems hang on reboot with hard reset␊ |
247 | ␉// Definitely needed during reboot on 10.4.6␊ |
248 | ␊ |
249 | ␉isOwnershipConflict = (((legacy[3] & 1) != 0) && ((legacy[2] & 1) != 0));␊ |
250 | ␉if (!alwaysHardBIOSReset && isOwnershipConflict) {␊ |
251 | ␉␉DBG("\tEHCI - Ownership conflict - attempting soft reset ...\n");␊ |
252 | ␉␉DBG("\tEHCI - toggle OS Ownership to 0\n");␊ |
253 | ␉␉pci_config_write8(pci_dev->dev.addr, eecp + 3, 0);␊ |
254 | ␉␉for (k = 0; k < 25; k++) {␊ |
255 | ␉␉␉for (j = 0; j < 8; j++) {␊ |
256 | ␉␉␉␉legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);␊ |
257 | ␉␉␉}␊ |
258 | ␉␉␉if (legacy[3] == 0) {␊ |
259 | ␉␉␉␉break;␊ |
260 | ␉␉␉}␊ |
261 | ␉␉␉delay(10);␊ |
262 | ␉␉}␊ |
263 | ␉}␉␊ |
264 | ␊ |
265 | ␉DBG("\tFound USBLEGSUP_ID - value %x:%x - writing OSOwned\n", legacy[3],legacy[2]);␊ |
266 | ␉pci_config_write8(pci_dev->dev.addr, eecp + 3, 1);␊ |
267 | ␊ |
268 | ␉// wait for kEHCI_USBLEGSUP_BIOSOwned bit to clear␊ |
269 | ␉for (k = 0; k < 25; k++) {␊ |
270 | ␉␉for (j = 0;j < 8; j++) {␊ |
271 | ␉␉␉legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);␊ |
272 | ␉␉}␊ |
273 | ␉␉DBG ("\t%x:%x,",legacy[3],legacy[2]);␊ |
274 | ␉␉if (legacy[2] == 0) {␊ |
275 | ␉␉␉break;␊ |
276 | ␉␉}␊ |
277 | ␉␉delay(10);␊ |
278 | ␉}␊ |
279 | ␊ |
280 | ␉for (j = 0;j < 8; j++) {␊ |
281 | ␉␉legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);␊ |
282 | ␉}␊ |
283 | ␉isOwnershipConflict = ((legacy[2]) != 0);␊ |
284 | ␉if (isOwnershipConflict) {␊ |
285 | ␉␉// Soft reset has failed. Assume SMI being ignored␊ |
286 | ␉␉// Hard reset␊ |
287 | ␉␉// Force Clear BIOS BIT␊ |
288 | ␉␉DBG("\tEHCI - Ownership conflict - attempting hard reset ...\n");␉␉␉␊ |
289 | ␉␉DBG ("\t%x:%x\n",legacy[3],legacy[2]);␊ |
290 | ␉␉DBG("\tEHCI - Force BIOS Ownership to 0\n");␊ |
291 | ␊ |
292 | ␉␉pci_config_write8(pci_dev->dev.addr, eecp + 2, 0);␊ |
293 | ␉␉for (k = 0; k < 25; k++) {␊ |
294 | ␉␉␉for (j = 0; j < 8; j++) {␊ |
295 | ␉␉␉␉legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);␊ |
296 | ␉␉␉}␊ |
297 | ␉␉␉DBG ("\t%x:%x,",legacy[3],legacy[2]);␊ |
298 | ␊ |
299 | ␉␉␉if ((legacy[2]) == 0) {␊ |
300 | ␉␉␉␉break;␊ |
301 | ␉␉␉}␊ |
302 | ␉␉␉delay(10);␉␊ |
303 | ␉␉}␉␉␊ |
304 | ␉␉// Disable further SMI events␊ |
305 | ␉␉for (j = 4; j < 8; j++) {␊ |
306 | ␉␉␉pci_config_write8(pci_dev->dev.addr, eecp + j, 0);␊ |
307 | ␉␉}␊ |
308 | ␉}␊ |
309 | ␊ |
310 | ␉for (j = 0; j < 8; j++) {␊ |
311 | ␉␉legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);␊ |
312 | ␉}␊ |
313 | ␊ |
314 | ␉DBG ("\t%x:%x\n",legacy[3],legacy[2]);␊ |
315 | ␊ |
316 | ␉// Final Ownership Resolution Check...␊ |
317 | ␉if (legacy[2] & 1) {␉␉␉␉␉␊ |
318 | ␉␉DBG("\tEHCI controller unable to take control from BIOS\n");␊ |
319 | ␉␉return 0;␊ |
320 | ␉}␊ |
321 | ␊ |
322 | ␉DBG("\tEHCI Acquire OS Ownership done\n");␉␊ |
323 | ␉return 1;␊ |
324 | }␊ |
325 | ␊ |
326 | static int uhci_reset (pci_dt_t *pci_dev)␊ |
327 | {␊ |
328 | ␉uint32_t base, port_base;␊ |
329 | ␉␊ |
330 | ␉base = pci_config_read32(pci_dev->dev.addr, 0x20);␊ |
331 | ␉port_base = (base >> 5) & 0x07ff;␊ |
332 | ␊ |
333 | ␉verbose("\tUHCI controller [%04x:%04x] at %02x:%2x.%x base %x(%x)\n", ␊ |
334 | ␉␉pci_dev->vendor_id, pci_dev->device_id,␊ |
335 | ␉␉pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func, ␊ |
336 | ␉␉port_base, base);␊ |
337 | ␉␊ |
338 | ␉pci_config_write16(pci_dev->dev.addr, 0xc0, 0x8f00);␊ |
339 | ␊ |
340 | ␉outw (port_base, 0x0002);␊ |
341 | ␉delay(10);␊ |
342 | ␉outw (port_base+4,0);␊ |
343 | ␉delay(10);␊ |
344 | ␉outw (port_base,0);␊ |
345 | ␉return 1;␊ |
346 | }␊ |
347 | ␊ |
348 | static int xhci_legacy_off(pci_dt_t *pci_dev)␊ |
349 | {␊ |
350 | ␉uint32_t bar0, hccparams1, extendCap, value;␊ |
351 | ␉int32_t timeOut;␊ |
352 | ␊ |
353 | ␉verbose("\tSetting Legacy USB Off on xHC [%04x:%04x] at %02x:%2x.%x\n",␊ |
354 | ␉␉␉pci_dev->vendor_id, pci_dev->device_id,␊ |
355 | ␉␉␉pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func);␊ |
356 | ␊ |
357 | ␉bar0 = pci_config_read32(pci_dev->dev.addr, 16);␊ |
358 | ␉/*␊ |
359 | ␉ * Check if memory bar␊ |
360 | ␉ */␊ |
361 | ␉if (bar0 & 1)␊ |
362 | ␉{␊ |
363 | ␉␉DBG("\t%s: BAR0 not a memory range\n", __FUNCTION__);␊ |
364 | ␉␉return 0;␊ |
365 | ␉}␊ |
366 | ␉/*␊ |
367 | ␉ * Check if outside 32-bit physical address space␊ |
368 | ␉ */␊ |
369 | ␉if (((bar0 & 6) == 4) &&␊ |
370 | ␉␉pci_config_read32(pci_dev->dev.addr, 20))␊ |
371 | ␉{␊ |
372 | ␉␉DBG("\t%s: BAR0 outside 32-bit physical address space\n", __FUNCTION__);␊ |
373 | ␉␉return 0;␊ |
374 | ␉}␊ |
375 | ␉bar0 &= ~15;␊ |
376 | ␊ |
377 | ␉hccparams1 = *(uint32_t const volatile*) (bar0 + 16);␊ |
378 | ␉if (hccparams1 == ~0)␊ |
379 | ␉{␊ |
380 | ␉␉DBG("\t%s: hccparams1 invalid 0x%x\n", __FUNCTION__, hccparams1);␊ |
381 | ␉␉return 0;␊ |
382 | ␉}␊ |
383 | ␉extendCap = (hccparams1 >> 14) & 0x3fffc;␊ |
384 | ␉while (extendCap) {␊ |
385 | ␉␉value = *(uint32_t const volatile*) (bar0 + extendCap);␊ |
386 | ␉␉if (value == ~0)␊ |
387 | ␉␉{␊ |
388 | ␉␉␉break;␊ |
389 | ␉␉}␊ |
390 | ␉␉if ((value & 0xff) == 1) {␊ |
391 | #if DEBUG_USB␊ |
392 | ␉␉␉verbose("\t%s: Found USBLEGSUP 0x%x, USBLEGCTLSTS 0x%x\n", __FUNCTION__,␊ |
393 | ␉␉␉␉␉value, *(uint32_t const volatile*) (bar0 + extendCap + 4));␊ |
394 | #endif␊ |
395 | ␉␉␉value |= (1 << 24);␊ |
396 | ␉␉␉*(uint32_t volatile*) (bar0 + extendCap) = value;␊ |
397 | ␉␉␉timeOut = 40;␊ |
398 | ␉␉␉while (timeOut--)␊ |
399 | ␉␉␉{␊ |
400 | ␉␉␉␉delay(500);␊ |
401 | ␉␉␉␉value = *(uint32_t const volatile*) (bar0 + extendCap);␊ |
402 | ␉␉␉␉if (value == ~0)␊ |
403 | ␉␉␉␉{␊ |
404 | ␉␉␉␉␉timeOut = -1;␊ |
405 | ␉␉␉␉␉break;␊ |
406 | ␉␉␉␉}␊ |
407 | ␉␉␉␉if ((value & 0x01010000) == 0x01000000)␊ |
408 | ␉␉␉␉{␊ |
409 | ␉␉␉␉␉timeOut = -1;␉/* Optional - always disable the SMI */␊ |
410 | ␉␉␉␉␉break;␊ |
411 | ␉␉␉␉}␊ |
412 | ␉␉␉}␊ |
413 | #if DEBUG_USB␊ |
414 | ␉␉␉verbose("\t%s: USBLEGSUP 0x%x, USBLEGCTLSTS 0x%x\n", __FUNCTION__,␊ |
415 | ␉␉␉␉␉value, *(uint32_t const volatile*) (bar0 + extendCap + 4));␊ |
416 | #endif␊ |
417 | ␉␉␉if (timeOut >= 0)␊ |
418 | ␉␉␉{␊ |
419 | ␉␉␉␉break;␊ |
420 | ␉␉␉}␊ |
421 | ␉␉␉/*␊ |
422 | ␉␉␉ * Disable the SMI in USBLEGCTLSTS if BIOS doesn't respond␊ |
423 | ␉␉␉ */␊ |
424 | ␉␉␉value = *(uint32_t const volatile*) (bar0 + extendCap + 4);␊ |
425 | ␉␉␉if (value == ~0)␊ |
426 | ␉␉␉{␊ |
427 | ␉␉␉␉break;␊ |
428 | ␉␉␉}␊ |
429 | ␉␉␉value &= 0x1f1fee;␊ |
430 | ␉␉␉value |= 0xe0000000;␊ |
431 | ␉␉␉*(uint32_t volatile*) (bar0 + extendCap + 4) = value;␊ |
432 | ␉␉␉break;␊ |
433 | ␉␉}␊ |
434 | ␉␉if (!(value & 0xff00))␊ |
435 | ␉␉␉break;␊ |
436 | ␉␉extendCap += ((value >> 6) & 0x3fc);␊ |
437 | ␉}␊ |
438 | ␉verbose("\tXHCI Legacy Off Done\n");␊ |
439 | ␉return 1;␊ |
440 | }␊ |
441 |