2 Copyright © 2014, The AROS Development Team. All rights reserved.
5 Desc: PCI XHCI USB host controller
15 #include <aros/debug.h>
16 #include <aros/macros.h>
17 #include <aros/asmcall.h>
18 #include <aros/symbolsets.h>
20 #include <proto/oop.h>
21 #include <proto/exec.h>
22 #include <proto/stdc.h>
23 #include <proto/arossupport.h>
25 #include <devices/usb.h>
26 #include <devices/usb_hub.h>
27 #include <devices/newstyle.h>
28 #include <devices/usbhardware.h>
29 #include <devices/timer.h>
35 #include <hidd/hidd.h>
37 #include "pcixhci_intern.h"
39 #include LC_LIBDEFS_FILE
41 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR LIBBASE
) {
42 mybug(0,("[PCIXHCI] Init: Entering function\n"));
44 struct OOP_ABDescr attrbases
[] = {
45 { (STRPTR
)IID_Hidd
, &LIBBASE
->HiddAB
},
46 { (STRPTR
)IID_Hidd_PCIDevice
, &LIBBASE
->HiddPCIDeviceAB
},
50 if ((LIBBASE
->pci
= OOP_NewObject(NULL
, (STRPTR
)CLID_Hidd_PCI
, NULL
))) {
51 if(OOP_ObtainAttrBases(attrbases
)) {
52 return(PCIXHCI_Discover(LIBBASE
));
56 /* Someone here failed... */
57 OOP_ReleaseAttrBases(attrbases
);
58 OOP_DisposeObject(LIBBASE
->pci
);
60 mybug(-1,("[PCIXHCI] Init: Failing...\n"));
64 static int GM_UNIQUENAME(Open
)(LIBBASETYPEPTR LIBBASE
, struct IOUsbHWReq
*ioreq
, ULONG unitnum
, ULONG flags
) {
65 mybug(0, ("[PCIXHCI] Open: Entering function\n"));
66 mybug(0, ("[PCIXHCI] Open: Unit %d\n", unitnum
));
68 struct PCIXHCIUnit
*unit
;
70 ioreq
->iouh_Req
.io_Unit
= NULL
;
71 ioreq
->iouh_Req
.io_Error
= IOERR_OPENFAIL
;
73 ForeachNode(&LIBBASE
->unit_list
, unit
) {
74 if(unit
->number
== unitnum
) {
75 mybug(0, (" Found unit from node list %s %p\n\n", unit
->name
, unit
));
77 if(ioreq
->iouh_Req
.io_Message
.mn_Length
< sizeof(struct IOUsbHWReq
)) {
78 mybug(-1, ("[PCIXHCI] Open: Invalid MN_LENGTH!\n"));
79 ioreq
->iouh_Req
.io_Error
= IOERR_BADLENGTH
;
83 ioreq
->iouh_Req
.io_Unit
= (struct Unit
*) unit
;
84 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
85 ioreq
->iouh_Req
.io_Error
= 0;
94 static int GM_UNIQUENAME(Close
)(LIBBASETYPEPTR LIBBASE
, struct IOUsbHWReq
*ioreq
) {
95 mybug(0, ("[PCIXHCI] Close: Entering function\n"));
97 ioreq
->iouh_Req
.io_Unit
= (APTR
) -1;
98 ioreq
->iouh_Req
.io_Device
= (APTR
) -1;
103 static int GM_UNIQUENAME(Expunge
)(LIBBASETYPEPTR LIBBASE
) {
105 struct PCIXHCIUnit
*unit
= NULL
;
106 struct PCIXHCIPort
*port
= NULL
;
108 ForeachNode(&LIBBASE
->unit_list
, unit
) {
109 ForeachNode(&unit
->roothub
.port_list
, port
) {
110 mybug_unit(-1, ("Deleting port %d named %s\n", port
->number
, port
->name
));
114 PCIXHCI_DeleteTimer(unit
);
115 HIDD_PCIDevice_Release(unit
->hc
.pcidevice
);
120 struct OOP_ABDescr attrbases
[] = {
121 { (STRPTR
)IID_Hidd
, &LIBBASE
->HiddAB
},
122 { (STRPTR
)IID_Hidd_PCIDevice
, &LIBBASE
->HiddPCIDeviceAB
},
126 OOP_ReleaseAttrBases(attrbases
);
127 OOP_DisposeObject(LIBBASE
->pci
);
132 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
133 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
134 ADD2CLOSEDEV(GM_UNIQUENAME(Close
), 0)
135 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge
), 0)
137 AROS_LH1(void, BeginIO
, AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
), LIBBASETYPEPTR
, LIBBASE
, 5, PCIXHCI
) {
142 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
143 ioreq
->iouh_Req
.io_Error
= UHIOERR_NO_ERROR
;
145 struct PCIXHCIUnit
*unit
= (struct PCIXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
149 switch (ioreq
->iouh_Req
.io_Command
) {
151 mybug_unit(0, ("CMD_RESET\n"));
152 //ret = cmdReset(ioreq);
155 mybug_unit(0, ("CMD_FLUSH\n"));
157 case UHCMD_QUERYDEVICE
:
158 mybug_unit(0, ("UHCMD_QUERYDEVICE\n"));
159 ret
= cmdQueryDevice(ioreq
);
162 mybug_unit(0, ("UHCMD_USBRESET\n"));
163 ret
= cmdUsbReset(ioreq
);
165 case UHCMD_USBRESUME
:
166 mybug_unit(0, ("UHCMD_USBRESUME\n"));
168 case UHCMD_USBSUSPEND
:
169 mybug_unit(0, ("UHCMD_USBSUSPEND\n"));
172 mybug_unit(0, ("UHCMD_USBOPER\n"));
173 //ret = cmdUsbOper(ioreq);
175 case UHCMD_CONTROLXFER
:
176 mybug_unit(0, ("UHCMD_CONTROLXFER unit %p %s\n", unit
, unit
->name
));
177 ret
= cmdControlXFer(ioreq
);
180 mybug_unit(0, ("UHCMD_BULKXFER\n"));
183 mybug_unit(0, ("UHCMD_INTXFER unit %p %s\n", unit
, unit
->name
));
184 ret
= cmdIntXFer(ioreq
);
187 mybug_unit(0, ("UHCMD_ISOXFER\n"));
190 /* Poseidon doesn't actually check this, ever... */
191 case NSCMD_DEVICEQUERY
:
192 mybug_unit(0, ("NSCMD_DEVICEQUERY\n"));
194 static const UWORD NSDSupported
[] = {
195 CMD_FLUSH
, CMD_RESET
,
209 struct NSDeviceQueryResult
*nsdq
= (struct NSDeviceQueryResult
*)((struct IOStdReq
*)(ioreq
))->io_Data
;
210 nsdq
->DevQueryFormat
= 0;
211 nsdq
->SizeAvailable
= sizeof(struct NSDeviceQueryResult
);
212 nsdq
->DeviceType
= NSDEVTYPE_USBHARDWARE
;
213 nsdq
->DeviceSubType
= 0;
214 nsdq
->SupportedCommands
= (UWORD
*)NSDSupported
;
218 mybug_unit(-1, ("IOERR_NOCMD\n"));
223 /* We have aborted the request as unit is invalid */
227 if(ret
!= RC_DONTREPLY
) {
228 /* Set error codes */
230 ioreq
->iouh_Req
.io_Error
= ret
& 0xff;
232 /* Terminate the iorequest */
233 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
234 /* If not quick I/O, reply the message */
235 if(!(ioreq
->iouh_Req
.io_Flags
& IOF_QUICK
)) {
236 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
243 AROS_LH1(LONG
, AbortIO
, AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
), LIBBASETYPEPTR
, LIBBASE
, 6, PCIXHCI
) {
246 if(ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
) {
247 if(cmdAbortIO(ioreq
)) {