Check for SYS/GL during library init. Reason is that
[AROS.git] / rom / usb / pciusbhc / uhci / pci_aros.c
blobc831f7638d6d1bbd5485ef476691f8cb6885a9a3
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 <proto/bootloader.h>
12 #include <proto/oop.h>
13 #include <proto/utility.h>
14 #include <proto/exec.h>
16 #include <inttypes.h>
17 #include <string.h>
19 #include "uhwcmd.h"
21 #undef HiddPCIDeviceAttrBase
22 #undef HiddAttrBase
24 #define HiddPCIDeviceAttrBase (hd->hd_HiddPCIDeviceAB)
25 #define HiddAttrBase (hd->hd_HiddAB)
27 #define PCI_BASE_CLASS_SERIAL 0x0c
28 #define PCI_SUB_CLASS_USB 0x03
29 #define PCI_INTERFACE_UHCI 0x00
31 AROS_UFH3(void, pciEnumerator,
32 AROS_UFHA(struct Hook *, hook, A0),
33 AROS_UFHA(OOP_Object *, pciDevice, A2),
34 AROS_UFHA(APTR, message, A1))
36 AROS_USERFUNC_INIT
38 struct PCIDevice *hd = (struct PCIDevice *) hook->h_Data;
39 struct PCIController *hc;
40 IPTR hcitype;
41 IPTR bus;
42 IPTR dev;
43 IPTR sub;
44 IPTR intline;
45 ULONG devid;
47 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Interface, &hcitype);
48 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Bus, &bus);
49 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Dev, &dev);
50 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Sub, &sub);
51 OOP_GetAttr(pciDevice, aHidd_PCIDevice_INTLine, &intline);
53 devid = (bus<<16)|dev;
55 KPRINTF(10, ("Found PCI device 0x%lx of type %ld, Intline=%ld\n", devid, hcitype, intline));
57 if(intline == 255) {
58 // we can't work without the correct interrupt line
59 // BIOS needs plug & play os option disabled. Alternatively AROS must support APIC reconfiguration
60 KPRINTF(200, ("ERROR: PCI card has no interrupt line assigned by BIOS, disable Plug & Play OS!\n"));
61 }else{
62 KPRINTF(10, ("Setting up device...\n"));
64 hc = AllocPooled(hd->hd_MemPool, sizeof(struct PCIController));
65 if (hc) {
66 hc->hc_Device = hd;
67 hc->hc_DevID = devid;
68 hc->hc_FunctionNum = sub;
69 hc->hc_HCIType = hcitype;
70 hc->hc_PCIDeviceObject = pciDevice;
71 hc->hc_PCIIntLine = intline;
73 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Driver, (IPTR *) &hc->hc_PCIDriverObject);
75 NEWLIST(&hc->hc_CtrlXFerQueue);
76 NEWLIST(&hc->hc_IntXFerQueue);
77 NEWLIST(&hc->hc_IsoXFerQueue);
78 NEWLIST(&hc->hc_BulkXFerQueue);
80 NEWLIST(&hc->hc_TDQueue);
81 NEWLIST(&hc->hc_AbortQueue);
82 NEWLIST(&hc->hc_PeriodicTDQueue);
84 AddTail(&hd->hd_TempHCIList, &hc->hc_Node);
88 AROS_USERFUNC_EXIT
91 BOOL pciInit(struct PCIDevice *hd) {
92 struct PCIController *hc;
93 struct PCIController *nexthc;
94 struct PCIUnit *hu;
95 ULONG unitno = 0;
97 KPRINTF(10, ("*** pciInit(%p) ***\n", hd));
99 NEWLIST(&hd->hd_TempHCIList);
101 if((hd->hd_PCIHidd = OOP_NewObject(NULL, (STRPTR) CLID_Hidd_PCI, NULL))) {
102 struct TagItem tags[] = {
103 { tHidd_PCI_Class, PCI_BASE_CLASS_SERIAL },
104 { tHidd_PCI_SubClass, PCI_SUB_CLASS_USB },
105 { tHidd_PCI_Interface, PCI_INTERFACE_UHCI },
106 { TAG_DONE, 0UL }
109 struct OOP_ABDescr attrbases[] = {
110 { (STRPTR) IID_Hidd, &hd->hd_HiddAB },
111 { (STRPTR) IID_Hidd_PCIDevice, &hd->hd_HiddPCIDeviceAB },
112 { NULL, NULL }
115 struct Hook findHook = {
116 h_Entry: (IPTR (*)()) pciEnumerator,
117 h_Data: hd,
120 OOP_ObtainAttrBases(attrbases);
122 KPRINTF(20, ("Searching for devices...\n"));
124 HIDD_PCI_EnumDevices(hd->hd_PCIHidd, &findHook, (struct TagItem *) &tags);
125 } else {
126 KPRINTF(20, ("Unable to create PCIHidd object!\n"));
127 return FALSE;
130 // Create units with a list of host controllers having the same bus and device number.
131 while(hd->hd_TempHCIList.lh_Head->ln_Succ) {
132 hu = AllocPooled(hd->hd_MemPool, sizeof(struct PCIUnit));
133 if(!hu) {
134 // actually, we should get rid of the allocated memory first, but I don't care as DeletePool() will take care of this eventually
135 return FALSE;
137 hu->hu_Device = hd;
138 hu->hu_UnitNo = unitno;
139 hu->hu_DevID = ((struct PCIController *) hd->hd_TempHCIList.lh_Head)->hc_DevID;
141 NEWLIST(&hu->hu_Controllers);
142 NEWLIST(&hu->hu_RHIOQueue);
144 hc = (struct PCIController *) hd->hd_TempHCIList.lh_Head;
145 while((nexthc = (struct PCIController *) hc->hc_Node.ln_Succ)) {
146 if(hc->hc_DevID == hu->hu_DevID) {
147 Remove(&hc->hc_Node);
148 hc->hc_Unit = hu;
149 AddTail(&hu->hu_Controllers, &hc->hc_Node);
151 hc = nexthc;
153 AddTail(&hd->hd_Units, (struct Node *) hu);
154 unitno++;
156 return TRUE;
159 BOOL pciAllocUnit(struct PCIUnit *hu) {
161 struct PCIController *hc;
163 BOOL allocgood = TRUE;
164 ULONG usb11ports = 0;
166 ULONG cnt;
168 KPRINTF(10, ("*** pciAllocUnit(%p) ***\n", hu));
170 // allocate necessary memory
171 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
172 while(hc->hc_Node.ln_Succ) {
173 allocgood = uhciInit(hc,hu);
174 if(allocgood) {
175 for(cnt = usb11ports; cnt < usb11ports + hc->hc_NumPorts; cnt++) {
176 hu->hu_PortMap11[cnt] = hc;
177 hu->hu_PortNum11[cnt] = cnt - usb11ports;
178 hc->hc_PortNumGlobal[cnt - usb11ports] = cnt;
179 KPRINTF2(200,("Mapping ports\n"));
180 KPRINTF2(200,(" Map11[%ld]= %p\n", cnt, hc));
181 KPRINTF2(200,(" Num11[%ld]= %ld\n", cnt, (cnt-usb11ports)));
182 KPRINTF2(200,(" Glo11[%ld]= %ld\n", (cnt-usb11ports), cnt));
184 usb11ports += hc->hc_NumPorts;
185 }else{
186 return FALSE;
188 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
191 hu->hu_RootHubPorts = usb11ports;
192 hu->hu_RootHubAddr = 0;
194 // put em online
195 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
196 while(hc->hc_Node.ln_Succ) {
197 hc->hc_Flags |= HCF_ONLINE;
198 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
201 KPRINTF(10, ("Unit allocated!\n"));
203 return TRUE;
206 void pciFreeUnit(struct PCIUnit *hu) {
207 struct PCIDevice *hd = hu->hu_Device;
208 struct PCIController *hc;
210 struct TagItem pciDeactivate[] = {
211 { aHidd_PCIDevice_isIO, FALSE },
212 { aHidd_PCIDevice_isMEM, FALSE },
213 { aHidd_PCIDevice_isMaster, FALSE },
214 { TAG_DONE, 0UL },
217 KPRINTF(10, ("*** pciFreeUnit(%p) ***\n", hu));
219 // put em offline
220 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
221 while(hc->hc_Node.ln_Succ)
223 hc->hc_Flags &= ~HCF_ONLINE;
224 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
227 uhciFree(hc, hu);
229 //FIXME: uhciFree routine actually ONLY stops the chip NOT free anything as code below...
230 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
231 while(hc->hc_Node.ln_Succ) {
232 if(hc->hc_PCIMem) {
233 HIDD_PCIDriver_FreePCIMem(hc->hc_PCIDriverObject, hc->hc_PCIMem);
234 hc->hc_PCIMem = NULL;
236 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
239 // disable and free board
240 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
241 while(hc->hc_Node.ln_Succ)
243 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciDeactivate); // deactivate busmaster and IO/Mem
244 if(hc->hc_PCIIntHandler.is_Node.ln_Name) {
245 RemIntServer(INTB_KERNEL + hc->hc_PCIIntLine, &hc->hc_PCIIntHandler);
246 hc->hc_PCIIntHandler.is_Node.ln_Name = NULL;
249 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
253 void pciExpunge(struct PCIDevice *hd) {
254 struct PCIController *hc;
255 struct PCIUnit *hu;
257 KPRINTF(10, ("*** pciExpunge(%p) ***\n", hd));
259 hu = (struct PCIUnit *) hd->hd_Units.lh_Head;
260 while(((struct Node *) hu)->ln_Succ) {
261 Remove((struct Node *) hu);
262 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
263 while(hc->hc_Node.ln_Succ) {
264 Remove(&hc->hc_Node);
265 FreePooled(hd->hd_MemPool, hc, sizeof(struct PCIController));
266 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
268 FreePooled(hd->hd_MemPool, hu, sizeof(struct PCIUnit));
269 hu = (struct PCIUnit *) hd->hd_Units.lh_Head;
271 if(hd->hd_PCIHidd) {
272 struct OOP_ABDescr attrbases[] =
274 { (STRPTR) IID_Hidd, &hd->hd_HiddAB },
275 { (STRPTR) IID_Hidd_PCIDevice, &hd->hd_HiddPCIDeviceAB },
276 { NULL, NULL }
279 OOP_ReleaseAttrBases(attrbases);
281 OOP_DisposeObject(hd->hd_PCIHidd);
285 APTR pciGetPhysical(struct PCIController *hc, APTR virtaddr) {
286 //struct PCIDevice *hd = hc->hc_Device;
287 return(HIDD_PCIDriver_CPUtoPCI(hc->hc_PCIDriverObject, virtaddr));
291 * Process some AROS-specific arguments.
292 * 'usbpoweron' helps to bring up USB ports on IntelMac,
293 * whose firmware sets them up incorrectly.
295 static int getArguments(struct PCIDevice *base) {
296 APTR BootLoaderBase = OpenResource("bootloader.resource");
298 if (BootLoaderBase)
300 struct List *args = GetBootInfo(BL_Args);
302 if (args)
304 struct Node *node;
306 for (node = args->lh_Head; node->ln_Succ; node = node->ln_Succ)
308 if (stricmp(node->ln_Name, "forceusbpower") == 0)
310 base->hd_Flags = HDF_FORCEPOWER;
311 break;
317 return TRUE;
320 ADD2INITLIB(getArguments, 10)