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.
25 #include <exec/types.h>
26 #include <exec/errors.h>
29 #include <utility/tagitem.h>
30 #include <aros/debug.h>
31 #include <aros/symbolsets.h>
33 #include <devices/timer.h>
35 #include <hidd/hidd.h>
38 #include <proto/oop.h>
39 #include <proto/utility.h>
45 BOOL
METHOD(OHCI
, Hidd_USBHub
, GetHubDescriptor
)
47 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
49 if (ohci
->hubDescr
.bDescriptorType
) {
50 CopyMem(&ohci
->hubDescr
, msg
->descriptor
, sizeof(ohci
->hubDescr
));
57 BOOL
METHOD(OHCI
, Hidd_USBHub
, OnOff
)
59 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
62 D(bug("[OHCI] USBHub::OnOff(%d)\n", msg
->on
));
65 retval
= OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
67 uint32_t ctl
= AROS_OHCI2LONG(mmio(ohci
->regs
->HcControl
));
68 ctl
&= ~HC_CTRL_HCFS_MASK
;
69 ctl
|= msg
->on
? HC_CTRL_HCFS_OPERATIONAL
: HC_CTRL_HCFS_SUSPENDED
;
70 mmio(ohci
->regs
->HcControl
) = AROS_LONG2OHCI(ctl
);
72 ohci
->running
= msg
->on
;
75 * Some OHCI Root Hub interrupts pending and the HUB has been just enabled?
76 * Go, fire up the interrupts!
78 if (msg
->on
&& ohci
->pendingRHSC
)
80 ohci
->pendingRHSC
= 0;
81 struct Interrupt
*intr
;
84 ForeachNode(&ohci
->intList
, intr
)
92 retval
= OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
97 BOOL
METHOD(OHCI
, Hidd_USBHub
, PortReset
)
99 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
102 D(bug("[OHCI] Port %d reset\n", msg
->portNummer
));
104 mmio(ohci
->regs
->HcRhPortStatus
[msg
->portNummer
-1]) = AROS_LONG2OHCI(UPS_RESET
);
106 for (i
=0; i
< 5; i
++)
108 D(bug("[OHCI] Reset: Waiting for completion\n"));
110 ohci_Delay(ohci
->tr
, USB_PORT_ROOT_RESET_DELAY
);
111 if ((mmio(ohci
->regs
->HcRhPortStatus
[msg
->portNummer
-1]) & AROS_LONG2OHCI(UPS_RESET
)) == 0)
118 mmio(ohci
->regs
->HcRhPortStatus
[msg
->portNummer
-1]) = AROS_LONG2OHCI(UPS_C_PORT_RESET
<< 16);
123 BOOL
METHOD(OHCI
, Hidd_USBHub
, GetHubStatus
)
128 BOOL
METHOD(OHCI
, Hidd_USBHub
, ClearHubFeature
)
134 BOOL
METHOD(OHCI
, Hidd_USBHub
, SetHubFeature
)
139 BOOL
METHOD(OHCI
, Hidd_USBHub
, GetPortStatus
)
141 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
144 if (msg
->port
>= 1 && msg
->port
<= ohci
->hubDescr
.bNbrPorts
)
146 uint32_t val
= AROS_OHCI2LONG(mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]));
147 msg
->status
->wPortStatus
= AROS_WORD2LE(val
);
148 msg
->status
->wPortChange
= AROS_WORD2LE(val
>> 16);
152 D(bug("[OHCI] GetPortStatus: sts=%04x chg=%04x\n", AROS_LE2WORD(msg
->status
->wPortStatus
), AROS_LE2WORD(msg
->status
->wPortChange
)));
157 BOOL
METHOD(OHCI
, Hidd_USBHub
, ClearPortFeature
)
159 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
161 D(bug("[OHCI] ClearPortFeature(). Port=%d, Feature=%08x\n", msg
->port
, msg
->feature
));
163 if (msg
->port
> ohci
->hubDescr
.bNbrPorts
)
166 switch (msg
->feature
)
168 case UHF_PORT_ENABLE
:
169 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_CURRENT_CONNECT_STATUS
);
172 case UHF_PORT_SUSPEND
:
173 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_OVERCURRENT_INDICATOR
);
177 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_LOW_SPEED
);
180 case UHF_C_PORT_CONNECTION
:
181 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_C_CONNECT_STATUS
<< 16);
184 case UHF_C_PORT_ENABLE
:
185 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_C_PORT_ENABLED
<< 16);
188 case UHF_C_PORT_SUSPEND
:
189 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_C_SUSPEND
<< 16);
192 case UHF_C_PORT_OVER_CURRENT
:
193 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_C_OVERCURRENT_INDICATOR
<< 16);
196 case UHF_C_PORT_RESET
:
197 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_C_PORT_RESET
<< 16);
201 switch (msg
->feature
)
203 case UHF_C_PORT_CONNECTION
:
204 case UHF_C_PORT_ENABLE
:
205 case UHF_C_PORT_SUSPEND
:
206 case UHF_C_PORT_OVER_CURRENT
:
207 case UHF_C_PORT_RESET
:
208 if (!CheckIO((struct IORequest
*)ohci
->timerReq
))
209 AbortIO((struct IORequest
*)ohci
->timerReq
);
210 GetMsg(&ohci
->timerPort
);
211 SetSignal(0, 1 << ohci
->timerPort
.mp_SigBit
);
213 D(bug("[OHCI] Reenabling the RHSC interrupt\n"));
214 mmio(ohci
->regs
->HcInterruptEnable
) = mmio(ohci
->regs
->HcInterruptEnable
) | AROS_LONG2OHCI(HC_INTR_RHSC
);
224 BOOL
METHOD(OHCI
, Hidd_USBHub
, SetPortFeature
)
226 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
229 D(bug("[OHCI] SetPortFeature(). Port=%d, Feature=%08x\n", msg
->port
, msg
->feature
));
231 if (msg
->port
> ohci
->hubDescr
.bNbrPorts
)
234 switch (msg
->feature
)
236 case UHF_PORT_ENABLE
:
237 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_PORT_ENABLED
);
240 case UHF_PORT_SUSPEND
:
241 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_SUSPEND
);
245 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_PORT_POWER
);
249 mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) = AROS_LONG2OHCI(UPS_RESET
);
250 for (i
=0; i
< 5; i
++)
252 ohci_Delay(ohci
->tr
, USB_PORT_ROOT_RESET_DELAY
);
253 if ((mmio(ohci
->regs
->HcRhPortStatus
[msg
->port
-1]) & AROS_LONG2OHCI(UPS_RESET
)) == 0)
265 AROS_INTH1(OHCI_HubInterrupt
, ohci_data_t
*,ohci
)
269 /* Remove self from the msg queue */
270 GetMsg(&ohci
->timerPort
);
272 if (ohci
->timerReq
->tr_node
.io_Error
== IOERR_ABORTED
)
274 D(bug("[OHCI] INTR: Abrted\n"));
278 D(bug("[OHCI] INTR: Reenabling the RHSC interrupt\n"));
280 /* Reenable the RHSC interrupt */
281 mmio(ohci
->regs
->HcInterruptStatus
) = AROS_LONG2OHCI(HC_INTR_RHSC
);
282 mmio(ohci
->regs
->HcInterruptEnable
) = AROS_LONG2OHCI(HC_INTR_RHSC
);