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>
28 #include <usb/usb_core.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>
46 * usb_delay() stops waits for specified amount of miliseconds. It uses the timerequest
47 * of specified USB device. No pre-allocation of signals is required.
49 void ohci_Delay(struct timerequest
*tr
, uint32_t msec
)
51 /* Allocate a signal within this task context */
52 tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= SIGB_SINGLE
;
53 tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= FindTask(NULL
);
55 /* Specify the request */
56 tr
->tr_node
.io_Command
= TR_ADDREQUEST
;
57 tr
->tr_time
.tv_secs
= msec
/ 1000;
58 tr
->tr_time
.tv_micro
= 1000 * (msec
% 1000);
61 DoIO((struct IORequest
*)tr
);
63 tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= NULL
;
67 struct timerequest
*ohci_CreateTimer()
69 struct timerequest
*tr
= NULL
;
70 struct MsgPort
*mp
= NULL
;
75 tr
= (struct timerequest
*)CreateIORequest(mp
, sizeof(struct timerequest
));
78 FreeSignal(mp
->mp_SigBit
);
79 if (!OpenDevice((STRPTR
)"timer.device", UNIT_MICROHZ
, (struct IORequest
*)tr
, 0))
82 DeleteIORequest((struct IORequest
*)tr
);
83 mp
->mp_SigBit
= AllocSignal(-1);
91 void ohci_DeleteTimer(struct timerequest
*tr
)
95 tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= AllocSignal(-1);
96 CloseDevice((struct IORequest
*)tr
);
97 DeleteMsgPort(tr
->tr_node
.io_Message
.mn_ReplyPort
);
98 DeleteIORequest((struct IORequest
*)tr
);
103 * This function allocates a new 32-byte Transfer Descriptor from the
104 * pool of 4K-aligned PCI-accessible memory regions. Within each 4K page,
105 * a bitmap is used to determine which of the TD elements are available
108 * This function returns NULL if no free TD's are found and no more memory
111 ohci_td_t
*ohci_AllocTD(OOP_Class
*cl
, OOP_Object
*o
)
113 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
115 uint8_t node_num
= 32;
118 ObtainSemaphore(&SD(cl
)->tdLock
);
120 /* Walk through the list of already available 4K pages */
121 ForeachNode(&SD(cl
)->tdList
, n
)
124 * For each 4K page, search the first free node (cleared bit) and alloc it.
126 for (bmp_pos
=0; bmp_pos
< 4; bmp_pos
++)
128 if (n
->tdBitmap
[bmp_pos
] != 0xffffffff)
130 for (node_num
= 0; node_num
< 32; node_num
++)
133 if (!(n
->tdBitmap
[bmp_pos
] & (1 << node_num
)))
135 ohci_td_t
* td
= &n
->tdPage
[bmp_pos
*32 + node_num
];
136 /* Mark the TD as used and return a pointer to it */
137 n
->tdBitmap
[bmp_pos
] |= 1 << node_num
;
139 ReleaseSemaphore(&SD(cl
)->tdLock
);
149 * No free TDs have been found on the list of 4K pages. Create new Page node
150 * and alloc 4K PCI accessible memory region for it
152 if ((n
= AllocPooled(SD(cl
)->memPool
, sizeof(td_node_t
))))
154 if ((n
->tdPage
= HIDD_PCIDriver_AllocPCIMem(ohci
->pciDriver
, 4096)))
156 /* Make 4K node available for future allocations */
157 AddHead(&SD(cl
)->tdList
, (struct Node
*)n
);
158 ohci_td_t
* td
= &n
->tdPage
[0];
160 /* Mark first TD as used and return a pointer to it */
163 ReleaseSemaphore(&SD(cl
)->tdLock
);
167 FreePooled(SD(cl
)->memPool
, n
, sizeof(td_node_t
));
170 ReleaseSemaphore(&SD(cl
)->tdLock
);
172 /* Everything failed? Out of memory, most likely */
177 * This function allocats new 16-byte Endpoint Descriptor aligned at the 16-byte boundary.
178 * See ohci_AllocTD for more details.
180 ohci_ed_t
*ohci_AllocED(OOP_Class
*cl
, OOP_Object
*o
)
183 * Since the Endpoint Descriptors have to be aligned at the 16-byte boundary, they may
184 * be allocated from the same pool TD's are
186 return (ohci_ed_t
*)ohci_AllocTD(cl
, o
);
190 * Mark the Transfer Descriptor free, so that it may be allocated by another one.
191 * A quick version which may be called from interrupts.
193 void ohci_FreeTDQuick(ohci_data_t
*ohci
, ohci_td_t
*td
)
197 /* We're inside interrupt probably. Don't ObtainSemaphore. Just lock interrupts instead */
200 /* traverse through the list of 4K pages */
201 ForeachNode(&ohci
->sd
->tdList
, t
)
204 if ((intptr_t)t
->tdPage
== ((intptr_t)td
& ~0xfff))
206 /* extract the correct location of the TD within the bitmap */
207 int bmp
= (((intptr_t)td
& 0xc00) >> 10);
208 int node
= (((intptr_t)td
& 0x3e0) >> 5);
211 t
->tdBitmap
[bmp
] &= ~(1 << node
);
220 void ohci_FreeEDQuick(ohci_data_t
*ohci
, ohci_ed_t
*ed
)
222 ohci_FreeTDQuick(ohci
, (ohci_td_t
*)ed
);
226 * Mark the Transfer Descriptor free, so that it may be allocated by another one.
227 * If the 4K page contains no used descriptors, the page will be freed
229 void ohci_FreeTD(OOP_Class
*cl
, OOP_Object
*o
, ohci_td_t
*td
)
232 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
234 ObtainSemaphore(&SD(cl
)->tdLock
);
236 /* traverse through the list of 4K pages */
237 ForeachNodeSafe(&SD(cl
)->tdList
, t
, next
)
240 if ((intptr_t)t
->tdPage
== ((intptr_t)td
& ~0xfff))
242 /* extract the correct location of the TD within the bitmap */
243 int bmp
= (((intptr_t)td
& 0xc00) >> 10);
244 int node
= (((intptr_t)td
& 0x3e0) >> 5);
247 t
->tdBitmap
[bmp
] &= ~(1 << node
);
249 /* Check, if all TD nodes are freee within the 4K page */
251 for (i
=0; i
< 4; i
++)
252 if (t
->tdBitmap
[i
] != 0)
255 /* So is it. Free the 4K page */
258 Remove((struct Node
*)t
);
259 HIDD_PCIDriver_FreePCIMem(ohci
->pciDriver
, t
->tdPage
);
260 FreePooled(SD(cl
)->memPool
, t
, sizeof(td_node_t
));
266 ReleaseSemaphore(&SD(cl
)->tdLock
);
269 void ohci_FreeED(OOP_Class
*cl
, OOP_Object
*o
, ohci_ed_t
*ed
)
271 ohci_FreeTD(cl
, o
, (ohci_td_t
*)ed
);
274 AROS_INTH1(ohci_Handler
, ohci_data_t
*,ohci
)
281 mmio(ohci
->regs
->HcInterruptDisable
) = AROS_LONG2OHCI(HC_INTR_MIE
);
283 CacheClearE((APTR
)ohci
->hcca
, sizeof(ohci_hcca_t
), CACRF_InvalidateD
);
284 done
= AROS_OHCI2LONG(ohci
->hcca
->hccaDoneHead
);
291 intrs
|= AROS_OHCI2LONG(mmio(ohci
->regs
->HcInterruptStatus
));
292 ohci
->hcca
->hccaDoneHead
= 0;
296 intrs
= AROS_OHCI2LONG(mmio(ohci
->regs
->HcInterruptStatus
));
297 if (intrs
& HC_INTR_WDH
)
299 done
= AROS_OHCI2LONG(ohci
->hcca
->hccaDoneHead
);
300 ohci
->hcca
->hccaDoneHead
= 0;
303 CacheClearE((APTR
)ohci
->hcca
, sizeof(ohci_hcca_t
), CACRF_ClearD
);
305 intrs
&= ~HC_INTR_MIE
;
307 mmio(ohci
->regs
->HcInterruptStatus
) = AROS_LONG2OHCI(intrs
);
309 /* Clear disabled interrupts */
310 intrs
&= AROS_OHCI2LONG(mmio(ohci
->regs
->HcInterruptEnable
));
313 D(bug("[OHCI] Intr handler %08x, enabled %08x\n",
315 AROS_OHCI2LONG(mmio(ohci
->regs
->HcInterruptEnable
))));
317 if (intrs
& HC_INTR_WDH
)
319 D(bug("[OHCI] WDH Interrupt, hccaDoneHead=%p\n[OHCI] TD's in hccaDoneHead:\n", done
));
320 ohci_td_t
*td
= (ohci_td_t
*)(done
& 0xfffffff0);
322 mmio(ohci
->regs
->HcInterruptStatus
) = AROS_LONG2OHCI(HC_INTR_WDH
);
326 //CacheClearE(td, sizeof(ohci_td_t), CACRF_InvalidateD);
327 //CacheClearE(ohci->hcca, sizeof(ohci_hcca_t), CACRF_InvalidateD);
332 * For each TD issue the signal for corresponding pipe if the
333 * edHeadP=edTailP (thus, the pipe is ready).
337 ohci_pipe_t
*pipe
= td
->tdPipe
;
338 D(bug("[OHCI] Pipe=%08x HeadP=%08x TailP=%08x SigTask=%08x\n", pipe
, AROS_OHCI2LONG(pipe
->ed
->edHeadP
),
339 AROS_OHCI2LONG(pipe
->ed
->edTailP
), pipe
->sigTask
));
341 //CacheClearE(pipe->ed, sizeof(ohci_ed_t), CACRF_InvalidateD);
342 if ((pipe
->ed
->edHeadP
& AROS_OHCI2LONG(0xfffffff0)) == pipe
->ed
->edTailP
)
345 Signal(pipe
->sigTask
, 1 << pipe
->signal
);
349 D(bug("[OHCI] TD @ %p (%08x %08x %08x %08x)\n", td
, AROS_OHCI2LONG(td
->tdFlags
), AROS_OHCI2LONG(td
->tdCurrentBufferPointer
), AROS_OHCI2LONG(td
->tdBufferEnd
), AROS_OHCI2LONG(td
->tdNextTD
)));
351 td
= (ohci_td_t
*)AROS_OHCI2LONG(td
->tdNextTD
);
353 if (tmp
->tdPipe
->type
== PIPE_Interrupt
)
355 ohci_td_t
*itd
= (ohci_td_t
*)AROS_OHCI2LONG(tmp
->tdPipe
->ed
->edTailP
);
357 //CacheClearE(itd, sizeof(ohci_td_t), CACRF_InvalidateD);
358 D(bug("[OHCI] TD belongs to the interrupt pipe. Intr = %p\n", tmp
->tdPipe
->interrupt
));
360 D(bug("[OHCI] restarting TD\n"));
362 /* Restart the pipe's interrupt */
363 itd
->tdFlags
= tmp
->tdFlags
| AROS_LONG2OHCI(0xf0000000);
364 itd
->tdPipe
= tmp
->tdPipe
;
365 itd
->tdBufferEnd
= tmp
->tdBufferEnd
;
366 itd
->tdCurrentBufferPointer
= AROS_LONG2OHCI((uint32_t)(tmp
->tdPipe
->interrupt
->buffer
));
367 itd
->tdNextTD
= AROS_LONG2OHCI((uint32_t)tmp
);
370 tmp
->tdCurrentBufferPointer
= 0;
371 tmp
->tdBufferEnd
= 0;
372 itd
->tdPipe
->ed
->edTailP
= AROS_LONG2OHCI((uint32_t)tmp
);
374 D(bug("[OHCI] TD @ %p (%08x %08x %08x %08x)\n", itd
, AROS_OHCI2LONG(itd
->tdFlags
), AROS_OHCI2LONG(itd
->tdCurrentBufferPointer
), AROS_OHCI2LONG(itd
->tdBufferEnd
), AROS_OHCI2LONG(itd
->tdNextTD
)));
376 D(bug("[OHCI] Pipe=%p, HeadP=%p, TailP=%p\n", itd
->tdPipe
,
377 AROS_OHCI2LONG(itd
->tdPipe
->ed
->edHeadP
), AROS_OHCI2LONG(itd
->tdPipe
->ed
->edTailP
)));
378 D(bug("[OHCI] ED @ %p (%p %p %p %p)\n", itd
->tdPipe
->ed
,
379 AROS_OHCI2LONG(itd
->tdPipe
->ed
->edFlags
),
380 AROS_OHCI2LONG(itd
->tdPipe
->ed
->edHeadP
),
381 AROS_OHCI2LONG(itd
->tdPipe
->ed
->edTailP
),
382 AROS_OHCI2LONG(itd
->tdPipe
->ed
->edNextED
)
385 // CacheClearE(tmp->tdPipe->ed, sizeof(ohci_ed_t), CACRF_ClearD);
386 // CacheClearE(tmp, sizeof(ohci_td_t), CACRF_ClearD);
387 // CacheClearE(itd, sizeof(ohci_td_t), CACRF_ClearD);
389 if (tmp
->tdPipe
->interrupt
)
391 Cause(tmp
->tdPipe
->interrupt
->intr
);
395 ohci_FreeTDQuick(ohci
, tmp
);
399 //CacheClearE(ohci->hcca, sizeof(ohci_hcca_t), CACRF_ClearD);
401 intrs
&= ~HC_INTR_WDH
;
404 if (intrs
& HC_INTR_RHSC
)
406 D(bug("[OHCI] RHSC interrupt. Disabling it for 1 second\n"));
408 mmio(ohci
->regs
->HcInterruptDisable
) = AROS_LONG2OHCI(HC_INTR_RHSC
);
409 mmio(ohci
->regs
->HcInterruptStatus
) = AROS_LONG2OHCI(HC_INTR_RHSC
);
411 intrs
&= ~HC_INTR_RHSC
;
413 /* Restart the RHSC enable timer */
414 ohci
->timerReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
415 ohci
->timerReq
->tr_time
.tv_secs
= 1;
416 ohci
->timerReq
->tr_time
.tv_micro
= 0;
417 SendIO((struct IORequest
*)ohci
->timerReq
);
421 struct Interrupt
*intr
;
423 ForeachNode(&ohci
->intList
, intr
)
431 * OHCI is not yet in running state, thus posting any interrupts
432 * down the classes is forbidden. The pending flag will be set in
433 * order to issue the interrupts as soon as the OHCI will be switched
434 * back to the running state
436 ohci
->pendingRHSC
= 1;
442 mmio(ohci
->regs
->HcInterruptDisable
) = AROS_OHCI2LONG(intrs
);
443 D(bug("[OHCI] Disabling interrupts %p\n", intrs
));
446 mmio(ohci
->regs
->HcInterruptEnable
) = AROS_LONG2OHCI(HC_INTR_MIE
);
453 BOOL
METHOD(OHCI
, Hidd_USBDrv
, AddInterrupt
)
457 if (msg
->pipe
== (void *)0xdeadbeef)
459 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
460 D(bug("[OHCI] AddInterrupt() local for the OHCI. Intr %p, list %p\n", msg
->interrupt
, &ohci
->intList
));
463 ohci
->tmp
= msg
->interrupt
;
465 AddTail(&ohci
->intList
, &msg
->interrupt
->is_Node
);
471 ohci_intr_t
*intr
= AllocVecPooled(SD(cl
)->memPool
, sizeof(ohci_intr_t
));
472 ohci_pipe_t
*pipe
= msg
->pipe
;
475 D(bug("[OHCI] AddInterrupt() intr = %p\n", intr
));
479 intr
->intr
= msg
->interrupt
;
481 tail
= ohci_AllocTD(cl
, o
);
483 intr
->td
= pipe
->tail
;
484 intr
->td
->tdPipe
= pipe
;
485 intr
->buffer
= msg
->buffer
;
486 intr
->length
= msg
->length
;
491 intr
->td
->tdCurrentBufferPointer
= AROS_LONG2OHCI((uint32_t)msg
->buffer
);
492 intr
->td
->tdBufferEnd
= AROS_LONG2OHCI((uint32_t)msg
->buffer
+ msg
->length
- 1);
495 intr
->td
->tdBufferEnd
= intr
->td
->tdCurrentBufferPointer
= 0;
497 D(bug("[OHCI] AddInterrupt() buffer: %08x - %08x\n", AROS_OHCI2LONG(intr
->td
->tdCurrentBufferPointer
), AROS_OHCI2LONG(intr
->td
->tdBufferEnd
)));
499 if (UE_GET_DIR(pipe
->endpoint
) == UE_DIR_IN
)
501 intr
->td
->tdFlags
= AROS_LONG2OHCI(0xf0100000);
505 intr
->td
->tdFlags
= AROS_LONG2OHCI(0xf0080000);
508 intr
->td
->tdNextTD
= AROS_LONG2OHCI((uint32_t)tail
);
510 D(bug("[OHCI] TD @ %p (%p %p %p %p)\n", intr
->td
, AROS_OHCI2LONG(intr
->td
->tdFlags
), AROS_OHCI2LONG(intr
->td
->tdCurrentBufferPointer
), AROS_OHCI2LONG(intr
->td
->tdBufferEnd
), AROS_OHCI2LONG(intr
->td
->tdNextTD
)));
512 CacheClearE(intr
->td
, sizeof(ohci_td_t
), CACRF_ClearD
);
516 pipe
->interrupt
= intr
;
517 pipe
->ed
->edTailP
= AROS_LONG2OHCI((uint32_t)tail
);
519 CacheClearE(pipe
->ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
521 D(bug("[OHCI] ED @ %p (%p %p %p %p)\n", pipe
->ed
,
522 AROS_OHCI2LONG(pipe
->ed
->edFlags
),
523 AROS_OHCI2LONG(pipe
->ed
->edHeadP
),
524 AROS_OHCI2LONG(pipe
->ed
->edTailP
),
525 AROS_OHCI2LONG(pipe
->ed
->edNextED
)
528 CacheClearE(intr
->td
, sizeof(ohci_td_t
), CACRF_ClearD
);
531 D(bug("[OHCI::AddInterrupt] %s\n", retval
? "success":"failure"));
536 BOOL
METHOD(OHCI
, Hidd_USBDrv
, RemInterrupt
)
538 if (msg
->pipe
== (void *)0xdeadbeef)
540 Remove((struct Node
*)msg
->interrupt
);
550 static ohci_ed_t
*ohci_SelectIntrED(ohci_data_t
*ohci
, uint8_t interval
)
552 ohci_ed_t
**ed
= NULL
;
553 uint8_t i
, count
, minimum
, bestat
;
560 else if (interval
< 4)
565 else if (interval
< 8)
570 else if (interval
< 16)
575 else if (interval
< 32)
587 minimum
= ED_GET_USAGE(ed
[0]);
590 if (minimum
> ED_GET_USAGE(ed
[i
]))
592 minimum
= ED_GET_USAGE(ed
[i
]);
595 } while (++i
< count
);
597 (bug("[OHCI] Best node (%d uses) %d from %d\n", minimum
, bestat
, count
));
599 ED_SET_USAGE(ed
[bestat
], ED_GET_USAGE(ed
[bestat
]) + 1);
604 void *METHOD(OHCI
, Hidd_USBDrv
, CreatePipe
)
606 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
607 ohci_pipe_t
*pipe
= NULL
;
609 // if (msg->address == 2 && msg->endpoint==0x81)
613 bug("[OHCI] CreatePipe(");
625 case PIPE_Isochronous
:
631 bug(", %s, %02x, %02x, %d, %dms)\n", msg
->fullspeed
? "FAST":"SLOW",
632 msg
->address
, msg
->endpoint
, msg
->maxpacket
, msg
->timeout
);
635 pipe
= AllocVecPooled(SD(cl
)->memPool
,sizeof(ohci_pipe_t
));
639 pipe
->tail
= ohci_AllocTD(cl
, o
);
640 pipe
->tail
->tdBufferEnd
= 0;
641 pipe
->tail
->tdCurrentBufferPointer
= 0;
642 pipe
->tail
->tdFlags
= 0;
643 pipe
->tail
->tdNextTD
= 0;
644 pipe
->tail
->tdPipe
= pipe
;
645 CacheClearE(pipe
->tail
, sizeof(ohci_td_t
), CACRF_ClearD
);
647 pipe
->ed
= ohci_AllocED(cl
, o
);
648 pipe
->type
= msg
->type
;
649 pipe
->address
= msg
->address
;
650 pipe
->endpoint
= msg
->endpoint
;
651 pipe
->interval
= msg
->period
;
652 pipe
->maxpacket
= msg
->maxpacket
;
654 pipe
->ed
->edPipe
= pipe
;
655 pipe
->ed
->edFlags
= AROS_LONG2OHCI((msg
->address
& ED_FA_MASK
) |
656 ((msg
->endpoint
<< 7) & ED_EN_MASK
) |
657 ((msg
->maxpacket
<< 16) & ED_MPS_MASK
) | ED_K
);
660 pipe
->ed
->edFlags
|= AROS_LONG2OHCI(ED_S
);
662 pipe
->ed
->edHeadP
= pipe
->ed
->edTailP
= AROS_LONG2OHCI((uint32_t)pipe
->tail
);
663 //pipe->ed->edHeadP |= AROS_LONG2OHCI(2);
665 CacheClearE(pipe
->ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
667 //NEWLIST(&pipe->intList);
668 InitSemaphore(&pipe
->lock
);
670 pipe
->timeoutVal
= msg
->timeout
;
671 pipe
->timeout
= (struct timerequest
*)CreateIORequest(
672 CreateMsgPort(), sizeof(struct timerequest
));
674 FreeSignal(pipe
->timeout
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
);
675 OpenDevice((STRPTR
)"timer.device", UNIT_MICROHZ
, (struct IORequest
*)pipe
->timeout
, 0);
677 /* According to the pipe's type, add it to proper list */
681 pipe
->location
= ohci
->bulk_head
;
685 pipe
->location
= ohci
->ctrl_head
;
688 case PIPE_Isochronous
:
689 pipe
->location
= ohci
->isoc_head
;
690 pipe
->ed
->edFlags
|= AROS_LONG2OHCI(ED_F
);
691 CacheClearE(pipe
->ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
695 pipe
->location
= ohci_SelectIntrED(ohci
, msg
->period
);
701 pipe
->ed
->edNextED
= pipe
->location
->edNextED
& AROS_LONG2OHCI(0xfffffff0);
702 pipe
->location
->edNextED
= AROS_LONG2OHCI((AROS_OHCI2LONG(pipe
->location
->edNextED
) & 0x0000000f) | (uint32_t)(pipe
->ed
));
704 D(bug("[OHCI] Master ED at %p\n", pipe
->location
));
707 pipe
->ed
->edFlags
&= ~AROS_LONG2OHCI(ED_K
);
708 pipe
->location
->edFlags
&= ~AROS_LONG2OHCI(ED_K
);
710 CacheClearE(pipe
->location
, sizeof(ohci_ed_t
), CACRF_ClearD
);
711 CacheClearE(pipe
->ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
714 D(bug("[OHCI] CreatePipe()=%p\n", pipe
));
718 void METHOD(OHCI
, Hidd_USBDrv
, SetTimeout
)
720 ohci_pipe_t
*pipe
= msg
->pipe
;
723 pipe
->timeoutVal
= msg
->timeout
;
726 void METHOD(OHCI
, Hidd_USBDrv
, DeletePipe
)
728 ohci_pipe_t
*pipe
= msg
->pipe
;
730 D(bug("[OHCI] DeletePipe(%p, ed=%p)\n", pipe
, pipe
->ed
));
734 ohci_ed_t
*ed
= pipe
->location
;
736 D(bug("[OHCI] ED @ %p (%p %p %p %p)\n", pipe
->ed
,
737 AROS_OHCI2LONG(pipe
->ed
->edFlags
),
738 AROS_OHCI2LONG(pipe
->ed
->edHeadP
),
739 AROS_OHCI2LONG(pipe
->ed
->edTailP
),
740 AROS_OHCI2LONG(pipe
->ed
->edNextED
)
743 D(bug("[OHCI] location=%p\n", ed
));
745 D(bug("[OHCI] ED @ %p (%p %p %p %p)\n", ed
,
746 AROS_OHCI2LONG(ed
->edFlags
),
747 AROS_OHCI2LONG(ed
->edHeadP
),
748 AROS_OHCI2LONG(ed
->edTailP
),
749 AROS_OHCI2LONG(ed
->edNextED
)
752 /* Stop pipe from being processed */
753 pipe
->ed
->edFlags
|= AROS_LONG2OHCI(ED_K
);
754 CacheClearE(pipe
->ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
756 if (pipe
->type
== PIPE_Interrupt
)
759 ED_SET_USAGE(ed
, ED_GET_USAGE(ed
) - 1);
760 CacheClearE(ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
764 /* Remove pipe from the proper list */
765 while ((uint32_t)ed
& 0xfffffff0)
767 D(bug("[OHCI] ed->edNextED=%p\n", AROS_OHCI2LONG(ed
->edNextED
)));
769 if ((AROS_OHCI2LONG(ed
->edNextED
) & 0xfffffff0) == ((uint32_t)pipe
->ed
))
771 D(bug("[OHCI] ED match the pipe (pipe->edNextED=%p)\n", AROS_OHCI2LONG(pipe
->ed
->edNextED
)));
773 uint32_t next
= (AROS_OHCI2LONG(ed
->edNextED
) & 0x0000000f) | (AROS_OHCI2LONG(pipe
->ed
->edNextED
) & 0xfffffff0);
774 ed
->edNextED
= AROS_LONG2OHCI(next
);
777 D(bug("[OHCI] ed->edNextED=%p (fixed)\n", AROS_LONG2OHCI(ed
->edNextED
)));
779 CacheClearE(ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
783 ed
= (ohci_ed_t
*)(AROS_LONG2OHCI(ed
->edNextED
) & 0xfffffff0);
786 /* Remove any TD's pending */
787 while((AROS_OHCI2LONG(pipe
->ed
->edTailP
) & 0xfffffff0) != (AROS_OHCI2LONG(pipe
->ed
->edHeadP
) & 0xfffffff0))
789 ohci_td_t
*t
= (ohci_td_t
*)(AROS_OHCI2LONG(pipe
->ed
->edHeadP
) & 0xfffffff0);
790 pipe
->ed
->edHeadP
= AROS_LONG2OHCI(AROS_OHCI2LONG(t
->tdNextTD
) & 0xfffffff0);
792 D(bug("[OHCI] TD @ %p (%p %p %p %p)\n", t
, AROS_OHCI2LONG(t
->tdFlags
), AROS_OHCI2LONG(t
->tdCurrentBufferPointer
), AROS_OHCI2LONG(t
->tdBufferEnd
), AROS_OHCI2LONG(t
->tdNextTD
)));
794 ohci_FreeTD(cl
, o
, t
);
797 if (pipe
->ed
->edTailP
)
798 ohci_FreeTD(cl
, o
, (ohci_td_t
*)AROS_OHCI2LONG(pipe
->ed
->edTailP
));
800 /* Close timer device */
801 pipe
->timeout
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= AllocSignal(-1);
802 CloseDevice((struct IORequest
*)pipe
->timeout
);
803 DeleteMsgPort(pipe
->timeout
->tr_node
.io_Message
.mn_ReplyPort
);
804 DeleteIORequest((struct IORequest
*)pipe
->timeout
);
806 ohci_FreeED(cl
, o
, pipe
->ed
);
807 FreeVecPooled(SD(cl
)->memPool
, pipe
);
813 BOOL
METHOD(OHCI
, Hidd_USBDrv
, ControlTransfer
)
815 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
816 ohci_pipe_t
*pipe
= msg
->pipe
;
817 int8_t sig
= AllocSignal(-1);
818 int8_t toutsig
= AllocSignal(-1);
822 D(bug("[OHCI] ControlTransfer()\n"));
824 ObtainSemaphore(&pipe
->lock
);
826 if (sig
>= 0 && toutsig
>= 0)
830 ohci_td_t
*td
, *tail
;
835 pipe
->sigTask
= FindTask(NULL
);
837 tail
= ohci_AllocTD(cl
, o
);
839 tail
->tdCurrentBufferPointer
= 0;
840 tail
->tdBufferEnd
= 0;
844 length
= sizeof(USBDevice_Request
);
845 request
= CachePreDMA(msg
->request
, &length
, DMA_ReadFromRAM
);
847 /* Do the right control transfer */
848 setup
= td
= pipe
->tail
;
849 setup
->tdFlags
= AROS_LONG2OHCI(0xf0000000 | 0x02000000 | 0x00e00000);
850 setup
->tdCurrentBufferPointer
= AROS_LONG2OHCI((uint32_t)request
);
851 setup
->tdBufferEnd
= AROS_LONG2OHCI((uint32_t)request
+ sizeof(USBDevice_Request
) - 1);
852 setup
->tdPipe
= pipe
;
854 status
= ohci_AllocTD(cl
, o
);
855 status
->tdFlags
= AROS_LONG2OHCI(0xf3000000 | ((msg
->request
->bmRequestType
& UT_READ
) ? 0x00080000 : 0x00100000));
856 status
->tdBufferEnd
= 0;
857 status
->tdCurrentBufferPointer
= 0;
858 status
->tdNextTD
= AROS_LONG2OHCI((uint32_t)tail
);
859 status
->tdPipe
= pipe
;
861 if (msg
->buffer
&& msg
->length
< 8192)
863 length
= msg
->length
;
864 if (msg
->request
->bmRequestType
& UT_READ
)
865 buffer
= CachePreDMA(msg
->buffer
, &length
, 0);
867 buffer
= CachePreDMA(msg
->buffer
, &length
, DMA_ReadFromRAM
);
869 /* Get new TD and link it immediatelly with the previous one */
870 td
->tdNextTD
= AROS_LONG2OHCI((uint32_t)ohci_AllocTD(cl
, o
));
871 td
= (ohci_td_t
*)AROS_OHCI2LONG(td
->tdNextTD
);
873 td
->tdFlags
= AROS_LONG2OHCI(0xf3e00000 | ((msg
->request
->bmRequestType
& UT_READ
) ? 0x00100000 : 0x00080000));
874 td
->tdCurrentBufferPointer
= AROS_LONG2OHCI((uint32_t)buffer
);
875 td
->tdBufferEnd
= AROS_LONG2OHCI((uint32_t)buffer
+ msg
->length
- 1);
879 /* Link last TD with the status TD */
880 td
->tdNextTD
= AROS_LONG2OHCI((uint32_t)status
);
882 D(bug("[OHCI] Transfer:\n[OHCI] SETUP=%p (%p %p %p %p)\n", setup
, AROS_OHCI2LONG(setup
->tdFlags
), AROS_OHCI2LONG(setup
->tdCurrentBufferPointer
), AROS_OHCI2LONG(setup
->tdBufferEnd
), AROS_OHCI2LONG(setup
->tdNextTD
)));
884 D(bug("[OHCI] DATA=%p (%p %p %p %p)\n", td
, AROS_OHCI2LONG(td
->tdFlags
), AROS_OHCI2LONG(td
->tdCurrentBufferPointer
), AROS_OHCI2LONG(td
->tdBufferEnd
), AROS_OHCI2LONG(td
->tdNextTD
)));
885 D(bug("[OHCI] STAT=%p (%p %p %p %p)\n", status
, AROS_OHCI2LONG(status
->tdFlags
), AROS_OHCI2LONG(status
->tdCurrentBufferPointer
), AROS_OHCI2LONG(status
->tdBufferEnd
), AROS_OHCI2LONG(status
->tdNextTD
)));
889 /* Link the first TD with end of the ED's transfer queue */
890 CacheClearE(setup
, sizeof(ohci_td_t
), CACRF_ClearD
);
891 CacheClearE(status
, sizeof(ohci_td_t
), CACRF_ClearD
);
892 CacheClearE(td
, sizeof(ohci_td_t
), CACRF_ClearD
);
893 CacheClearE(tail
, sizeof(ohci_td_t
), CACRF_ClearD
);
895 /* Fire the transfer */
896 if (pipe
->timeoutVal
!= 0)
898 int32_t msec
= pipe
->timeoutVal
+ 10000;
899 pipe
->timeout
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= toutsig
;
900 pipe
->timeout
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= FindTask(NULL
);
902 pipe
->timeout
->tr_node
.io_Command
= TR_ADDREQUEST
;
903 pipe
->timeout
->tr_time
.tv_secs
= msec
/ 1000;
904 pipe
->timeout
->tr_time
.tv_micro
= 1000 * (msec
% 1000);
906 SendIO((struct IORequest
*)pipe
->timeout
);
909 pipe
->ed
->edTailP
= AROS_LONG2OHCI((uint32_t)tail
);
911 CacheClearE(pipe
->ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
913 mmio(ohci
->regs
->HcCommandStatus
) |= AROS_LONG2OHCI(HC_CS_CLF
);
915 /* Wait for completion signals */
916 if (Wait((1 << sig
) | (1 << toutsig
)) & (1 << toutsig
))
918 /* Timeout. Pipe stall. */
919 bug("[OHCI] ControlTransfer() !!!TIMEOUT!!!\n");
921 GetMsg(pipe
->timeout
->tr_node
.io_Message
.mn_ReplyPort
);
923 /* Remove any TD's pending */
925 D(bug("[OHCI] HeadP=%p TailP=%p\n", AROS_OHCI2LONG(pipe
->ed
->edHeadP
), AROS_OHCI2LONG(pipe
->ed
->edTailP
)));
926 D(bug("[OHCI] TD's in ED: \n"));
927 ohci_td_t
*td
= (ohci_td_t
*)(AROS_OHCI2LONG(pipe
->ed
->edHeadP
) & 0xfffffff0);
930 D(bug("[OHCI] TD @ %p (%p %p %p %p)\n", td
, AROS_OHCI2LONG(td
->tdFlags
), AROS_OHCI2LONG(td
->tdCurrentBufferPointer
), AROS_OHCI2LONG(td
->tdBufferEnd
), AROS_OHCI2LONG(td
->tdNextTD
)));
931 td
= (ohci_td_t
*)(AROS_OHCI2LONG(td
->tdNextTD
) & 0xfffffff0);
934 while((AROS_OHCI2LONG(pipe
->ed
->edTailP
) & 0xfffffff0) != (AROS_OHCI2LONG(pipe
->ed
->edHeadP
) & 0xfffffff0))
936 ohci_td_t
*t
= (ohci_td_t
*)(AROS_OHCI2LONG(pipe
->ed
->edHeadP
) & 0xfffffff0);
937 pipe
->ed
->edHeadP
= AROS_LONG2OHCI(AROS_OHCI2LONG(t
->tdNextTD
) & 0xfffffff0);
938 ohci_FreeTD(cl
, o
, t
);
941 /* Reenable the ED */
942 pipe
->ed
->edHeadP
&= AROS_LONG2OHCI(0xfffffff0);
943 CacheClearE(pipe
->ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
950 * No timeout occured. Remove the timeout request and report success. In this case,
951 * the TD's are freed automatically by the interrupt handler.
954 if (!CheckIO((struct IORequest
*)pipe
->timeout
))
955 AbortIO((struct IORequest
*)pipe
->timeout
);
956 WaitIO((struct IORequest
*)pipe
->timeout
);
957 SetSignal(0, 1 << toutsig
);
959 if (!pipe
->errorCode
)
963 length
= sizeof(USBDevice_Request
);
964 CachePostDMA(msg
->request
, &length
, DMA_ReadFromRAM
);
965 if (msg
->buffer
&& msg
->length
)
967 length
= msg
->length
;
968 if (msg
->request
->bmRequestType
& UT_READ
)
969 CachePostDMA(msg
->buffer
, &length
, 0);
971 CachePostDMA(msg
->buffer
, &length
, DMA_ReadFromRAM
);
979 D(bug("[OHCI] ControlTransfer() %s\n", retval
?"OK":"FAILED"));
981 ReleaseSemaphore(&pipe
->lock
);
986 BOOL
METHOD(OHCI
, Hidd_USBDrv
, BulkTransfer
)
988 ohci_data_t
*ohci
= OOP_INST_DATA(cl
, o
);
989 ohci_pipe_t
*pipe
= msg
->pipe
;
990 int8_t sig
= AllocSignal(-1);
991 int8_t toutsig
= AllocSignal(-1);
992 uint32_t length
= msg
->length
;
996 D(bug("[OHCI] BulkTransfer()\n"));
997 D(bug("[OHCI] Pipe %x %s endpoint %02x addr %02x\n", pipe
, UE_GET_DIR(pipe
->endpoint
) == UE_DIR_IN
? "IN":"OUT",
998 pipe
->endpoint
, pipe
->address
));
1000 ObtainSemaphore(&pipe
->lock
);
1002 if (sig
>= 0 && toutsig
>= 0)
1004 ohci_td_t
*td
, *first_td
, *tail
;
1005 const uint32_t maxpacket
= 4096; //(8192 / pipe->maxpacket) * pipe->maxpacket;
1008 pipe
->sigTask
= FindTask(NULL
);
1010 first_td
= td
= pipe
->tail
;
1012 tail
= ohci_AllocTD(cl
, o
);
1014 tail
->tdCurrentBufferPointer
= 0;
1015 tail
->tdBufferEnd
= 0;
1017 tail
->tdPipe
= pipe
;
1019 if (UE_GET_DIR(pipe
->endpoint
) == UE_DIR_IN
)
1020 buff
= CachePreDMA(msg
->buffer
, &length
, 0);
1022 buff
= CachePreDMA(msg
->buffer
, &length
, DMA_ReadFromRAM
);
1026 uint32_t len
= length
> maxpacket
? maxpacket
: length
;
1028 td
->tdFlags
= AROS_LONG2OHCI(0xf0000000);
1029 td
->tdFlags
|= AROS_LONG2OHCI(TD_R
);
1032 td
->tdFlags
|= AROS_LONG2OHCI(0x00e00000);
1034 if (UE_GET_DIR(pipe
->endpoint
) == UE_DIR_IN
)
1035 td
->tdFlags
|= AROS_LONG2OHCI(0x00100000);
1037 td
->tdFlags
|= AROS_LONG2OHCI(0x00080000);
1040 td
->tdCurrentBufferPointer
= AROS_LONG2OHCI((IPTR
)buff
);
1041 td
->tdBufferEnd
= AROS_LONG2OHCI((IPTR
)buff
+ len
- 1);
1047 ohci_td_t
*newtd
= ohci_AllocTD(cl
, o
);
1048 td
->tdNextTD
= AROS_LONG2OHCI((uint32_t)newtd
);
1049 CacheClearE(td
, sizeof(ohci_td_t
), CACRF_ClearD
);
1053 td
->tdNextTD
= (IPTR
)AROS_LONG2OHCI((IPTR
)tail
);
1054 CacheClearE(td
, sizeof(ohci_td_t
), CACRF_ClearD
);
1056 D(bug("[OHCI] Transfer:\n"));
1057 for (td
= first_td
; td
; td
= (ohci_td_t
*)AROS_OHCI2LONG(td
->tdNextTD
))
1059 D(bug("[OHCI] DATA=%p (%p %p %p %p)\n", td
, AROS_OHCI2LONG(td
->tdFlags
), AROS_OHCI2LONG(td
->tdCurrentBufferPointer
), AROS_OHCI2LONG(td
->tdBufferEnd
), AROS_OHCI2LONG(td
->tdNextTD
)));
1061 pipe
->errorCode
= 0;
1063 length
= msg
->length
;
1065 /* Fire the transfer */
1066 if (pipe
->timeoutVal
!= 0)
1068 int32_t msec
= pipe
->timeoutVal
+ 10000;
1069 pipe
->timeout
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= toutsig
;
1070 pipe
->timeout
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= FindTask(NULL
);
1072 pipe
->timeout
->tr_node
.io_Command
= TR_ADDREQUEST
;
1073 pipe
->timeout
->tr_time
.tv_secs
= msec
/ 1000;
1074 pipe
->timeout
->tr_time
.tv_micro
= 1000 * (msec
% 1000);
1076 SendIO((struct IORequest
*)pipe
->timeout
);
1079 pipe
->ed
->edTailP
= AROS_LONG2OHCI((uint32_t)tail
);
1081 CacheClearE(pipe
->ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
1083 mmio(ohci
->regs
->HcCommandStatus
) |= AROS_LONG2OHCI(HC_CS_BLF
);
1085 /* Wait for completion signals */
1086 if (Wait((1 << sig
) | (1 << toutsig
)) & (1 << toutsig
))
1088 /* Timeout. Pipe stall. */
1089 bug("[OHCI] BulkTransfer() !!!TIMEOUT!!!\n");
1091 GetMsg(pipe
->timeout
->tr_node
.io_Message
.mn_ReplyPort
);
1093 /* Remove any TD's pending */
1095 D(bug("[OHCI] HeadP=%p TailP=%p\n", AROS_OHCI2LONG(pipe
->ed
->edHeadP
), AROS_OHCI2LONG(pipe
->ed
->edTailP
)));
1096 D(bug("[OHCI] TD's in ED: \n"));
1097 ohci_td_t
*td
= (ohci_td_t
*)(AROS_OHCI2LONG(pipe
->ed
->edHeadP
) & 0xfffffff0);
1100 D(bug("[OHCI] TD @ %p (%p %p %p %p)\n", td
, AROS_OHCI2LONG(td
->tdFlags
), AROS_OHCI2LONG(td
->tdCurrentBufferPointer
), AROS_OHCI2LONG(td
->tdBufferEnd
), AROS_OHCI2LONG(td
->tdNextTD
)));
1101 td
= (ohci_td_t
*)(AROS_OHCI2LONG(td
->tdNextTD
) & 0xfffffff0);
1104 while((AROS_OHCI2LONG(pipe
->ed
->edTailP
) & 0xfffffff0) != (AROS_OHCI2LONG(pipe
->ed
->edHeadP
) & 0xfffffff0))
1106 ohci_td_t
*t
= (ohci_td_t
*)(AROS_OHCI2LONG(pipe
->ed
->edHeadP
) & 0xfffffff0);
1107 pipe
->ed
->edHeadP
= AROS_LONG2OHCI(AROS_OHCI2LONG(t
->tdNextTD
) & 0xfffffff0);
1108 ohci_FreeTD(cl
, o
, t
);
1111 /* Reenable the ED */
1112 pipe
->ed
->edHeadP
&= AROS_LONG2OHCI(0xfffffff0);
1113 CacheClearE(pipe
->ed
, sizeof(ohci_ed_t
), CACRF_ClearD
);
1120 * No timeout occured. Remove the timeout request and report success. In this case,
1121 * the TD's are freed automatically by the interrupt handler.
1124 if (!CheckIO((struct IORequest
*)pipe
->timeout
))
1125 AbortIO((struct IORequest
*)pipe
->timeout
);
1126 WaitIO((struct IORequest
*)pipe
->timeout
);
1127 SetSignal(0, 1 << toutsig
);
1129 if (!pipe
->errorCode
)
1133 length
= msg
->length
;
1134 if (UE_GET_DIR(pipe
->endpoint
) == UE_DIR_IN
)
1135 CachePostDMA(msg
->buffer
, &length
, 0);
1137 CachePostDMA(msg
->buffer
, &length
, DMA_ReadFromRAM
);
1140 FreeSignal(toutsig
);
1143 D(bug("[OHCI] BulkTransfer() %s\n", retval
?"OK":"FAILED"));
1145 ReleaseSemaphore(&pipe
->lock
);