2 Copyright (C) 2006 by Michal Schulz
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <aros/symbolsets.h>
25 #include <asm/mpc5200b.h>
27 #include <hidd/hidd.h>
34 #include <proto/exec.h>
35 #include <proto/oop.h>
36 #include <proto/openfirmware.h>
37 #include <proto/kernel.h>
38 #include <aros/debug.h>
41 #include "../pci/pci.h"
44 #define SD(x) (&LIBBASE->sd)
46 static void init_builtin_ohci(struct ohci_staticdata
*sd
)
48 void *OpenFirmwareBase
= OpenResource("openfirmware.resource");
50 ohci_registers_t
*regs
;
51 struct timerequest
*tr
= ohci_CreateTimer();
53 key
= OF_OpenKey("/builtin/usb");
56 void *prop
= OF_FindProperty(key
, "reg");
59 struct pcibase
*pci_efika_base
= OpenLibrary("pci-efika.hidd",0);
61 intptr_t *base
= OF_GetPropValue(prop
);
62 regs
= (ohci_registers_t
*)*base
;
63 sd
->ramBase
[0] = *base
;
64 sd
->pciDevice
[0] = NULL
;
65 sd
->irqNum
[0] = MPC5200B_USB
;
68 sd
->pciDriver
[0] = OOP_NewObject(pci_efika_base
->psd
.driverClass
, NULL
, NULL
);
70 sd
->pciDriver
[0] = NULL
;
72 D(bug("[OHCI_MPC5200B] HC @ %08x\n", sd
->ramBase
[0]));
75 sd
->numPorts
[0] = HC_RHA_GET_NDP(AROS_OHCI2LONG(mmio(regs
->HcRhDescriptorA
)));
77 D(bug("[OHCI_MPC5200B] %d-port Device %d @ %08x with MMIO @ %08x\n", sd
->numPorts
[0], 1, sd
->pciDriver
[0], sd
->ramBase
[0]));
79 uint32_t ctrl
= AROS_OHCI2LONG(mmio(regs
->HcControl
));
80 if (ctrl
& HC_CTRL_IR
)
82 D(bug("[OHCI_MPC5200B] Performing BIOS handoff\n"));
83 int delay
= 500; /* 0.5 second */
84 mmio(regs
->HcInterruptEnable
) = AROS_LONG2OHCI(HC_INTR_OC
);
85 mmio(regs
->HcCommandStatus
) = AROS_LONG2OHCI(HC_CS_OCR
);
88 while ((delay
> 0) && AROS_OHCI2LONG(mmio(regs
->HcControl
) & HC_CTRL_IR
))
94 D(bug("[OHCI_MPC5200B] BIOS handoff failed!\n"));
96 mmio(regs
->HcControl
) = AROS_LONG2OHCI(ctrl
& HC_CTRL_RWC
);
99 /* Disable all interrupts */
100 mmio(regs
->HcInterruptDisable
) = AROS_LONG2OHCI(0xffffffff);
101 mmio(regs
->HcInterruptStatus
) = AROS_LONG2OHCI(0xffffffff);
103 ohci_DeleteTimer(tr
);
109 AROS_UFH3(void, Enumerator
,
110 AROS_UFHA(struct Hook
*, hook
, A0
),
111 AROS_UFHA(OOP_Object
*, pciDevice
, A2
),
112 AROS_UFHA(APTR
, message
, A1
))
116 ohci_registers_t
*regs
;
118 struct timerequest
*tr
= ohci_CreateTimer();
120 if (counter
== MAX_OHCI_DEVICES
)
123 LIBBASETYPE
*LIBBASE
= (LIBBASETYPE
*)hook
->h_Data
;
125 struct TagItem attrs
[] = {
126 { aHidd_PCIDevice_isMEM
, TRUE
},
127 { aHidd_PCIDevice_isMaster
, TRUE
},
132 OOP_SetAttrs(pciDevice
, (struct TagItem
*)attrs
);
133 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, &LIBBASE
->sd
.ramBase
[counter
]);
134 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (void *)&LIBBASE
->sd
.pciDriver
[counter
]);
135 LIBBASE
->sd
.pciDevice
[counter
] = pciDevice
;
137 regs
= (ohci_registers_t
*)LIBBASE
->sd
.ramBase
[counter
];
139 LIBBASE
->sd
.numPorts
[counter
] = HC_RHA_GET_NDP(AROS_OHCI2LONG(mmio(regs
->HcRhDescriptorA
)));
141 D(bug("[OHCI_MPC5200B] %d-port Device %d @ %08x with MMIO @ %08x\n", LIBBASE
->sd
.numPorts
[counter
], counter
+ 1, pciDevice
, LIBBASE
->sd
.ramBase
[counter
]));
143 uint32_t ctrl
= AROS_OHCI2LONG(mmio(regs
->HcControl
));
144 if (ctrl
& HC_CTRL_IR
)
146 D(bug("[OHCI_MPC5200B] Performing BIOS handoff\n"));
147 int delay
= 500; /* 0.5 second */
148 mmio(regs
->HcInterruptEnable
) = AROS_LONG2OHCI(HC_INTR_OC
);
149 mmio(regs
->HcCommandStatus
) = AROS_LONG2OHCI(HC_CS_OCR
);
152 while ((delay
> 0) && AROS_OHCI2LONG(mmio(regs
->HcControl
) & HC_CTRL_IR
))
158 D(bug("[OHCI_MPC5200B] BIOS handoff failed!\n"));
160 mmio(regs
->HcControl
) = AROS_LONG2OHCI(ctrl
& HC_CTRL_RWC
);
163 /* Disable all interrupts */
164 mmio(regs
->HcInterruptDisable
) = AROS_LONG2OHCI(0xffffffff);
165 mmio(regs
->HcInterruptStatus
) = AROS_LONG2OHCI(0xffffffff);
167 LIBBASE
->sd
.numDevices
= ++counter
;
169 ohci_DeleteTimer(tr
);
175 static int OHCI_Init(LIBBASETYPEPTR LIBBASE
)
177 struct OOP_ABDescr attrbases
[] = {
178 { (STRPTR
)IID_Hidd
, &HiddAttrBase
},
179 { (STRPTR
)IID_Hidd_PCIDevice
, &HiddPCIDeviceAttrBase
},
180 { (STRPTR
)IID_Hidd_USBDevice
, &HiddUSBDeviceAttrBase
},
181 { (STRPTR
)IID_Hidd_USBHub
, &HiddUSBHubAttrBase
},
182 { (STRPTR
)IID_Hidd_USBDrv
, &HiddUSBDrvAttrBase
},
186 D(bug("[OHCI_MPC5200B] OHCI_Init()\n"));
188 LIBBASE
->sd
.usb
= OOP_NewObject(NULL
, (STRPTR
)CLID_Hidd_USB
, NULL
);
190 NEWLIST(&LIBBASE
->sd
.tdList
);
191 InitSemaphore(&LIBBASE
->sd
.tdLock
);
193 if (!LIBBASE
->sd
.usb
)
195 bug("[OHCI_MPC5200B] Cannot create the instance of base USB class\n");
199 OOP_ObtainAttrBases(attrbases
);
201 init_builtin_ohci(&LIBBASE
->sd
);
203 D(bug("[OHCI_MPC5200B] Done. OHCI devices found: %d\n", LIBBASE
->sd
.numDevices
));
205 if (LIBBASE
->sd
.numDevices
> 0)
207 LIBBASE
->sd
.memPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
, 8192, 4096);
209 if (LIBBASE
->sd
.memPool
)
217 static int OHCI_Expunge(LIBBASETYPEPTR LIBBASE
)
219 struct OOP_ABDescr attrbases
[] = {
220 { (STRPTR
)IID_Hidd
, &HiddAttrBase
},
221 { (STRPTR
)IID_Hidd_PCIDevice
, &HiddPCIDeviceAttrBase
},
222 { (STRPTR
)IID_Hidd_USBDevice
, &HiddUSBDeviceAttrBase
},
223 { (STRPTR
)IID_Hidd_USBHub
, &HiddUSBHubAttrBase
},
224 { (STRPTR
)IID_Hidd_USBDrv
, &HiddUSBDrvAttrBase
},
228 OOP_ReleaseAttrBases(attrbases
);
233 ADD2INITLIB(OHCI_Init
, 0)
234 ADD2EXPUNGELIB(OHCI_Expunge
, 0)
235 ADD2LIBS((STRPTR
)"usb.hidd", 0, static struct Library
*, __usbbase
)