5 Copyright (C) 2006 by Michal Schulz
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Library General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU Library General Public
19 License along with this program; if not, write to the
20 Free Software Foundation, Inc.,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include <exec/types.h>
27 #include <exec/libraries.h>
28 #include <exec/execbase.h>
29 #include <exec/nodes.h>
30 #include <exec/lists.h>
31 #include <exec/ports.h>
32 #include <exec/semaphores.h>
35 #include <aros/libcall.h>
36 #include <aros/asmcall.h>
41 #include <usb/usb_core.h>
43 #include <devices/timer.h>
45 #include <aros/arossupportbase.h>
46 #include <exec/execbase.h>
48 #include LC_LIBDEFS_FILE
50 #define CLID_Drv_USB_UHCI "Bus::Drv::UHCI"
51 #define IID_Drv_USB_UHCI "Bus::Drv::UHCI"
53 #undef HiddPCIDeviceAttrBase
54 #undef HiddUSBDeviceAttrBase
55 #undef HiddUSBHubAttrBase
56 #undef HiddUSBDrvAttrBase
59 #define HiddPCIDeviceAttrBase (SD(cl)->HiddPCIDeviceAB)
60 #define HiddUSBDeviceAttrBase (SD(cl)->HiddUSBDeviceAB)
61 #define HiddUSBHubAttrBase (SD(cl)->HiddUSBHubAB)
62 #define HiddUSBDrvAttrBase (SD(cl)->HiddUSBDrvAB)
63 #define HiddAttrBase (SD(cl)->HiddAB)
81 struct uhci_staticdata
83 struct SignalSemaphore global_lock
;
87 IPTR iobase
[MAX_DEVS
];
90 OOP_Object
*uhciDevice
[MAX_DEVS
];
91 OOP_Object
*uhciPCIDriver
[MAX_DEVS
];
100 OOP_AttrBase HiddPCIDeviceAB
;
101 OOP_AttrBase HiddUSBDeviceAB
;
102 OOP_AttrBase HiddUSBHubAB
;
103 OOP_AttrBase HiddUSBDrvAB
;
108 struct MinNode td_Node
;
109 uint32_t td_Bitmap
[8];
115 struct Library LibNode
;
116 struct uhci_staticdata sd
;
119 #define UHCI_BITMAP_SIZE 128
121 typedef struct UHCI_Interrupt
{
122 struct MinNode i_node
;
123 struct Interrupt
*i_intr
;
124 UHCI_TransferDesc
*i_td
;
127 typedef struct UHCI_Pipe
{
128 struct MinNode p_Node
;
129 struct MinList p_Intr
;
130 volatile UHCI_QueueHeader
*p_Queue
;
131 enum USB_PipeType p_Type
;
136 uint8_t p_NextToggle
;
137 uint16_t p_MaxTransfer
;
141 uint8_t p_QHLocation
;
143 uint32_t p_ErrorCode
;
145 struct timerequest
*p_Timeout
;
146 uint32_t p_TimeoutVal
;
147 struct Task
*p_SigTask
;
150 volatile UHCI_TransferDesc
*p_FirstTD
;
151 volatile UHCI_TransferDesc
*p_LastTD
;
155 struct uhci_staticdata
*sd
;
158 struct Interrupt
*tmp
;
163 struct MsgPort mport
;
164 struct timerequest
*timereq
;
165 struct Interrupt timerint
;
172 OOP_Object
*pciDriver
;
175 struct Interrupt irqHandler
;
177 struct timerequest
*tr
;
179 struct MinList Isochronous
;
180 struct MinList Interrupts
;
181 struct MinList ControlLS
;
182 struct MinList ControlFS
;
185 UHCI_TransferDesc
*dummy_td
;
187 /* Interrupt queue headers */
188 UHCI_QueueHeader
*qh01
;
189 UHCI_QueueHeader
*qh02
[2];
190 UHCI_QueueHeader
*qh04
[4];
191 UHCI_QueueHeader
*qh08
[8];
192 UHCI_QueueHeader
*qh16
[16];
193 UHCI_QueueHeader
*qh32
[32];
198 aoHidd_UHCI_PCIDriver
,
199 aoHidd_UHCI_PCIDevice
,
205 #define aHidd_UHCI_IOBase (HiddUHCIAttrBase + aoHidd_UHCI_IOBase)
206 #define aHidd_UHCI_PCIDriver (HiddUHCIAttrBase + aoHidd_UHCI_PCIDriver)
207 #define aHidd_UHCI_PCIDevice (HiddUHCIAttrBase + aoHidd_UHCI_PCIDevice)
208 #define IS_UHCI_ATTR(attr, idx) (((idx)=(attr)-HiddUHCIAttrBase) < num_Hidd_UHCI_Attrs)
210 #define BASE(lib)((struct uhcibase*)(lib))
211 #define SD(cl) (&BASE(cl->UserData)->sd)
213 #define METHOD(base, id, name) \
214 base ## __ ## id ## __ ## name (OOP_Class *cl, OOP_Object *o, struct p ## id ## _ ## name *msg)
216 /*** PCI config registers ***/
218 #define PCI_USBREV 0x60 /* USB protocol revision */
219 #define PCI_USBREV_MASK 0xff
220 #define PCI_USBREV_PRE_1_0 0x00
221 #define PCI_USBREV_1_0 0x10
222 #define PCI_USBREV_1_1 0x11
224 #define PCI_LEGSUP 0xc0 /* Legacy Support register */
225 #define PCI_LEGSUP_USBPIRQDEN 0x2000 /* USB PIRQ D Enable */
227 #define PCI_CBIO 0x20 /* configuration base IO */
229 #define PCI_BASE_CLASS_SERIAL 0x0c
230 #define PCI_SUB_CLASS_USB 0x03
231 #define PCI_INTERFACE_UHCI 0x00
233 /*** UHCI registers ***/
235 #define UHCI_CMD 0x00
236 #define UHCI_CMD_RS 0x0001
237 #define UHCI_CMD_HCRESET 0x0002
238 #define UHCI_CMD_GRESET 0x0004
239 #define UHCI_CMD_EGSM 0x0008
240 #define UHCI_CMD_FGR 0x0010
241 #define UHCI_CMD_SWDBG 0x0020
242 #define UHCI_CMD_CF 0x0040
243 #define UHCI_CMD_MAXP 0x0080
245 #define UHCI_RESET_TIMEOUT 100
247 #define UHCI_STS 0x02
248 #define UHCI_STS_USBINT 0x0001
249 #define UHCI_STS_USBEI 0x0002
250 #define UHCI_STS_RD 0x0004
251 #define UHCI_STS_HSE 0x0008
252 #define UHCI_STS_HCPE 0x0010
253 #define UHCI_STS_HCH 0x0020
254 #define UHCI_STS_ALLINTRS 0x003f
256 #define UHCI_INTR 0x04
257 #define UHCI_INTR_TOCRCIE 0x0001
258 #define UHCI_INTR_RIE 0x0002
259 #define UHCI_INTR_IOCE 0x0004
260 #define UHCI_INTR_SPIE 0x0008
262 #define UHCI_FRNUM 0x06
263 #define UHCI_FRNUM_MASK 0x03ff
265 #define UHCI_FLBASEADDR 0x08
267 #define UHCI_SOF 0x0c
268 #define UHCI_SOF_MASK 0x7f
270 #define UHCI_PORTSC1 0x010
271 #define UHCI_PORTSC2 0x012
272 #define UHCI_PORTSC_CCS 0x0001
273 #define UHCI_PORTSC_CSC 0x0002
274 #define UHCI_PORTSC_PE 0x0004
275 #define UHCI_PORTSC_POEDC 0x0008
276 #define UHCI_PORTSC_LS 0x0030
277 #define UHCI_PORTSC_LS_SHIFT 4
278 #define UHCI_PORTSC_RD 0x0040
279 #define UHCI_PORTSC_LSDA 0x0100
280 #define UHCI_PORTSC_PR 0x0200
281 #define UHCI_PORTSC_OCI 0x0400
282 #define UHCI_PORTSC_OCIC 0x0800
283 #define UHCI_PORTSC_SUSP 0x1000
286 ((x) & (UHCI_PORTSC_SUSP | UHCI_PORTSC_PR | UHCI_PORTSC_RD | UHCI_PORTSC_PE))
288 #define UHCI_FRAMELIST_COUNT 1024
289 #define UHCI_FRAMELIST_ALIGN 4096
291 #define UHCI_TD_ALIGN 16
292 #define UHCI_QH_ALIGN 16
294 #define UHCI_PTR_T 0x00000001
295 #define UHCI_PTR_TD 0x00000000
296 #define UHCI_PTR_QH 0x00000002
297 #define UHCI_PTR_VF 0x00000004
299 #define UHCI_TD_GET_ACTLEN(s) (((s) + 1) & 0x3ff)
300 #define UHCI_TD_ZERO_ACTLEN(t) ((t) | 0x3ff)
301 #define UHCI_TD_BITSTUFF 0x00020000
302 #define UHCI_TD_CRCTO 0x00040000
303 #define UHCI_TD_NAK 0x00080000
304 #define UHCI_TD_BABBLE 0x00100000
305 #define UHCI_TD_DBUFFER 0x00200000
306 #define UHCI_TD_STALLED 0x00400000
307 #define UHCI_TD_ACTIVE 0x00800000
308 #define UHCI_TD_IOC 0x01000000
309 #define UHCI_TD_IOS 0x02000000
310 #define UHCI_TD_LS 0x04000000
311 #define UHCI_TD_GET_ERRCNT(s) (((s) >> 27) & 3)
312 #define UHCI_TD_SET_ERRCNT(n) ((n) << 27)
313 #define UHCI_TD_SPD 0x20000000
315 #define UHCI_TD_PID_IN 0x00000069
316 #define UHCI_TD_PID_OUT 0x000000e1
317 #define UHCI_TD_PID_SETUP 0x0000002d
318 #define UHCI_TD_GET_PID(s) ((s) & 0xff)
319 #define UHCI_TD_SET_DEVADDR(a) ((a) << 8)
320 #define UHCI_TD_GET_DEVADDR(s) (((s) >> 8) & 0x7f)
321 #define UHCI_TD_SET_ENDPT(e) (((e)&0xf) << 15)
322 #define UHCI_TD_GET_ENDPT(s) (((s) >> 15) & 0xf)
323 #define UHCI_TD_SET_DT(t) ((t) << 19)
324 #define UHCI_TD_GET_DT(s) (((s) >> 19) & 1)
325 #define UHCI_TD_SET_MAXLEN(l) (((l)-1) << 21)
326 #define UHCI_TD_GET_MAXLEN(s) ((((s) >> 21) + 1) & 0x7ff)
327 #define UHCI_TD_MAXLEN_MASK 0xffe00000
329 #define UHCI_TD_ERROR (UHCI_TD_BITSTUFF|UHCI_TD_CRCTO|UHCI_TD_BABBLE|UHCI_TD_DBUFFER|UHCI_TD_STALLED)
331 #define UHCI_TD_SETUP(len, endp, dev) (UHCI_TD_SET_MAXLEN(len) | \
332 UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_SETUP)
333 #define UHCI_TD_OUT(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \
334 UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | \
335 UHCI_TD_PID_OUT | UHCI_TD_SET_DT(dt))
336 #define UHCI_TD_IN(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \
337 UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_IN | \
341 UHCI_TransferDesc
*uhci_AllocTD(OOP_Class
*cl
, OOP_Object
*o
);
342 UHCI_QueueHeader
*uhci_AllocQH(OOP_Class
*cl
, OOP_Object
*o
);
343 void uhci_FreeTD(OOP_Class
*cl
, OOP_Object
*o
, UHCI_TransferDesc
*td
);
344 void uhci_FreeQH(OOP_Class
*cl
, OOP_Object
*o
, UHCI_QueueHeader
*qh
);
345 void uhci_FreeTDQuick(UHCIData
*uhci
, UHCI_TransferDesc
*td
);
346 void uhci_FreeQHQuick(UHCIData
*uhci
, UHCI_QueueHeader
*qh
);
347 void uhci_sleep(OOP_Class
*cl
, OOP_Object
*o
, uint32_t msec
);
348 void uhci_globalreset(OOP_Class
*cl
, OOP_Object
*o
);
349 void uhci_reset(OOP_Class
*cl
, OOP_Object
*o
);
350 BOOL
uhci_run(OOP_Class
*cl
, OOP_Object
*o
, BOOL run
);
352 void uhci_RebuildList(OOP_Class
*cl
, OOP_Object
*o
);
353 UHCI_Pipe
*uhci_CreatePipe(OOP_Class
*cl
, OOP_Object
*o
, enum USB_PipeType type
, BOOL fullspeed
,
354 uint8_t addr
, uint8_t endp
, uint8_t period
, uint32_t maxp
, uint32_t timeout
);
355 void uhci_DeletePipe(OOP_Class
*cl
, OOP_Object
*o
, UHCI_Pipe
*pipe
);
356 void uhci_QueuedTransfer(OOP_Class
*cl
, OOP_Object
*o
, UHCI_Pipe
*pipe
, VOID
*buffer
, uint32_t length
, BOOL in
);
357 void uhci_QueuedWrite(OOP_Class
*cl
, OOP_Object
*o
, UHCI_Pipe
*pipe
, VOID
*buffer
, uint32_t length
);
358 void uhci_QueuedRead(OOP_Class
*cl
, OOP_Object
*o
, UHCI_Pipe
*pipe
, VOID
*buffer
, uint32_t length
);
359 void uhci_ControlTransfer(OOP_Class
*cl
, OOP_Object
*o
, UHCI_Pipe
*pipe
,
360 USBDevice_Request
*request
, VOID
*buffer
, uint32_t length
);
361 BOOL
uhci_PortReset(OOP_Class
*cl
, OOP_Object
*o
, uint8_t p
);