Reverted r44762 (removal of USB3.0 and HC driver separation work).
[AROS.git] / rom / usb / pciusb / pci_aros.c
blob10fb8cce82000c6074d1686a4d4f5745042155b4
1 /* pci_aros.c - pci access abstraction for AROS by Chris Hodges
2 */
4 #include <aros/bootloader.h>
5 #include <aros/symbolsets.h>
6 #include <exec/types.h>
7 #include <oop/oop.h>
8 #include <devices/timer.h>
9 #include <hidd/hidd.h>
10 #include <hidd/pci.h>
11 #include <hidd/irq.h>
12 #include <resources/acpi.h>
14 #include <proto/acpi.h>
15 #include <proto/bootloader.h>
16 #include <proto/oop.h>
17 #include <proto/utility.h>
18 #include <proto/exec.h>
20 #include <inttypes.h>
21 #include <string.h>
23 #include "uhwcmd.h"
24 #include "ohciproto.h"
26 #ifdef __i386__
27 #define HAVE_ACPI
28 #endif
29 #ifdef __x86_64__
30 #define HAVE_ACPI
31 #endif
33 #define NewList NEWLIST
35 #undef HiddPCIDeviceAttrBase
36 //#undef HiddUSBDeviceAttrBase
37 //#undef HiddUSBHubAttrBase
38 //#undef HiddUSBDrvAttrBase
39 #undef HiddAttrBase
41 #define HiddPCIDeviceAttrBase (hd->hd_HiddPCIDeviceAB)
42 //#define HiddUSBDeviceAttrBase (hd->hd_HiddUSBDeviceAB)
43 //#define HiddUSBHubAttrBase (hd->hd_HiddUSBHubAB)
44 //#define HiddUSBDrvAttrBase (hd->hd_HiddUSBDrvAB)
45 #define HiddAttrBase (hd->hd_HiddAB)
47 AROS_UFH3(void, pciEnumerator,
48 AROS_UFHA(struct Hook *, hook, A0),
49 AROS_UFHA(OOP_Object *, pciDevice, A2),
50 AROS_UFHA(APTR, message, A1))
52 AROS_USERFUNC_INIT
54 struct PCIDevice *hd = (struct PCIDevice *) hook->h_Data;
55 struct PCIController *hc;
56 IPTR hcitype;
57 IPTR bus;
58 IPTR dev;
59 IPTR sub;
60 IPTR intline;
61 ULONG devid;
63 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Interface, &hcitype);
64 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Bus, &bus);
65 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Dev, &dev);
66 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Dev, &sub);
67 OOP_GetAttr(pciDevice, aHidd_PCIDevice_INTLine, &intline);
69 devid = (bus<<16)|dev;
71 KPRINTF(10, ("Found PCI device 0x%lx of type %ld, Intline=%ld\n", devid, hcitype, intline));
73 if(intline == 255)
75 // we can't work without the correct interrupt line
76 // BIOS needs plug & play os option disabled. Alternatively AROS must support APIC reconfiguration
77 KPRINTF(200, ("ERROR: PCI card has no interrupt line assigned by BIOS, disable Plug & Play OS!\n"));
79 else
81 switch (hcitype)
83 case HCITYPE_OHCI:
84 #ifndef __powerpc__ /* It was not from me. Perhaps on PPC these drivers suffer from CPU cache problems? (sonic) */
85 case HCITYPE_EHCI:
86 case HCITYPE_UHCI:
87 #endif
88 #ifdef AROS_USB30_CODE
89 case HCITYPE_XHCI:
90 #endif
91 KPRINTF(10, ("Setting up device...\n"));
93 hc = AllocPooled(hd->hd_MemPool, sizeof(struct PCIController));
94 if (hc)
96 hc->hc_Device = hd;
97 hc->hc_DevID = devid;
98 hc->hc_FunctionNum = sub;
99 hc->hc_HCIType = hcitype;
100 hc->hc_PCIDeviceObject = pciDevice;
101 hc->hc_PCIIntLine = intline;
103 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Driver, (IPTR *) &hc->hc_PCIDriverObject);
105 NewList(&hc->hc_CtrlXFerQueue);
106 NewList(&hc->hc_IntXFerQueue);
107 NewList(&hc->hc_IsoXFerQueue);
108 NewList(&hc->hc_BulkXFerQueue);
109 NewList(&hc->hc_TDQueue);
110 NewList(&hc->hc_AbortQueue);
111 NewList(&hc->hc_PeriodicTDQueue);
112 NewList(&hc->hc_OhciRetireQueue);
113 AddTail(&hd->hd_TempHCIList, &hc->hc_Node);
115 break;
117 default:
118 KPRINTF(10, ("Unsupported HCI type %ld\n", hcitype));
122 AROS_USERFUNC_EXIT
125 /* /// "pciInit()" */
126 BOOL pciInit(struct PCIDevice *hd)
128 struct PCIController *hc;
129 struct PCIController *nexthc;
130 struct PCIUnit *hu;
131 ULONG unitno = 0;
133 KPRINTF(10, ("*** pciInit(%p) ***\n", hd));
134 /* if(sizeof(IPTR) > 4)
136 KPRINTF(200, ("I said the pciusb.device is not 64bit compatible right now. Go away!\n"));
137 return FALSE;
140 NewList(&hd->hd_TempHCIList);
142 if(!(hd->hd_IRQHidd = OOP_NewObject(NULL, (STRPTR) CLID_Hidd_IRQ, NULL)))
144 KPRINTF(20, ("Unable to create IRQHidd object!\n"));
145 return FALSE;
148 if((hd->hd_PCIHidd = OOP_NewObject(NULL, (STRPTR) CLID_Hidd_PCI, NULL)))
150 struct TagItem tags[] =
152 { tHidd_PCI_Class, (PCI_CLASS_SERIAL_USB>>8) & 0xff },
153 { tHidd_PCI_SubClass, (PCI_CLASS_SERIAL_USB & 0xff) },
154 { TAG_DONE, 0UL }
157 struct OOP_ABDescr attrbases[] =
159 { (STRPTR) IID_Hidd, &hd->hd_HiddAB },
160 { (STRPTR) IID_Hidd_PCIDevice, &hd->hd_HiddPCIDeviceAB },
161 { NULL, NULL }
164 struct Hook findHook =
166 h_Entry: (IPTR (*)()) pciEnumerator,
167 h_Data: hd,
170 OOP_ObtainAttrBases(attrbases);
172 KPRINTF(20, ("Searching for devices...\n"));
174 HIDD_PCI_EnumDevices(hd->hd_PCIHidd, &findHook, (struct TagItem *) &tags);
175 } else {
176 KPRINTF(20, ("Unable to create PCIHidd object!\n"));
177 OOP_DisposeObject(hd->hd_IRQHidd);
178 return FALSE;
181 // Create units with a list of host controllers having the same bus and device number.
182 while(hd->hd_TempHCIList.lh_Head->ln_Succ)
184 hu = AllocPooled(hd->hd_MemPool, sizeof(struct PCIUnit));
185 if(!hu)
187 // actually, we should get rid of the allocated memory first, but I don't care as DeletePool() will take care of this eventually
188 return FALSE;
190 hu->hu_Device = hd;
191 hu->hu_UnitNo = unitno;
192 hu->hu_DevID = ((struct PCIController *) hd->hd_TempHCIList.lh_Head)->hc_DevID;
194 NewList(&hu->hu_Controllers);
195 NewList(&hu->hu_RHIOQueue);
197 hc = (struct PCIController *) hd->hd_TempHCIList.lh_Head;
198 while((nexthc = (struct PCIController *) hc->hc_Node.ln_Succ))
200 if(hc->hc_DevID == hu->hu_DevID)
202 Remove(&hc->hc_Node);
203 hc->hc_Unit = hu;
204 AddTail(&hu->hu_Controllers, &hc->hc_Node);
206 hc = nexthc;
208 AddTail(&hd->hd_Units, (struct Node *) hu);
209 unitno++;
211 return TRUE;
213 /* \\\ */
215 /* /// "PCIXReadConfigByte()" */
216 UBYTE PCIXReadConfigByte(struct PCIController *hc, UBYTE offset)
218 struct pHidd_PCIDevice_ReadConfigByte msg;
220 msg.mID = OOP_GetMethodID(CLID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
221 msg.reg = offset;
223 return OOP_DoMethod(hc->hc_PCIDeviceObject, (OOP_Msg) &msg);
225 /* \\\ */
227 /* /// "PCIXReadConfigWord()" */
228 UWORD PCIXReadConfigWord(struct PCIController *hc, UBYTE offset)
230 struct pHidd_PCIDevice_ReadConfigWord msg;
232 msg.mID = OOP_GetMethodID(CLID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigWord);
233 msg.reg = offset;
235 return OOP_DoMethod(hc->hc_PCIDeviceObject, (OOP_Msg) &msg);
237 /* \\\ */
239 /* /// "PCIXReadConfigLong()" */
240 ULONG PCIXReadConfigLong(struct PCIController *hc, UBYTE offset)
242 struct pHidd_PCIDevice_ReadConfigLong msg;
244 msg.mID = OOP_GetMethodID(CLID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigLong);
245 msg.reg = offset;
247 return OOP_DoMethod(hc->hc_PCIDeviceObject, (OOP_Msg) &msg);
249 /* \\\ */
251 /* /// "PCIXWriteConfigByte()" */
252 void PCIXWriteConfigByte(struct PCIController *hc, ULONG offset, UBYTE value)
254 struct pHidd_PCIDevice_WriteConfigByte msg;
256 msg.mID = OOP_GetMethodID(CLID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
257 msg.reg = offset;
258 msg.val = value;
260 OOP_DoMethod(hc->hc_PCIDeviceObject, (OOP_Msg) &msg);
262 /* \\\ */
264 /* /// "PCIXWriteConfigWord()" */
265 void PCIXWriteConfigWord(struct PCIController *hc, ULONG offset, UWORD value)
267 struct pHidd_PCIDevice_WriteConfigWord msg;
269 msg.mID = OOP_GetMethodID(CLID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigWord);
270 msg.reg = offset;
271 msg.val = value;
273 OOP_DoMethod(hc->hc_PCIDeviceObject, (OOP_Msg) &msg);
275 /* \\\ */
277 /* /// "PCIXWriteConfigLong()" */
278 void PCIXWriteConfigLong(struct PCIController *hc, ULONG offset, ULONG value)
280 struct pHidd_PCIDevice_WriteConfigLong msg;
282 msg.mID = OOP_GetMethodID(CLID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigLong);
283 msg.reg = offset;
284 msg.val = value;
286 OOP_DoMethod(hc->hc_PCIDeviceObject, (OOP_Msg) &msg);
288 /* \\\ */
290 /* /// "pciStrcat()" */
291 void pciStrcat(STRPTR d, STRPTR s)
293 while(*d) d++;
294 while((*d++ = *s++));
296 /* \\\ */
298 /* /// "pciAllocUnit()" */
299 BOOL pciAllocUnit(struct PCIUnit *hu)
301 #if 0
302 struct PCIDevice *hd = hu->hu_Device;
303 #endif
304 struct PCIController *hc;
306 BOOL allocgood = TRUE;
307 ULONG usb11ports = 0;
308 ULONG usb20ports = 0;
309 #ifdef AROS_USB30_CODE
310 ULONG usb30ports = 0;
311 #endif
312 ULONG cnt;
314 ULONG ohcicnt = 0;
315 ULONG uhcicnt = 0;
316 ULONG ehcicnt = 0;
317 #ifdef AROS_USB30_CODE
318 ULONG xhcicnt = 0;
319 #endif
321 STRPTR prodname;
323 KPRINTF(10, ("*** pciAllocUnit(%p) ***\n", hu));
325 #if 0 // FIXME this needs to be replaced by something AROS supports
326 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
327 while(hc->hc_Node.ln_Succ)
329 PCIXObtainBoard(hc->hc_BoardObject);
330 if (PCIXSetBoardAttr(hc->hc_BoardObject, PCIXTAG_OWNER, (ULONG) hd->hd_Library.lib_Node.ln_Name))
331 hc->hc_Flags |= HCF_BOARD_ALLOCATED;
332 else
334 KPRINTF(20, ("Couldn't allocate board, already allocated by %s\n", PCIXGetBoardAttr(hc->hc_BoardObject, PCIXTAG_OWNER)));
335 allocgood = FALSE;
337 PCIXReleaseBoard(hc->hc_BoardObject);
339 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
342 if(allocgood)
344 #endif
345 // allocate necessary memory
346 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
347 while(hc->hc_Node.ln_Succ)
349 switch(hc->hc_HCIType)
351 case HCITYPE_UHCI:
353 allocgood = uhciInit(hc,hu);
354 if(allocgood) {
355 uhcicnt++;
357 break;
360 case HCITYPE_OHCI:
362 allocgood = ohciInit(hc,hu);
363 if(allocgood) {
364 ohcicnt++;
366 break;
369 case HCITYPE_EHCI:
371 allocgood = ehciInit(hc,hu);
372 if(allocgood) {
373 ehcicnt++;
374 if(usb20ports) {
375 KPRINTF(200, ("WARNING: More than one EHCI controller per board?!?\n"));
377 usb20ports = hc->hc_NumPorts;
379 for(cnt = 0; cnt < usb20ports; cnt++) {
380 hu->hu_PortMap20[cnt] = hc;
381 hc->hc_PortNum20[cnt] = cnt;
384 break;
386 #ifdef AROS_USB30_CODE
387 case HCITYPE_XHCI:
389 allocgood = xhciInit(hc,hu);
390 if(allocgood) {
391 xhcicnt++;
392 if(usb30ports) {
393 KPRINTF(200, ("WARNING: More than one XHCI controller per board?!?\n"));
395 usb20ports = hc->xhc_NumPorts20;
396 usb30ports = hc->xhc_NumPorts30;
398 break;
400 #endif
402 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
404 #if 0 // FIXME this needs to be replaced by something AROS supports
407 if(!allocgood)
409 // free previously allocated boards
410 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
411 while(hc->hc_Node.ln_Succ)
413 PCIXObtainBoard(hc->hc_BoardObject);
414 if (hc->hc_Flags & HCF_ALLOCATED)
416 hc->hc_Flags &= ~HCF_ALLOCATED;
417 PCIXSetBoardAttr(hc->hc_BoardObject, PCIXTAG_OWNER, 0);
419 PCIXReleaseBoard(hc->hc_BoardObject);
421 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
423 #else
424 if(!allocgood)
426 #endif
427 return FALSE;
430 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
431 while(hc->hc_Node.ln_Succ)
433 if((hc->hc_HCIType == HCITYPE_UHCI) || (hc->hc_HCIType == HCITYPE_OHCI))
435 if(hc->hc_complexrouting)
437 ULONG locport = 0;
438 for(cnt = 0; cnt < usb20ports; cnt++)
440 if(((hc->hc_portroute >> (cnt<<2)) & 0xf) == hc->hc_FunctionNum)
442 KPRINTF(10, ("CHC %ld Port %ld assigned to global Port %ld\n", hc->hc_FunctionNum, locport, cnt));
443 hu->hu_PortMap11[cnt] = hc;
444 hu->hu_PortNum11[cnt] = locport;
445 hc->hc_PortNum20[locport] = cnt;
446 locport++;
449 } else {
450 for(cnt = usb11ports; cnt < usb11ports + hc->hc_NumPorts; cnt++)
452 hu->hu_PortMap11[cnt] = hc;
453 hu->hu_PortNum11[cnt] = cnt - usb11ports;
454 hc->hc_PortNum20[cnt - usb11ports] = cnt;
457 usb11ports += hc->hc_NumPorts;
459 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
461 if((usb11ports != usb20ports) && usb20ports)
463 KPRINTF(20, ("Warning! #EHCI Ports (%ld) does not match USB 1.1 Ports (%ld)!\n", usb20ports, usb11ports));
466 hu->hu_RootHub11Ports = usb11ports;
467 hu->hu_RootHub20Ports = usb20ports;
468 #ifdef AROS_USB30_CODE
469 // FIXME: This is probably wrong as well...
470 hu->hu_RootHub30Ports = usb30ports;
471 hu->hu_RootHubPorts = (usb11ports > usb20ports) ? ((usb11ports > usb30ports) ? usb11ports : usb30ports) : ((usb30ports > usb20ports) ? usb30ports : usb20ports);
472 #else
473 hu->hu_RootHubPorts = (usb11ports > usb20ports) ? usb11ports : usb20ports;
474 #endif
475 for(cnt = 0; cnt < hu->hu_RootHubPorts; cnt++)
477 hu->hu_EhciOwned[cnt] = hu->hu_PortMap20[cnt] ? TRUE : FALSE;
480 #ifdef AROS_USB30_CODE
481 KPRINTF(1000, ("Unit %ld: USB Board %08lx has %ld USB1.1, %ld USB2.0 and %ld USB3.0 ports!\n", hu->hu_UnitNo, hu->hu_DevID, hu->hu_RootHub11Ports, hu->hu_RootHub20Ports, hu->hu_RootHub30Ports));
482 #else
483 KPRINTF(10, ("Unit %ld: USB Board %08lx has %ld USB1.1 and %ld USB2.0 ports!\n", hu->hu_UnitNo, hu->hu_DevID, hu->hu_RootHub11Ports, hu->hu_RootHub20Ports));
484 #endif
486 hu->hu_FrameCounter = 1;
487 hu->hu_RootHubAddr = 0;
489 // put em online
490 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
491 while(hc->hc_Node.ln_Succ)
493 hc->hc_Flags |= HCF_ONLINE;
494 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
497 // create product name of device
498 prodname = hu->hu_ProductName;
499 *prodname = 0;
500 pciStrcat(prodname, "PCI ");
501 if(ohcicnt + uhcicnt)
503 if(ohcicnt + uhcicnt >1)
505 prodname[4] = ohcicnt + uhcicnt + '0';
506 prodname[5] = 'x';
507 prodname[6] = 0;
509 pciStrcat(prodname, ohcicnt ? "OHCI" : "UHCI");
510 if(ehcicnt)
512 pciStrcat(prodname, " +");
513 } else{
514 pciStrcat(prodname, " USB 1.1");
517 if(ehcicnt)
519 pciStrcat(prodname, " EHCI USB 2.0");
521 #ifdef AROS_USB30_CODE
522 if(xhcicnt)
524 if(xhcicnt >1)
526 prodname[4] = xhcicnt + '0';
527 prodname[5] = 'x';
528 prodname[6] = 0;
530 pciStrcat(prodname, " XHCI USB 3.0");
532 #endif
533 #if 0 // user can use pcitool to check what the chipset is and not guess it from this
534 pciStrcat(prodname, " Host Controller (");
535 if(ohcicnt + uhcicnt)
537 pciStrcat(prodname, ohcicnt ? "NEC)" : "VIA, Intel, ALI, etc.)");
538 } else {
539 pciStrcat(prodname, "Emulated?)");
541 #else
542 pciStrcat(prodname, " Host Controller");
543 #endif
544 KPRINTF(10, ("Unit allocated!\n"));
546 return TRUE;
548 /* \\\ */
550 /* /// "pciFreeUnit()" */
551 void pciFreeUnit(struct PCIUnit *hu)
553 struct PCIDevice *hd = hu->hu_Device;
554 struct PCIController *hc;
556 struct TagItem pciDeactivate[] =
558 { aHidd_PCIDevice_isIO, FALSE },
559 { aHidd_PCIDevice_isMEM, FALSE },
560 { aHidd_PCIDevice_isMaster, FALSE },
561 { TAG_DONE, 0UL },
564 KPRINTF(10, ("*** pciFreeUnit(%p) ***\n", hu));
566 // put em offline
567 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
568 while(hc->hc_Node.ln_Succ)
570 hc->hc_Flags &= ~HCF_ONLINE;
571 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
574 #ifdef AROS_USB30_CODE
575 xhciFree(hc, hu);
576 #endif
577 // doing this in three steps to avoid these damn host errors
578 ehciFree(hc, hu);
579 ohciFree(hc, hu);
580 uhciFree(hc, hu);
582 //FIXME: (x/e/o/u)hciFree routines actually ONLY stops the chip NOT free anything as below...
583 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
584 while(hc->hc_Node.ln_Succ) {
585 if(hc->hc_PCIMem) {
586 HIDD_PCIDriver_FreePCIMem(hc->hc_PCIDriverObject, hc->hc_PCIMem);
587 hc->hc_PCIMem = NULL;
589 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
592 // disable and free board
593 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
594 while(hc->hc_Node.ln_Succ)
596 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciDeactivate); // deactivate busmaster and IO/Mem
597 if(hc->hc_PCIIntHandler.h_Node.ln_Name)
599 HIDD_IRQ_RemHandler(hd->hd_IRQHidd, &hc->hc_PCIIntHandler);
600 hc->hc_PCIIntHandler.h_Node.ln_Name = NULL;
602 #if 0
604 PCIXObtainBoard(hc->hc_BoardObject);
605 hc->hc_Flags &= ~HCF_ALLOCATED;
606 PCIXSetBoardAttr(hc->hc_BoardObject, PCIXTAG_OWNER, 0);
607 PCIXReleaseBoard(hc->hc_BoardObject);
608 #endif
609 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
612 /* \\\ */
614 /* /// "pciExpunge()" */
615 void pciExpunge(struct PCIDevice *hd)
617 struct PCIController *hc;
618 struct PCIUnit *hu;
620 KPRINTF(10, ("*** pciExpunge(%p) ***\n", hd));
622 hu = (struct PCIUnit *) hd->hd_Units.lh_Head;
623 while(((struct Node *) hu)->ln_Succ)
625 Remove((struct Node *) hu);
626 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
627 while(hc->hc_Node.ln_Succ)
629 Remove(&hc->hc_Node);
630 FreePooled(hd->hd_MemPool, hc, sizeof(struct PCIController));
631 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
633 FreePooled(hd->hd_MemPool, hu, sizeof(struct PCIUnit));
634 hu = (struct PCIUnit *) hd->hd_Units.lh_Head;
636 if(hd->hd_PCIHidd)
638 struct OOP_ABDescr attrbases[] =
640 { (STRPTR) IID_Hidd, &hd->hd_HiddAB },
641 { (STRPTR) IID_Hidd_PCIDevice, &hd->hd_HiddPCIDeviceAB },
642 { NULL, NULL }
645 OOP_ReleaseAttrBases(attrbases);
647 OOP_DisposeObject(hd->hd_PCIHidd);
649 if(hd->hd_IRQHidd)
651 OOP_DisposeObject(hd->hd_IRQHidd);
654 /* \\\ */
656 /* /// "pciGetPhysical()" */
657 APTR pciGetPhysical(struct PCIController *hc, APTR virtaddr)
659 //struct PCIDevice *hd = hc->hc_Device;
660 return(HIDD_PCIDriver_CPUtoPCI(hc->hc_PCIDriverObject, virtaddr));
662 /* \\\ */
665 * Process some AROS-specific arguments.
666 * 'usbpoweron' helps to bring up USB ports on IntelMac,
667 * whose firmware sets them up incorrectly.
669 static int getArguments(struct PCIDevice *base)
671 APTR BootLoaderBase;
672 #ifdef HAVE_ACPI
673 struct ACPIBase *ACPIBase;
675 ACPIBase = OpenResource("acpi.resource");
676 if (ACPIBase)
679 * Use ACPI IDs to identify known machines which need HDF_FORCEPOWER to work.
680 * Currently we know only MacMini.
682 struct ACPI_TABLE_DEF_HEADER *dsdt = ACPI_FindSDT(ACPI_MAKE_ID('D','S','D','T'));
684 if (dsdt)
686 /* Yes, the last byte in ID is zero */
687 if (strcmp(dsdt->oem_table_id, "Macmini") == 0)
689 base->hd_Flags = HDF_FORCEPOWER;
690 return TRUE;
694 #endif
696 BootLoaderBase = OpenResource("bootloader.resource");
697 if (BootLoaderBase)
699 struct List *args = GetBootInfo(BL_Args);
701 if (args)
703 struct Node *node;
705 for (node = args->lh_Head; node->ln_Succ; node = node->ln_Succ)
707 if (stricmp(node->ln_Name, "forceusbpower") == 0)
709 base->hd_Flags = HDF_FORCEPOWER;
710 break;
716 return TRUE;
719 ADD2INITLIB(getArguments, 10)