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 void PCIXHCI_Delay(struct PCIXHCIUnit
*unit
, ULONG msec
) {
42 /* Allocate a signal within this task context */
43 unit
->tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= SIGB_SINGLE
;
44 unit
->tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= FindTask(NULL
);
46 /* Specify the request */
47 unit
->tr
->tr_node
.io_Command
= TR_ADDREQUEST
;
48 unit
->tr
->tr_time
.tv_secs
= msec
/ 1000;
49 unit
->tr
->tr_time
.tv_micro
= 1000 * (msec
% 1000);
52 DoIO((struct IORequest
*)unit
->tr
);
54 unit
->tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= NULL
;
57 BOOL
PCIXHCI_CreateTimer(struct PCIXHCIUnit
*unit
) {
58 mybug_unit(0, ("Entering function\n"));
60 struct MsgPort
*mp
= NULL
;
64 unit
->tr
= (struct timerequest
*)CreateIORequest(mp
, sizeof(struct timerequest
));
66 FreeSignal(mp
->mp_SigBit
);
67 if (!OpenDevice((STRPTR
)"timer.device", UNIT_MICROHZ
, (struct IORequest
*)unit
->tr
, 0)) {
70 DeleteIORequest((struct IORequest
*)unit
->tr
);
71 mp
->mp_SigBit
= AllocSignal(-1);
79 void PCIXHCI_DeleteTimer(struct PCIXHCIUnit
*unit
) {
80 mybug_unit(0, ("Entering function\n"));
83 unit
->tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= AllocSignal(-1);
84 CloseDevice((struct IORequest
*)unit
->tr
);
85 DeleteMsgPort(unit
->tr
->tr_node
.io_Message
.mn_ReplyPort
);
86 DeleteIORequest((struct IORequest
*)unit
->tr
);
90 void FreeVecOnBoundary(APTR onboundary
) {
95 allocation
= onboundary
;
96 FreeVec((APTR
)*--allocation
);
100 APTR
AllocVecOnBoundary(ULONG size
, ULONG boundary
, STRPTR description
) {
105 /* Sanity check, size can never exceed boundary by definition */
106 if((size
<=boundary
) || (boundary
== 0)) {
109 /* If no boundary defined, allocate with 64 byte alignement */
110 allocation
= AllocVec(AROS_ROUNDUP2((size
+ AROS_ROUNDUP2(strlen(description
), sizeof(IPTR
)) + sizeof(IPTR
)), 64), (MEMF_ANY
|MEMF_CLEAR
));
112 onboundary
= ++allocation
;
113 onboundary
= (APTR
)AROS_ROUNDUP2((IPTR
)onboundary
, 64);
114 *--onboundary
= (IPTR
)--allocation
;
116 mybug(-1, (" - Allocated %d bytes for %s\n", size
, description
));
121 Worst case scenario is that we allocate 64kb more, I can live with that... I think...
122 - transfer ring, command ring and event ring all have 64kb boundary requirement
126 We might get the allocation spot on to boundary in the first place, but we need to store the address of our allocation
127 for possible FreeVecOnBoundary() call. We need twice the allocation size plus size for one IPTR. Or do we?
129 TODO: Add a string description for the allocation, "needed" for DEBUG purposes.
131 onboundary becomes the original allocation advanced by the size of one IPTR. We do not yeat know where our allocation is.
132 The allocation might have been spot on to boundary, but it is not anymore.
134 We then roundup the onboundary address to the boundary. We now have atleast one IPTR below onboundary.
135 We store the original allocation address to that address and return onboundary as the allocation.
138 allocation
= AllocVec(AROS_ROUNDUP2((size
+ AROS_ROUNDUP2(strlen(description
), sizeof(IPTR
)) + sizeof(IPTR
)), boundary
), (MEMF_ANY
|MEMF_CLEAR
));
140 onboundary
= ++allocation
;
141 onboundary
= (APTR
)AROS_ROUNDUP2((IPTR
)onboundary
, boundary
);
142 *--onboundary
= (IPTR
)--allocation
;
144 mybug(-1, (" - Allocated %d bytes for %s\n", size
, description
));
152 mybug(-1, ("Allocation for %s failed!\n", description
));