1 /* pci_aros.c - pci access abstraction for AROS by Chris Hodges
4 #include <aros/bootloader.h>
5 #include <aros/symbolsets.h>
6 #include <exec/types.h>
8 #include <devices/timer.h>
12 #include <proto/bootloader.h>
13 #include <proto/oop.h>
14 #include <proto/utility.h>
15 #include <proto/exec.h>
22 #undef HiddPCIDeviceAttrBase
25 #define HiddPCIDeviceAttrBase (hd->hd_HiddPCIDeviceAB)
26 #define HiddAttrBase (hd->hd_HiddAB)
28 #define PCI_BASE_CLASS_SERIAL 0x0c
29 #define PCI_SUB_CLASS_USB 0x03
30 #define PCI_INTERFACE_UHCI 0x00
32 AROS_UFH3(void, pciEnumerator
,
33 AROS_UFHA(struct Hook
*, hook
, A0
),
34 AROS_UFHA(OOP_Object
*, pciDevice
, A2
),
35 AROS_UFHA(APTR
, message
, A1
))
39 struct PCIDevice
*hd
= (struct PCIDevice
*) hook
->h_Data
;
40 struct PCIController
*hc
;
48 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Interface
, &hcitype
);
49 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Bus
, &bus
);
50 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Dev
, &dev
);
51 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Dev
, &sub
);
52 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_INTLine
, &intline
);
54 devid
= (bus
<<16)|dev
;
56 KPRINTF(10, ("Found PCI device 0x%lx of type %ld, Intline=%ld\n", devid
, hcitype
, intline
));
59 // we can't work without the correct interrupt line
60 // BIOS needs plug & play os option disabled. Alternatively AROS must support APIC reconfiguration
61 KPRINTF(200, ("ERROR: PCI card has no interrupt line assigned by BIOS, disable Plug & Play OS!\n"));
63 KPRINTF(10, ("Setting up device...\n"));
65 hc
= AllocPooled(hd
->hd_MemPool
, sizeof(struct PCIController
));
69 hc
->hc_FunctionNum
= sub
;
70 hc
->hc_HCIType
= hcitype
;
71 hc
->hc_PCIDeviceObject
= pciDevice
;
72 hc
->hc_PCIIntLine
= intline
;
74 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (IPTR
*) &hc
->hc_PCIDriverObject
);
76 NEWLIST(&hc
->hc_CtrlXFerQueue
);
77 NEWLIST(&hc
->hc_IntXFerQueue
);
78 NEWLIST(&hc
->hc_IsoXFerQueue
);
79 NEWLIST(&hc
->hc_BulkXFerQueue
);
81 NEWLIST(&hc
->hc_TDQueue
);
82 NEWLIST(&hc
->hc_AbortQueue
);
83 NEWLIST(&hc
->hc_PeriodicTDQueue
);
85 AddTail(&hd
->hd_TempHCIList
, &hc
->hc_Node
);
92 BOOL
pciInit(struct PCIDevice
*hd
) {
93 struct PCIController
*hc
;
94 struct PCIController
*nexthc
;
98 KPRINTF(10, ("*** pciInit(%p) ***\n", hd
));
100 NEWLIST(&hd
->hd_TempHCIList
);
102 if(!(hd
->hd_IRQHidd
= OOP_NewObject(NULL
, (STRPTR
) CLID_Hidd_IRQ
, NULL
))) {
103 KPRINTF(20, ("Unable to create IRQHidd object!\n"));
107 if((hd
->hd_PCIHidd
= OOP_NewObject(NULL
, (STRPTR
) CLID_Hidd_PCI
, NULL
))) {
108 struct TagItem tags
[] = {
109 { tHidd_PCI_Class
, PCI_BASE_CLASS_SERIAL
},
110 { tHidd_PCI_SubClass
, PCI_SUB_CLASS_USB
},
111 { tHidd_PCI_Interface
, PCI_INTERFACE_UHCI
},
115 struct OOP_ABDescr attrbases
[] = {
116 { (STRPTR
) IID_Hidd
, &hd
->hd_HiddAB
},
117 { (STRPTR
) IID_Hidd_PCIDevice
, &hd
->hd_HiddPCIDeviceAB
},
121 struct Hook findHook
= {
122 h_Entry
: (IPTR (*)()) pciEnumerator
,
126 OOP_ObtainAttrBases(attrbases
);
128 KPRINTF(20, ("Searching for devices...\n"));
130 HIDD_PCI_EnumDevices(hd
->hd_PCIHidd
, &findHook
, (struct TagItem
*) &tags
);
132 KPRINTF(20, ("Unable to create PCIHidd object!\n"));
133 OOP_DisposeObject(hd
->hd_IRQHidd
);
137 // Create units with a list of host controllers having the same bus and device number.
138 while(hd
->hd_TempHCIList
.lh_Head
->ln_Succ
) {
139 hu
= AllocPooled(hd
->hd_MemPool
, sizeof(struct PCIUnit
));
141 // actually, we should get rid of the allocated memory first, but I don't care as DeletePool() will take care of this eventually
145 hu
->hu_UnitNo
= unitno
;
146 hu
->hu_DevID
= ((struct PCIController
*) hd
->hd_TempHCIList
.lh_Head
)->hc_DevID
;
148 NEWLIST(&hu
->hu_Controllers
);
149 NEWLIST(&hu
->hu_RHIOQueue
);
151 hc
= (struct PCIController
*) hd
->hd_TempHCIList
.lh_Head
;
152 while((nexthc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
)) {
153 if(hc
->hc_DevID
== hu
->hu_DevID
) {
154 Remove(&hc
->hc_Node
);
156 AddTail(&hu
->hu_Controllers
, &hc
->hc_Node
);
160 AddTail(&hd
->hd_Units
, (struct Node
*) hu
);
166 BOOL
pciAllocUnit(struct PCIUnit
*hu
) {
168 struct PCIController
*hc
;
170 BOOL allocgood
= TRUE
;
171 ULONG usb11ports
= 0;
175 KPRINTF(10, ("*** pciAllocUnit(%p) ***\n", hu
));
177 // allocate necessary memory
178 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
179 while(hc
->hc_Node
.ln_Succ
) {
180 allocgood
= uhciInit(hc
,hu
);
182 for(cnt
= usb11ports
; cnt
< usb11ports
+ hc
->hc_NumPorts
; cnt
++) {
183 hu
->hu_PortMap11
[cnt
] = hc
;
184 hu
->hu_PortNum11
[cnt
] = cnt
- usb11ports
;
185 hc
->hc_PortNumGlobal
[cnt
- usb11ports
] = cnt
;
186 KPRINTF2(200,("Mapping ports\n"));
187 KPRINTF2(200,(" Map11[%ld]= %p\n", cnt
, hc
));
188 KPRINTF2(200,(" Num11[%ld]= %ld\n", cnt
, (cnt
-usb11ports
)));
189 KPRINTF2(200,(" Glo11[%ld]= %ld\n", (cnt
-usb11ports
), cnt
));
191 usb11ports
+= hc
->hc_NumPorts
;
195 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
198 hu
->hu_RootHubPorts
= usb11ports
;
199 hu
->hu_RootHubAddr
= 0;
202 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
203 while(hc
->hc_Node
.ln_Succ
) {
204 hc
->hc_Flags
|= HCF_ONLINE
;
205 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
208 KPRINTF(10, ("Unit allocated!\n"));
213 void pciFreeUnit(struct PCIUnit
*hu
) {
214 struct PCIDevice
*hd
= hu
->hu_Device
;
215 struct PCIController
*hc
;
217 struct TagItem pciDeactivate
[] = {
218 { aHidd_PCIDevice_isIO
, FALSE
},
219 { aHidd_PCIDevice_isMEM
, FALSE
},
220 { aHidd_PCIDevice_isMaster
, FALSE
},
224 KPRINTF(10, ("*** pciFreeUnit(%p) ***\n", hu
));
227 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
228 while(hc
->hc_Node
.ln_Succ
)
230 hc
->hc_Flags
&= ~HCF_ONLINE
;
231 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
236 //FIXME: uhciFree routine actually ONLY stops the chip NOT free anything as code below...
237 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
238 while(hc
->hc_Node
.ln_Succ
) {
240 HIDD_PCIDriver_FreePCIMem(hc
->hc_PCIDriverObject
, hc
->hc_PCIMem
);
241 hc
->hc_PCIMem
= NULL
;
243 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
246 // disable and free board
247 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
248 while(hc
->hc_Node
.ln_Succ
)
250 OOP_SetAttrs(hc
->hc_PCIDeviceObject
, (struct TagItem
*) pciDeactivate
); // deactivate busmaster and IO/Mem
251 if(hc
->hc_PCIIntHandler
.h_Node
.ln_Name
) {
252 HIDD_IRQ_RemHandler(hd
->hd_IRQHidd
, &hc
->hc_PCIIntHandler
);
253 hc
->hc_PCIIntHandler
.h_Node
.ln_Name
= NULL
;
256 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
260 void pciExpunge(struct PCIDevice
*hd
) {
261 struct PCIController
*hc
;
264 KPRINTF(10, ("*** pciExpunge(%p) ***\n", hd
));
266 hu
= (struct PCIUnit
*) hd
->hd_Units
.lh_Head
;
267 while(((struct Node
*) hu
)->ln_Succ
) {
268 Remove((struct Node
*) hu
);
269 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
270 while(hc
->hc_Node
.ln_Succ
) {
271 Remove(&hc
->hc_Node
);
272 FreePooled(hd
->hd_MemPool
, hc
, sizeof(struct PCIController
));
273 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
275 FreePooled(hd
->hd_MemPool
, hu
, sizeof(struct PCIUnit
));
276 hu
= (struct PCIUnit
*) hd
->hd_Units
.lh_Head
;
279 struct OOP_ABDescr attrbases
[] =
281 { (STRPTR
) IID_Hidd
, &hd
->hd_HiddAB
},
282 { (STRPTR
) IID_Hidd_PCIDevice
, &hd
->hd_HiddPCIDeviceAB
},
286 OOP_ReleaseAttrBases(attrbases
);
288 OOP_DisposeObject(hd
->hd_PCIHidd
);
291 OOP_DisposeObject(hd
->hd_IRQHidd
);
295 APTR
pciGetPhysical(struct PCIController
*hc
, APTR virtaddr
) {
296 //struct PCIDevice *hd = hc->hc_Device;
297 return(HIDD_PCIDriver_CPUtoPCI(hc
->hc_PCIDriverObject
, virtaddr
));
301 * Process some AROS-specific arguments.
302 * 'usbpoweron' helps to bring up USB ports on IntelMac,
303 * whose firmware sets them up incorrectly.
305 static int getArguments(struct PCIDevice
*base
) {
306 APTR BootLoaderBase
= OpenResource("bootloader.resource");
310 struct List
*args
= GetBootInfo(BL_Args
);
316 for (node
= args
->lh_Head
; node
->ln_Succ
; node
= node
->ln_Succ
)
318 if (stricmp(node
->ln_Name
, "forceusbpower") == 0)
320 base
->hd_Flags
= HDF_FORCEPOWER
;
330 ADD2INITLIB(getArguments
, 10)