2 * Copyright 2004-2011, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
8 * Salvatore Benedetto <salvatore.benedetto@gmail.com>
15 #include <KernelExport.h>
19 #define USB_MODULE_NAME "uhci"
21 pci_module_info
*UHCI::sPCIModule
= NULL
;
22 pci_x86_module_info
*UHCI::sPCIx86Module
= NULL
;
26 uhci_std_ops(int32 op
, ...)
30 TRACE_MODULE("init module\n");
33 TRACE_MODULE("uninit module\n");
43 usb_host_controller_info uhci_module
= {
54 module_info
*modules
[] = {
55 (module_info
*)&uhci_module
,
68 print_descriptor_chain(uhci_td
*descriptor
)
71 dprintf("ph: 0x%08" B_PRIx32
"; lp: 0x%08" B_PRIx32
"; vf: %s; q: %s; "
72 "t: %s; st: 0x%08" B_PRIx32
"; to: 0x%08" B_PRIx32
"\n",
73 descriptor
->this_phy
& 0xffffffff, descriptor
->link_phy
& 0xfffffff0,
74 descriptor
->link_phy
& 0x4 ? "y" : "n",
75 descriptor
->link_phy
& 0x2 ? "qh" : "td",
76 descriptor
->link_phy
& 0x1 ? "y" : "n",
77 descriptor
->status
, descriptor
->token
);
79 if (descriptor
->link_phy
& TD_TERMINATE
)
82 descriptor
= (uhci_td
*)descriptor
->link_log
;
94 Queue::Queue(Stack
*stack
)
98 mutex_init(&fLock
, "uhci queue lock");
100 phys_addr_t physicalAddress
;
101 fStatus
= fStack
->AllocateChunk((void **)&fQueueHead
, &physicalAddress
,
106 fQueueHead
->this_phy
= (uint32
)physicalAddress
;
107 fQueueHead
->element_phy
= QH_TERMINATE
;
109 fStrayDescriptor
= NULL
;
117 mutex_destroy(&fLock
);
119 fStack
->FreeChunk(fQueueHead
, fQueueHead
->this_phy
, sizeof(uhci_qh
));
121 if (fStrayDescriptor
)
122 fStack
->FreeChunk(fStrayDescriptor
, fStrayDescriptor
->this_phy
,
137 return (mutex_lock(&fLock
) == B_OK
);
144 mutex_unlock(&fLock
);
149 Queue::LinkTo(Queue
*other
)
157 fQueueHead
->link_phy
= other
->fQueueHead
->this_phy
| QH_NEXT_IS_QH
;
158 fQueueHead
->link_log
= other
->fQueueHead
;
166 Queue::TerminateByStrayDescriptor()
168 // According to the *BSD USB sources, there needs to be a stray transfer
169 // descriptor in order to get some chipset to work nicely (like the PIIX).
170 phys_addr_t physicalAddress
;
171 status_t result
= fStack
->AllocateChunk((void **)&fStrayDescriptor
,
172 &physicalAddress
, sizeof(uhci_td
));
174 TRACE_ERROR("failed to allocate a stray transfer descriptor\n");
178 fStrayDescriptor
->status
= 0;
179 fStrayDescriptor
->this_phy
= (uint32
)physicalAddress
;
180 fStrayDescriptor
->link_phy
= TD_TERMINATE
;
181 fStrayDescriptor
->link_log
= NULL
;
182 fStrayDescriptor
->buffer_phy
= 0;
183 fStrayDescriptor
->buffer_log
= NULL
;
184 fStrayDescriptor
->buffer_size
= 0;
185 fStrayDescriptor
->token
= TD_TOKEN_NULL_DATA
186 | (0x7f << TD_TOKEN_DEVADDR_SHIFT
) | TD_TOKEN_IN
;
189 fStack
->FreeChunk(fStrayDescriptor
, fStrayDescriptor
->this_phy
,
194 fQueueHead
->link_phy
= fStrayDescriptor
->this_phy
;
195 fQueueHead
->link_log
= fStrayDescriptor
;
203 Queue::AppendTransfer(uhci_qh
*transfer
, bool lock
)
208 transfer
->link_log
= NULL
;
209 transfer
->link_phy
= fQueueHead
->link_phy
;
212 // the list is empty, make this the first element
213 fQueueTop
= transfer
;
214 fQueueHead
->element_phy
= transfer
->this_phy
| QH_NEXT_IS_QH
;
216 // append the transfer queue to the list
217 uhci_qh
*element
= fQueueTop
;
218 while (element
&& element
->link_log
)
219 element
= (uhci_qh
*)element
->link_log
;
221 element
->link_log
= transfer
;
222 element
->link_phy
= transfer
->this_phy
| QH_NEXT_IS_QH
;
232 Queue::RemoveTransfer(uhci_qh
*transfer
, bool lock
)
237 if (fQueueTop
== transfer
) {
238 // this was the top element
239 fQueueTop
= (uhci_qh
*)transfer
->link_log
;
241 // this was the only element, terminate this queue
242 fQueueHead
->element_phy
= QH_TERMINATE
;
244 // there are elements left, adjust the element pointer
245 fQueueHead
->element_phy
= transfer
->link_phy
;
252 uhci_qh
*element
= fQueueTop
;
254 if (element
->link_log
== transfer
) {
255 element
->link_log
= transfer
->link_log
;
256 element
->link_phy
= transfer
->link_phy
;
262 element
= (uhci_qh
*)element
->link_log
;
273 Queue::PhysicalAddress()
275 return fQueueHead
->this_phy
;
280 Queue::PrintToStream()
284 dprintf("link phy: 0x%08" B_PRIx32
"; link type: %s; terminate: %s\n",
285 fQueueHead
->link_phy
& 0xfff0,
286 fQueueHead
->link_phy
& 0x0002 ? "QH" : "TD",
287 fQueueHead
->link_phy
& 0x0001 ? "yes" : "no");
288 dprintf("elem phy: 0x%08" B_PRIx32
"; elem type: %s; terminate: %s\n",
289 fQueueHead
->element_phy
& 0xfff0,
290 fQueueHead
->element_phy
& 0x0002 ? "QH" : "TD",
291 fQueueHead
->element_phy
& 0x0001 ? "yes" : "no");
301 UHCI::UHCI(pci_info
*info
, Stack
*stack
)
305 fEnabledInterrupts(0),
308 fFrameBandwidth(NULL
),
309 fFirstIsochronousDescriptor(NULL
),
310 fLastIsochronousDescriptor(NULL
),
313 fFirstTransfer(NULL
),
315 fFinishTransfersSem(-1),
318 fProcessingPipe(NULL
),
323 fFirstIsochronousTransfer(NULL
),
324 fLastIsochronousTransfer(NULL
),
325 fFinishIsochronousTransfersSem(-1),
326 fFinishIsochronousThread(-1),
333 // Create a lock for the isochronous transfer list
334 mutex_init(&fIsochronousLock
, "UHCI isochronous lock");
337 TRACE_ERROR("bus manager failed to init\n");
341 TRACE("constructing new UHCI host controller driver\n");
344 fRegisterBase
= sPCIModule
->read_pci_config(fPCIInfo
->bus
,
345 fPCIInfo
->device
, fPCIInfo
->function
, PCI_memory_base
, 4);
346 fRegisterBase
&= PCI_address_io_mask
;
347 TRACE("iospace offset: 0x%08" B_PRIx32
"\n", fRegisterBase
);
349 if (fRegisterBase
== 0) {
350 fRegisterBase
= fPCIInfo
->u
.h0
.base_registers
[0];
351 TRACE_ALWAYS("register base: 0x%08" B_PRIx32
"\n", fRegisterBase
);
354 // enable pci address access
355 uint16 command
= PCI_command_io
| PCI_command_master
| PCI_command_memory
;
356 command
|= sPCIModule
->read_pci_config(fPCIInfo
->bus
, fPCIInfo
->device
,
357 fPCIInfo
->function
, PCI_command
, 2);
359 sPCIModule
->write_pci_config(fPCIInfo
->bus
, fPCIInfo
->device
,
360 fPCIInfo
->function
, PCI_command
, 2, command
);
362 // disable interrupts
363 WriteReg16(UHCI_USBINTR
, 0);
365 // make sure we gain control of the UHCI controller instead of the BIOS
366 sPCIModule
->write_pci_config(fPCIInfo
->bus
, fPCIInfo
->device
,
367 fPCIInfo
->function
, PCI_LEGSUP
, 2, PCI_LEGSUP_USBPIRQDEN
368 | PCI_LEGSUP_CLEAR_SMI
);
370 // do a global and host reset
372 if (ControllerReset() < B_OK
) {
373 TRACE_ERROR("host failed to reset\n");
377 // Setup the frame list
378 phys_addr_t physicalAddress
;
379 fFrameArea
= fStack
->AllocateArea((void **)&fFrameList
, &physicalAddress
,
380 4096, "USB UHCI framelist");
382 if (fFrameArea
< B_OK
) {
383 TRACE_ERROR("unable to create an area for the frame pointer list\n");
387 // Set base pointer and reset frame number
388 WriteReg32(UHCI_FRBASEADD
, (uint32
)physicalAddress
);
389 WriteReg16(UHCI_FRNUM
, 0);
391 // Set the max packet size for bandwidth reclamation to 64 bytes
392 WriteReg16(UHCI_USBCMD
, ReadReg16(UHCI_USBCMD
) | UHCI_USBCMD_MAXP
);
394 // we will create four queues:
395 // 0: interrupt transfers
396 // 1: low speed control transfers
397 // 2: full speed control transfers
400 // TODO: 4: bandwidth reclamation queue
402 fQueues
= new(std::nothrow
) Queue
*[fQueueCount
];
404 delete_area(fFrameArea
);
408 for (int32 i
= 0; i
< fQueueCount
; i
++) {
409 fQueues
[i
] = new(std::nothrow
) Queue(fStack
);
410 if (!fQueues
[i
] || fQueues
[i
]->InitCheck() < B_OK
) {
411 TRACE_ERROR("cannot create queues\n");
412 delete_area(fFrameArea
);
417 fQueues
[i
- 1]->LinkTo(fQueues
[i
]);
420 // Make sure the last queue terminates
421 fQueues
[fQueueCount
- 1]->TerminateByStrayDescriptor();
423 // Create the array that will keep bandwidth information
424 fFrameBandwidth
= new(std::nothrow
) uint16
[NUMBER_OF_FRAMES
];
426 // Create lists for managing isochronous transfer descriptors
427 fFirstIsochronousDescriptor
= new(std::nothrow
) uhci_td
*[NUMBER_OF_FRAMES
];
428 if (!fFirstIsochronousDescriptor
) {
429 TRACE_ERROR("faild to allocate memory for first isochronous descriptor\n");
433 fLastIsochronousDescriptor
= new(std::nothrow
) uhci_td
*[NUMBER_OF_FRAMES
];
434 if (!fLastIsochronousDescriptor
) {
435 TRACE_ERROR("failed to allocate memory for last isochronous descriptor\n");
436 delete [] fFirstIsochronousDescriptor
;
440 for (int32 i
= 0; i
< NUMBER_OF_FRAMES
; i
++) {
441 fFrameList
[i
] = fQueues
[UHCI_INTERRUPT_QUEUE
]->PhysicalAddress()
442 | FRAMELIST_NEXT_IS_QH
;
443 fFrameBandwidth
[i
] = MAX_AVAILABLE_BANDWIDTH
;
444 fFirstIsochronousDescriptor
[i
] = NULL
;
445 fLastIsochronousDescriptor
[i
] = NULL
;
448 // Create semaphore the finisher and cleanup threads will wait for
449 fFinishTransfersSem
= create_sem(0, "UHCI Finish Transfers");
450 if (fFinishTransfersSem
< B_OK
) {
451 TRACE_ERROR("failed to create finisher semaphore\n");
455 fCleanupSem
= create_sem(0, "UHCI Cleanup");
456 if (fCleanupSem
< B_OK
) {
457 TRACE_ERROR("failed to create cleanup semaphore\n");
461 // Create the finisher service and cleanup threads
462 fFinishThread
= spawn_kernel_thread(FinishThread
,
463 "uhci finish thread", B_URGENT_DISPLAY_PRIORITY
, (void *)this);
464 resume_thread(fFinishThread
);
466 fCleanupThread
= spawn_kernel_thread(CleanupThread
,
467 "uhci cleanup thread", B_NORMAL_PRIORITY
, (void *)this);
468 resume_thread(fCleanupThread
);
470 // Create semaphore the isochronous finisher thread will wait for
471 fFinishIsochronousTransfersSem
= create_sem(0,
472 "UHCI Isochronous Finish Transfers");
473 if (fFinishIsochronousTransfersSem
< B_OK
) {
474 TRACE_ERROR("failed to create isochronous finisher semaphore\n");
478 // Create the isochronous finisher service thread
479 fFinishIsochronousThread
= spawn_kernel_thread(FinishIsochronousThread
,
480 "uhci isochronous finish thread", B_URGENT_DISPLAY_PRIORITY
,
482 resume_thread(fFinishIsochronousThread
);
484 // Find the right interrupt vector, using MSIs if available.
485 fIRQ
= fPCIInfo
->u
.h0
.interrupt_line
;
486 if (sPCIx86Module
!= NULL
&& sPCIx86Module
->get_msi_count(fPCIInfo
->bus
,
487 fPCIInfo
->device
, fPCIInfo
->function
) >= 1) {
489 if (sPCIx86Module
->configure_msi(fPCIInfo
->bus
, fPCIInfo
->device
,
490 fPCIInfo
->function
, 1, &msiVector
) == B_OK
491 && sPCIx86Module
->enable_msi(fPCIInfo
->bus
, fPCIInfo
->device
,
492 fPCIInfo
->function
) == B_OK
) {
493 TRACE_ALWAYS("using message signaled interrupts\n");
499 // Install the interrupt handler
500 TRACE("installing interrupt handler\n");
501 install_io_interrupt_handler(fIRQ
, InterruptHandler
, (void *)this, 0);
504 fEnabledInterrupts
= UHCI_USBSTS_USBINT
| UHCI_USBSTS_ERRINT
505 | UHCI_USBSTS_HOSTERR
| UHCI_USBSTS_HCPRERR
| UHCI_USBSTS_HCHALT
;
506 WriteReg16(UHCI_USBINTR
, UHCI_USBINTR_CRC
| UHCI_USBINTR_IOC
507 | UHCI_USBINTR_SHORT
);
509 TRACE("UHCI host controller driver constructed\n");
518 delete_sem(fFinishTransfersSem
);
519 delete_sem(fCleanupSem
);
520 delete_sem(fFinishIsochronousTransfersSem
);
521 wait_for_thread(fFinishThread
, &result
);
522 wait_for_thread(fCleanupThread
, &result
);
523 wait_for_thread(fFinishIsochronousThread
, &result
);
525 remove_io_interrupt_handler(fIRQ
, InterruptHandler
, (void *)this);
528 isochronous_transfer_data
*isoTransfer
= fFirstIsochronousTransfer
;
529 while (isoTransfer
) {
530 isochronous_transfer_data
*next
= isoTransfer
->link
;
534 mutex_destroy(&fIsochronousLock
);
537 transfer_data
*transfer
= fFirstTransfer
;
539 transfer
->transfer
->Finished(B_CANCELED
, 0);
540 delete transfer
->transfer
;
542 transfer_data
*next
= transfer
->link
;
547 for (int32 i
= 0; i
< fQueueCount
; i
++)
551 delete [] fFrameBandwidth
;
552 delete [] fFirstIsochronousDescriptor
;
553 delete [] fLastIsochronousDescriptor
;
555 delete_area(fFrameArea
);
557 if (fUseMSI
&& sPCIx86Module
!= NULL
) {
558 sPCIx86Module
->disable_msi(fPCIInfo
->bus
,
559 fPCIInfo
->device
, fPCIInfo
->function
);
560 sPCIx86Module
->unconfigure_msi(fPCIInfo
->bus
,
561 fPCIInfo
->device
, fPCIInfo
->function
);
563 put_module(B_PCI_MODULE_NAME
);
564 if (sPCIx86Module
!= NULL
) {
565 sPCIx86Module
= NULL
;
566 put_module(B_PCI_X86_MODULE_NAME
);
575 // Start the host controller, then start the Busmanager
576 TRACE("starting UHCI BusManager\n");
577 TRACE("usbcmd reg 0x%04x, usbsts reg 0x%04x\n",
578 ReadReg16(UHCI_USBCMD
), ReadReg16(UHCI_USBSTS
));
580 // Set the run bit in the command register
581 WriteReg16(UHCI_USBCMD
, ReadReg16(UHCI_USBCMD
) | UHCI_USBCMD_RS
);
583 bool running
= false;
584 for (int32 i
= 0; i
< 10; i
++) {
585 uint16 status
= ReadReg16(UHCI_USBSTS
);
586 TRACE("current loop %" B_PRId32
", status 0x%04x\n", i
, status
);
588 if (status
& UHCI_USBSTS_HCHALT
)
597 TRACE_ERROR("controller won't start running\n");
601 fRootHubAddress
= AllocateAddress();
602 fRootHub
= new(std::nothrow
) UHCIRootHub(RootObject(), fRootHubAddress
);
604 TRACE_ERROR("no memory to allocate root hub\n");
608 if (fRootHub
->InitCheck() < B_OK
) {
609 TRACE_ERROR("root hub failed init check\n");
614 SetRootHub(fRootHub
);
616 TRACE("controller is started. status: %u curframe: %u\n",
617 ReadReg16(UHCI_USBSTS
), ReadReg16(UHCI_FRNUM
));
618 TRACE_ALWAYS("successfully started the controller\n");
619 return BusManager::Start();
624 UHCI::SubmitTransfer(Transfer
*transfer
)
626 // Short circuit the root hub
627 Pipe
*pipe
= transfer
->TransferPipe();
628 if (pipe
->DeviceAddress() == fRootHubAddress
)
629 return fRootHub
->ProcessTransfer(this, transfer
);
631 TRACE("submit transfer called for device %d\n", pipe
->DeviceAddress());
632 if (pipe
->Type() & USB_OBJECT_CONTROL_PIPE
)
633 return SubmitRequest(transfer
);
635 // Process isochronous transfers
636 if (pipe
->Type() & USB_OBJECT_ISO_PIPE
)
637 return SubmitIsochronous(transfer
);
639 uhci_td
*firstDescriptor
= NULL
;
640 uhci_qh
*transferQueue
= NULL
;
641 status_t result
= CreateFilledTransfer(transfer
, &firstDescriptor
,
647 if (pipe
->Type() & USB_OBJECT_INTERRUPT_PIPE
)
648 queue
= fQueues
[UHCI_INTERRUPT_QUEUE
];
650 queue
= fQueues
[UHCI_BULK_QUEUE
];
652 bool directionIn
= (pipe
->Direction() == Pipe::In
);
653 result
= AddPendingTransfer(transfer
, queue
, transferQueue
,
654 firstDescriptor
, firstDescriptor
, directionIn
);
656 TRACE_ERROR("failed to add pending transfer\n");
657 FreeDescriptorChain(firstDescriptor
);
658 FreeTransferQueue(transferQueue
);
662 queue
->AppendTransfer(transferQueue
);
668 UHCI::StartDebugTransfer(Transfer
*transfer
)
670 if ((transfer
->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE
) != 0)
671 return B_UNSUPPORTED
;
673 static transfer_data transferData
;
674 transferData
.first_descriptor
= NULL
;
675 transferData
.transfer_queue
= NULL
;
676 status_t result
= CreateFilledTransfer(transfer
,
677 &transferData
.first_descriptor
, &transferData
.transfer_queue
);
681 fQueues
[UHCI_DEBUG_QUEUE
]->AppendTransfer(transferData
.transfer_queue
,
684 // we abuse the callback cookie to hold our transfer data
685 transfer
->SetCallback(NULL
, &transferData
);
691 UHCI::CheckDebugTransfer(Transfer
*transfer
)
693 bool transferOK
= false;
694 bool transferError
= false;
695 transfer_data
*transferData
= (transfer_data
*)transfer
->CallbackCookie();
696 uhci_td
*descriptor
= transferData
->first_descriptor
;
699 uint32 status
= descriptor
->status
;
700 if (status
& TD_STATUS_ACTIVE
)
703 if (status
& TD_ERROR_MASK
) {
704 transferError
= true;
708 if ((descriptor
->link_phy
& TD_TERMINATE
)
709 || uhci_td_actual_length(descriptor
)
710 < uhci_td_maximum_length(descriptor
)) {
715 descriptor
= (uhci_td
*)descriptor
->link_log
;
718 if (!transferOK
&& !transferError
) {
720 return B_DEV_PENDING
;
724 uint8 lastDataToggle
= 0;
725 if (transfer
->TransferPipe()->Direction() == Pipe::In
) {
727 iovec
*vector
= transfer
->Vector();
728 size_t vectorCount
= transfer
->VectorCount();
730 ReadDescriptorChain(transferData
->first_descriptor
,
731 vector
, vectorCount
, &lastDataToggle
);
733 // read the actual length that was sent
734 ReadActualLength(transferData
->first_descriptor
, &lastDataToggle
);
737 transfer
->TransferPipe()->SetDataToggle(lastDataToggle
== 0);
740 fQueues
[UHCI_DEBUG_QUEUE
]->RemoveTransfer(transferData
->transfer_queue
,
742 FreeDescriptorChain(transferData
->first_descriptor
);
743 FreeTransferQueue(transferData
->transfer_queue
);
744 return transferOK
? B_OK
: B_IO_ERROR
;
749 UHCI::CancelDebugTransfer(Transfer
*transfer
)
751 transfer_data
*transferData
= (transfer_data
*)transfer
->CallbackCookie();
753 // clear the active bit so the descriptors are canceled
754 uhci_td
*descriptor
= transferData
->first_descriptor
;
756 descriptor
->status
&= ~TD_STATUS_ACTIVE
;
757 descriptor
= (uhci_td
*)descriptor
->link_log
;
760 transfer
->Finished(B_CANCELED
, 0);
762 // dequeue and free resources
763 fQueues
[UHCI_DEBUG_QUEUE
]->RemoveTransfer(transferData
->transfer_queue
,
765 FreeDescriptorChain(transferData
->first_descriptor
);
766 FreeTransferQueue(transferData
->transfer_queue
);
767 // TODO: [bonefish] The Free*() calls cause "PMA: provided address resulted
768 // in invalid index" to be printed, so apparently something is not right.
769 // Though I have not clue what. This is the same cleanup code as in
770 // CheckDebugTransfer() that should undo the CreateFilledTransfer() from
771 // StartDebugTransfer().
776 UHCI::CancelQueuedTransfers(Pipe
*pipe
, bool force
)
778 if (pipe
->Type() & USB_OBJECT_ISO_PIPE
)
779 return CancelQueuedIsochronousTransfers(pipe
, force
);
784 struct transfer_entry
{
786 transfer_entry
* next
;
789 transfer_entry
*list
= NULL
;
790 transfer_data
*current
= fFirstTransfer
;
792 if (current
->transfer
&& current
->transfer
->TransferPipe() == pipe
) {
793 // clear the active bit so the descriptors are canceled
794 uhci_td
*descriptor
= current
->first_descriptor
;
796 descriptor
->status
&= ~TD_STATUS_ACTIVE
;
797 descriptor
= (uhci_td
*)descriptor
->link_log
;
801 // if the transfer is canceled by force, the one causing the
802 // cancel is probably not the one who initiated the transfer
803 // and the callback is likely not safe anymore
804 transfer_entry
*entry
805 = (transfer_entry
*)malloc(sizeof(transfer_entry
));
807 entry
->transfer
= current
->transfer
;
808 current
->transfer
= NULL
;
814 current
->canceled
= true;
816 current
= current
->link
;
821 while (list
!= NULL
) {
822 transfer_entry
*next
= list
->next
;
823 list
->transfer
->Finished(B_CANCELED
, 0);
824 delete list
->transfer
;
829 // wait for any transfers that might have made it before canceling
830 while (fProcessingPipe
== pipe
)
833 // notify the finisher so it can clean up the canceled transfers
834 release_sem_etc(fFinishTransfersSem
, 1, B_DO_NOT_RESCHEDULE
);
840 UHCI::CancelQueuedIsochronousTransfers(Pipe
*pipe
, bool force
)
842 isochronous_transfer_data
*current
= fFirstIsochronousTransfer
;
845 if (current
->transfer
->TransferPipe() == pipe
) {
847 = current
->transfer
->IsochronousData()->packet_count
;
848 // Set the active bit off on every descriptor in order to prevent
849 // the controller from processing them. Then set off the is_active
850 // field of the transfer in order to make the finisher thread skip
851 // the transfer. The FinishIsochronousThread will do the rest.
852 for (int32 i
= 0; i
< packetCount
; i
++)
853 current
->descriptors
[i
]->status
&= ~TD_STATUS_ACTIVE
;
855 // TODO: Use the force paramater in order to avoid calling
857 current
->is_active
= false;
860 current
= current
->link
;
863 TRACE_ERROR("no isochronous transfer found!\n");
869 UHCI::SubmitRequest(Transfer
*transfer
)
871 Pipe
*pipe
= transfer
->TransferPipe();
872 usb_request_data
*requestData
= transfer
->RequestData();
873 bool directionIn
= (requestData
->RequestType
& USB_REQTYPE_DEVICE_IN
) > 0;
875 uhci_td
*setupDescriptor
= CreateDescriptor(pipe
, TD_TOKEN_SETUP
,
876 sizeof(usb_request_data
));
878 uhci_td
*statusDescriptor
= CreateDescriptor(pipe
,
879 directionIn
? TD_TOKEN_OUT
: TD_TOKEN_IN
, 0);
881 if (!setupDescriptor
|| !statusDescriptor
) {
882 TRACE_ERROR("failed to allocate descriptors\n");
883 FreeDescriptor(setupDescriptor
);
884 FreeDescriptor(statusDescriptor
);
889 vector
.iov_base
= requestData
;
890 vector
.iov_len
= sizeof(usb_request_data
);
891 WriteDescriptorChain(setupDescriptor
, &vector
, 1);
893 statusDescriptor
->status
|= TD_CONTROL_IOC
;
894 statusDescriptor
->token
|= TD_TOKEN_DATA1
;
895 statusDescriptor
->link_phy
= TD_TERMINATE
;
896 statusDescriptor
->link_log
= NULL
;
898 uhci_td
*dataDescriptor
= NULL
;
899 if (transfer
->VectorCount() > 0) {
900 uhci_td
*lastDescriptor
= NULL
;
901 status_t result
= CreateDescriptorChain(pipe
, &dataDescriptor
,
902 &lastDescriptor
, directionIn
? TD_TOKEN_IN
: TD_TOKEN_OUT
,
903 transfer
->VectorLength());
906 FreeDescriptor(setupDescriptor
);
907 FreeDescriptor(statusDescriptor
);
912 WriteDescriptorChain(dataDescriptor
, transfer
->Vector(),
913 transfer
->VectorCount());
916 LinkDescriptors(setupDescriptor
, dataDescriptor
);
917 LinkDescriptors(lastDescriptor
, statusDescriptor
);
919 // Link transfer and status descriptors directly
920 LinkDescriptors(setupDescriptor
, statusDescriptor
);
924 if (pipe
->Speed() == USB_SPEED_LOWSPEED
)
925 queue
= fQueues
[UHCI_LOW_SPEED_CONTROL_QUEUE
];
927 queue
= fQueues
[UHCI_FULL_SPEED_CONTROL_QUEUE
];
929 uhci_qh
*transferQueue
= CreateTransferQueue(setupDescriptor
);
930 status_t result
= AddPendingTransfer(transfer
, queue
, transferQueue
,
931 setupDescriptor
, dataDescriptor
, directionIn
);
933 TRACE_ERROR("failed to add pending transfer\n");
934 FreeDescriptorChain(setupDescriptor
);
935 FreeTransferQueue(transferQueue
);
939 queue
->AppendTransfer(transferQueue
);
945 UHCI::AddPendingTransfer(Transfer
*transfer
, Queue
*queue
,
946 uhci_qh
*transferQueue
, uhci_td
*firstDescriptor
, uhci_td
*dataDescriptor
,
949 if (!transfer
|| !queue
|| !transferQueue
|| !firstDescriptor
)
952 transfer_data
*data
= new(std::nothrow
) transfer_data
;
956 status_t result
= transfer
->InitKernelAccess();
962 data
->transfer
= transfer
;
964 data
->transfer_queue
= transferQueue
;
965 data
->first_descriptor
= firstDescriptor
;
966 data
->data_descriptor
= dataDescriptor
;
967 data
->incoming
= directionIn
;
968 data
->canceled
= false;
977 fLastTransfer
->link
= data
;
979 fFirstTransfer
= data
;
981 fLastTransfer
= data
;
988 UHCI::AddPendingIsochronousTransfer(Transfer
*transfer
, uhci_td
**isoRequest
,
991 if (!transfer
|| !isoRequest
)
994 isochronous_transfer_data
*data
995 = new(std::nothrow
) isochronous_transfer_data
;
999 status_t result
= transfer
->InitKernelAccess();
1000 if (result
< B_OK
) {
1005 data
->transfer
= transfer
;
1006 data
->descriptors
= isoRequest
;
1007 data
->last_to_process
= transfer
->IsochronousData()->packet_count
- 1;
1008 data
->incoming
= directionIn
;
1009 data
->is_active
= true;
1012 // Put in the isochronous transfer list
1013 if (!LockIsochronous()) {
1018 if (fLastIsochronousTransfer
)
1019 fLastIsochronousTransfer
->link
= data
;
1020 if (!fFirstIsochronousTransfer
)
1021 fFirstIsochronousTransfer
= data
;
1023 fLastIsochronousTransfer
= data
;
1024 UnlockIsochronous();
1030 UHCI::SubmitIsochronous(Transfer
*transfer
)
1032 Pipe
*pipe
= transfer
->TransferPipe();
1033 bool directionIn
= (pipe
->Direction() == Pipe::In
);
1034 usb_isochronous_data
*isochronousData
= transfer
->IsochronousData();
1035 size_t packetSize
= transfer
->DataLength();
1036 size_t restSize
= packetSize
% isochronousData
->packet_count
;
1037 packetSize
/= isochronousData
->packet_count
;
1038 uint16 currentFrame
;
1040 if (packetSize
> pipe
->MaxPacketSize()) {
1041 TRACE_ERROR("isochronous packetSize is bigger than pipe MaxPacketSize\n");
1045 // Ignore the fact that the last descriptor might need less bandwidth.
1046 // The overhead is not worthy.
1047 uint16 bandwidth
= transfer
->Bandwidth() / isochronousData
->packet_count
;
1049 TRACE("isochronous transfer descriptor bandwidth %d\n", bandwidth
);
1051 // The following holds the list of transfer descriptor of the
1052 // isochronous request. It is used to quickly remove all the isochronous
1053 // descriptors from the frame list, as descriptors are not link to each
1054 // other in a queue like for every other transfer.
1055 uhci_td
**isoRequest
1056 = new(std::nothrow
) uhci_td
*[isochronousData
->packet_count
];
1057 if (isoRequest
== NULL
) {
1058 TRACE("failed to create isoRequest array!\n");
1062 // Create the list of transfer descriptors
1063 for (uint32 i
= 0; i
< (isochronousData
->packet_count
- 1); i
++) {
1064 isoRequest
[i
] = CreateDescriptor(pipe
,
1065 directionIn
? TD_TOKEN_IN
: TD_TOKEN_OUT
, packetSize
);
1066 // If we ran out of memory, clean up and return
1067 if (isoRequest
[i
] == NULL
) {
1068 for (uint32 j
= 0; j
< i
; j
++)
1069 FreeDescriptor(isoRequest
[j
]);
1070 delete [] isoRequest
;
1073 // Make sure data toggle is set to zero
1074 isoRequest
[i
]->token
&= ~TD_TOKEN_DATA1
;
1077 // Create the last transfer descriptor which should be of smaller size
1078 // and set the IOC bit
1079 isoRequest
[isochronousData
->packet_count
- 1] = CreateDescriptor(pipe
,
1080 directionIn
? TD_TOKEN_IN
: TD_TOKEN_OUT
,
1081 (restSize
) ? restSize
: packetSize
);
1082 // If we are that unlucky...
1083 if (!isoRequest
[isochronousData
->packet_count
- 1]) {
1084 for (uint32 i
= 0; i
< (isochronousData
->packet_count
- 2); i
++)
1085 FreeDescriptor(isoRequest
[i
]);
1086 delete [] isoRequest
;
1089 isoRequest
[isochronousData
->packet_count
- 1]->token
&= ~TD_TOKEN_DATA1
;
1091 // If direction is out set every descriptor data
1093 iovec
*vector
= transfer
->Vector();
1094 WriteIsochronousDescriptorChain(isoRequest
,
1095 isochronousData
->packet_count
, vector
);
1097 // Initialize the packet descriptors
1098 for (uint32 i
= 0; i
< isochronousData
->packet_count
; i
++) {
1099 isochronousData
->packet_descriptors
[i
].actual_length
= 0;
1100 isochronousData
->packet_descriptors
[i
].status
= B_NO_INIT
;
1104 TRACE("isochronous submitted size=%ld bytes, TDs=%" B_PRId32
", "
1105 "packetSize=%ld, restSize=%ld\n", transfer
->DataLength(),
1106 isochronousData
->packet_count
, packetSize
, restSize
);
1108 // Find the entry where to start inserting the first Isochronous descriptor
1109 if (isochronousData
->flags
& USB_ISO_ASAP
||
1110 isochronousData
->starting_frame_number
== NULL
) {
1111 // find the first available frame with enough bandwidth.
1112 // This should always be the case, as defining the starting frame
1113 // number in the driver makes no sense for many reason, one of which
1114 // is that frame numbers value are host controller specific, and the
1115 // driver does not know which host controller is running.
1116 currentFrame
= ReadReg16(UHCI_FRNUM
);
1119 // 1. We are at least 5ms ahead the controller
1120 // 2. We stay in the range 0-1023
1121 // 3. There is enough bandwidth in the first entry
1122 currentFrame
= (currentFrame
+ 5) % NUMBER_OF_FRAMES
;
1124 // Find out if the frame number specified has enough bandwidth,
1125 // otherwise find the first next available frame with enough bandwidth
1126 currentFrame
= *isochronousData
->starting_frame_number
;
1129 // Find the first entry with enough bandwidth
1130 // TODO: should we also check the bandwidth of the following packet_count frames?
1131 uint16 startSeekingFromFrame
= currentFrame
;
1132 while (fFrameBandwidth
[currentFrame
] < bandwidth
) {
1133 currentFrame
= (currentFrame
+ 1) % NUMBER_OF_FRAMES
;
1134 if (currentFrame
== startSeekingFromFrame
) {
1135 TRACE_ERROR("not enough bandwidth to queue the isochronous request");
1136 for (uint32 i
= 0; i
< isochronousData
->packet_count
; i
++)
1137 FreeDescriptor(isoRequest
[i
]);
1138 delete [] isoRequest
;
1143 if (isochronousData
->starting_frame_number
)
1144 *isochronousData
->starting_frame_number
= currentFrame
;
1146 // Add transfer to the list
1147 status_t result
= AddPendingIsochronousTransfer(transfer
, isoRequest
,
1149 if (result
< B_OK
) {
1150 TRACE_ERROR("failed to add pending isochronous transfer\n");
1151 for (uint32 i
= 0; i
< isochronousData
->packet_count
; i
++)
1152 FreeDescriptor(isoRequest
[i
]);
1153 delete [] isoRequest
;
1157 TRACE("appended isochronous transfer by starting at frame number %d\n",
1160 // Insert the Transfer Descriptor by starting at
1161 // the starting_frame_number entry
1162 // TODO: We don't consider bInterval, and assume it's 1!
1163 for (uint32 i
= 0; i
< isochronousData
->packet_count
; i
++) {
1164 result
= LinkIsochronousDescriptor(isoRequest
[i
], currentFrame
);
1165 if (result
< B_OK
) {
1166 TRACE_ERROR("failed to add pending isochronous transfer\n");
1167 for (uint32 i
= 0; i
< isochronousData
->packet_count
; i
++)
1168 FreeDescriptor(isoRequest
[i
]);
1169 delete [] isoRequest
;
1173 fFrameBandwidth
[currentFrame
] -= bandwidth
;
1174 currentFrame
= (currentFrame
+ 1) % NUMBER_OF_FRAMES
;
1177 // Wake up the isochronous finisher thread
1178 release_sem_etc(fFinishIsochronousTransfersSem
, 1, B_DO_NOT_RESCHEDULE
);
1184 isochronous_transfer_data
*
1185 UHCI::FindIsochronousTransfer(uhci_td
*descriptor
)
1187 // Simply check every last descriptor of the isochronous transfer list
1188 if (LockIsochronous()) {
1189 isochronous_transfer_data
*transfer
= fFirstIsochronousTransfer
;
1191 while (transfer
->descriptors
[transfer
->last_to_process
]
1193 transfer
= transfer
->link
;
1198 UnlockIsochronous();
1206 UHCI::LinkIsochronousDescriptor(uhci_td
*descriptor
, uint16 frame
)
1208 // The transfer descriptor is appended to the last
1209 // existing isochronous transfer descriptor (if any)
1211 if (LockIsochronous()) {
1212 if (!fFirstIsochronousDescriptor
[frame
]) {
1213 // Insert the transfer descriptor in the first position
1214 fFrameList
[frame
] = descriptor
->this_phy
& ~FRAMELIST_NEXT_IS_QH
;
1215 fFirstIsochronousDescriptor
[frame
] = descriptor
;
1216 fLastIsochronousDescriptor
[frame
] = descriptor
;
1218 // Append to the last transfer descriptor
1219 fLastIsochronousDescriptor
[frame
]->link_log
= descriptor
;
1220 fLastIsochronousDescriptor
[frame
]->link_phy
1221 = descriptor
->this_phy
& ~TD_NEXT_IS_QH
;
1222 fLastIsochronousDescriptor
[frame
] = descriptor
;
1225 descriptor
->link_phy
1226 = fQueues
[UHCI_INTERRUPT_QUEUE
]->PhysicalAddress() | TD_NEXT_IS_QH
;
1227 UnlockIsochronous();
1235 UHCI::UnlinkIsochronousDescriptor(uint16 frame
)
1237 // We always unlink from the top
1238 if (LockIsochronous()) {
1239 uhci_td
*descriptor
= fFirstIsochronousDescriptor
[frame
];
1241 // The descriptor will be freed later.
1242 fFrameList
[frame
] = descriptor
->link_phy
;
1243 if (descriptor
->link_log
) {
1244 fFirstIsochronousDescriptor
[frame
]
1245 = (uhci_td
*)descriptor
->link_log
;
1247 fFirstIsochronousDescriptor
[frame
] = NULL
;
1248 fLastIsochronousDescriptor
[frame
] = NULL
;
1251 UnlockIsochronous();
1259 UHCI::FinishThread(void *data
)
1261 ((UHCI
*)data
)->FinishTransfers();
1267 UHCI::FinishTransfers()
1269 while (!fStopThreads
) {
1270 if (acquire_sem(fFinishTransfersSem
) < B_OK
)
1273 // eat up sems that have been released by multiple interrupts
1275 get_sem_count(fFinishTransfersSem
, &semCount
);
1277 acquire_sem_etc(fFinishTransfersSem
, semCount
, B_RELATIVE_TIMEOUT
, 0);
1282 TRACE("finishing transfers (first transfer: 0x%08lx; last"
1283 " transfer: 0x%08lx)\n", (addr_t
)fFirstTransfer
,
1284 (addr_t
)fLastTransfer
);
1285 transfer_data
*lastTransfer
= NULL
;
1286 transfer_data
*transfer
= fFirstTransfer
;
1290 bool transferDone
= false;
1291 uhci_td
*descriptor
= transfer
->first_descriptor
;
1292 status_t callbackStatus
= B_OK
;
1294 while (descriptor
) {
1295 uint32 status
= descriptor
->status
;
1296 if (status
& TD_STATUS_ACTIVE
) {
1297 // still in progress
1298 TRACE("td (0x%08" B_PRIx32
") still active\n",
1299 descriptor
->this_phy
);
1303 if (status
& TD_ERROR_MASK
) {
1305 TRACE_ERROR("td (0x%08" B_PRIx32
") error: status: 0x%08"
1306 B_PRIx32
"; token: 0x%08" B_PRIx32
";\n",
1307 descriptor
->this_phy
, status
, descriptor
->token
);
1309 uint8 errorCount
= status
>> TD_ERROR_COUNT_SHIFT
;
1310 errorCount
&= TD_ERROR_COUNT_MASK
;
1311 if (errorCount
== 0) {
1312 // the error counter counted down to zero, report why
1314 if (status
& TD_STATUS_ERROR_BUFFER
) {
1315 callbackStatus
= transfer
->incoming
? B_DEV_DATA_OVERRUN
: B_DEV_DATA_UNDERRUN
;
1318 if (status
& TD_STATUS_ERROR_TIMEOUT
) {
1319 callbackStatus
= transfer
->incoming
? B_DEV_CRC_ERROR
: B_TIMED_OUT
;
1322 if (status
& TD_STATUS_ERROR_NAK
) {
1323 callbackStatus
= B_DEV_UNEXPECTED_PID
;
1326 if (status
& TD_STATUS_ERROR_BITSTUFF
) {
1327 callbackStatus
= B_DEV_CRC_ERROR
;
1332 callbackStatus
= B_DEV_MULTIPLE_ERRORS
;
1333 } else if (status
& TD_STATUS_ERROR_BABBLE
) {
1334 // there is a babble condition
1335 callbackStatus
= transfer
->incoming
? B_DEV_FIFO_OVERRUN
: B_DEV_FIFO_UNDERRUN
;
1337 // if the error counter didn't count down to zero
1338 // and there was no babble, then this halt was caused
1339 // by a stall handshake
1340 callbackStatus
= B_DEV_STALLED
;
1343 transferDone
= true;
1347 if ((descriptor
->link_phy
& TD_TERMINATE
)
1348 || ((descriptor
->status
& TD_CONTROL_SPD
) != 0
1349 && uhci_td_actual_length(descriptor
)
1350 < uhci_td_maximum_length(descriptor
))) {
1351 // all descriptors are done, or we have a short packet
1352 TRACE("td (0x%08" B_PRIx32
") ok\n", descriptor
->this_phy
);
1353 callbackStatus
= B_OK
;
1354 transferDone
= true;
1358 descriptor
= (uhci_td
*)descriptor
->link_log
;
1361 if (!transferDone
) {
1362 lastTransfer
= transfer
;
1363 transfer
= transfer
->link
;
1367 // remove the transfer from the list first so we are sure
1368 // it doesn't get canceled while we still process it
1369 transfer_data
*next
= transfer
->link
;
1372 lastTransfer
->link
= transfer
->link
;
1374 if (transfer
== fFirstTransfer
)
1375 fFirstTransfer
= transfer
->link
;
1376 if (transfer
== fLastTransfer
)
1377 fLastTransfer
= lastTransfer
;
1379 // store the currently processing pipe here so we can wait
1380 // in cancel if we are processing something on the target pipe
1381 if (!transfer
->canceled
)
1382 fProcessingPipe
= transfer
->transfer
->TransferPipe();
1384 transfer
->link
= NULL
;
1388 // if canceled the callback has already been called
1389 if (!transfer
->canceled
) {
1390 size_t actualLength
= 0;
1391 if (callbackStatus
== B_OK
) {
1392 uint8 lastDataToggle
= 0;
1393 if (transfer
->data_descriptor
&& transfer
->incoming
) {
1395 iovec
*vector
= transfer
->transfer
->Vector();
1396 size_t vectorCount
= transfer
->transfer
->VectorCount();
1398 transfer
->transfer
->PrepareKernelAccess();
1399 actualLength
= ReadDescriptorChain(
1400 transfer
->data_descriptor
,
1401 vector
, vectorCount
,
1403 } else if (transfer
->data_descriptor
) {
1404 // read the actual length that was sent
1405 actualLength
= ReadActualLength(
1406 transfer
->data_descriptor
, &lastDataToggle
);
1409 transfer
->transfer
->TransferPipe()->SetDataToggle(lastDataToggle
== 0);
1411 if (transfer
->transfer
->IsFragmented()) {
1412 // this transfer may still have data left
1413 TRACE("advancing fragmented transfer\n");
1414 transfer
->transfer
->AdvanceByFragment(actualLength
);
1415 if (transfer
->transfer
->VectorLength() > 0) {
1416 TRACE("still %ld bytes left on transfer\n",
1417 transfer
->transfer
->VectorLength());
1419 Transfer
*resubmit
= transfer
->transfer
;
1421 // free the used descriptors
1422 transfer
->queue
->RemoveTransfer(
1423 transfer
->transfer_queue
);
1424 AddToFreeList(transfer
);
1426 // resubmit the advanced transfer so the rest
1427 // of the buffers are transmitted over the bus
1428 resubmit
->PrepareKernelAccess();
1429 if (SubmitTransfer(resubmit
) != B_OK
)
1430 resubmit
->Finished(B_ERROR
, 0);
1436 // the transfer is done, but we already set the
1437 // actualLength with AdvanceByFragment()
1442 transfer
->transfer
->Finished(callbackStatus
, actualLength
);
1443 fProcessingPipe
= NULL
;
1446 // remove and free the hardware queue and its descriptors
1447 transfer
->queue
->RemoveTransfer(transfer
->transfer_queue
);
1448 delete transfer
->transfer
;
1449 AddToFreeList(transfer
);
1457 UHCI::AddToFreeList(transfer_data
*transfer
)
1459 transfer
->free_after_frame
= ReadReg16(UHCI_FRNUM
);
1463 transfer
->link
= fFreeList
;
1464 fFreeList
= transfer
;
1467 if (atomic_add(&fCleanupCount
, 1) == 0)
1468 release_sem(fCleanupSem
);
1473 UHCI::CleanupThread(void *data
)
1475 ((UHCI
*)data
)->Cleanup();
1483 while (!fStopThreads
) {
1484 if (acquire_sem(fCleanupSem
) != B_OK
)
1487 bigtime_t nextTime
= system_time() + 1000;
1488 while (atomic_get(&fCleanupCount
) != 0) {
1489 // wait for the frame to pass
1490 snooze_until(nextTime
, B_SYSTEM_TIMEBASE
);
1496 // find the first entry we may free
1497 transfer_data
**link
= &fFreeList
;
1498 transfer_data
*transfer
= fFreeList
;
1499 uint16 frameNumber
= ReadReg16(UHCI_FRNUM
);
1501 if (transfer
->free_after_frame
!= frameNumber
) {
1506 link
= &transfer
->link
;
1507 transfer
= transfer
->link
;
1512 // the transfers below this one are all freeable
1514 transfer_data
*next
= transfer
->link
;
1515 FreeDescriptorChain(transfer
->first_descriptor
);
1516 FreeTransferQueue(transfer
->transfer_queue
);
1518 atomic_add(&fCleanupCount
, -1);
1527 UHCI::FinishIsochronousThread(void *data
)
1529 ((UHCI
*)data
)->FinishIsochronousTransfers();
1535 UHCI::FinishIsochronousTransfers()
1537 /* This thread stays one position behind the controller and processes every
1538 * isochronous descriptor. Once it finds the last isochronous descriptor
1539 * of a transfer, it processes the entire transfer.
1542 while (!fStopThreads
) {
1543 // Go to sleep if there are not isochronous transfer to process
1544 if (acquire_sem(fFinishIsochronousTransfersSem
) < B_OK
)
1547 bool transferDone
= false;
1548 uint16 currentFrame
= ReadReg16(UHCI_FRNUM
);
1550 // Process the frame list until one transfer is processed
1551 while (!transferDone
) {
1552 // wait 1ms in order to be sure to be one position behind
1554 if (currentFrame
== ReadReg16(UHCI_FRNUM
))
1557 // Process the frame till it has isochronous descriptors in it.
1558 while (!(fFrameList
[currentFrame
] & FRAMELIST_NEXT_IS_QH
)) {
1559 uhci_td
*current
= UnlinkIsochronousDescriptor(currentFrame
);
1561 // Process the transfer if we found the last descriptor
1562 isochronous_transfer_data
*transfer
1563 = FindIsochronousTransfer(current
);
1564 // Process the descriptors only if it is still active and
1565 // belongs to an inbound transfer. If the transfer is not
1566 // active, it means the request has been removed, so simply
1567 // remove the descriptors.
1568 if (transfer
&& transfer
->is_active
) {
1569 if (current
->token
& TD_TOKEN_IN
) {
1570 iovec
*vector
= transfer
->transfer
->Vector();
1571 transfer
->transfer
->PrepareKernelAccess();
1572 ReadIsochronousDescriptorChain(transfer
, vector
);
1575 // Remove the transfer
1576 if (LockIsochronous()) {
1577 if (transfer
== fFirstIsochronousTransfer
) {
1578 fFirstIsochronousTransfer
= transfer
->link
;
1579 if (transfer
== fLastIsochronousTransfer
)
1580 fLastIsochronousTransfer
= NULL
;
1582 isochronous_transfer_data
*temp
1583 = fFirstIsochronousTransfer
;
1584 while (transfer
!= temp
->link
)
1587 if (transfer
== fLastIsochronousTransfer
)
1588 fLastIsochronousTransfer
= temp
;
1589 temp
->link
= temp
->link
->link
;
1591 UnlockIsochronous();
1594 transfer
->transfer
->Finished(B_OK
, 0);
1596 uint32 packetCount
=
1597 transfer
->transfer
->IsochronousData()->packet_count
;
1598 for (uint32 i
= 0; i
< packetCount
; i
++)
1599 FreeDescriptor(transfer
->descriptors
[i
]);
1601 delete [] transfer
->descriptors
;
1602 delete transfer
->transfer
;
1604 transferDone
= true;
1608 // Make sure to reset the frame bandwidth
1609 fFrameBandwidth
[currentFrame
] = MAX_AVAILABLE_BANDWIDTH
;
1610 currentFrame
= (currentFrame
+ 1) % NUMBER_OF_FRAMES
;
1619 uint8 sofValue
= ReadReg8(UHCI_SOFMOD
);
1621 WriteReg16(UHCI_USBCMD
, UHCI_USBCMD_GRESET
);
1623 WriteReg16(UHCI_USBCMD
, 0);
1626 WriteReg8(UHCI_SOFMOD
, sofValue
);
1631 UHCI::ControllerReset()
1633 WriteReg16(UHCI_USBCMD
, UHCI_USBCMD_HCRESET
);
1636 while (ReadReg16(UHCI_USBCMD
) & UHCI_USBCMD_HCRESET
) {
1647 UHCI::GetPortStatus(uint8 index
, usb_port_status
*status
)
1652 status
->status
= status
->change
= 0;
1653 uint16 portStatus
= ReadReg16(UHCI_PORTSC1
+ index
* 2);
1656 if (portStatus
& UHCI_PORTSC_CURSTAT
)
1657 status
->status
|= PORT_STATUS_CONNECTION
;
1658 if (portStatus
& UHCI_PORTSC_ENABLED
)
1659 status
->status
|= PORT_STATUS_ENABLE
;
1660 if (portStatus
& UHCI_PORTSC_RESET
)
1661 status
->status
|= PORT_STATUS_RESET
;
1662 if (portStatus
& UHCI_PORTSC_LOWSPEED
)
1663 status
->status
|= PORT_STATUS_LOW_SPEED
;
1666 if (portStatus
& UHCI_PORTSC_STATCHA
)
1667 status
->change
|= PORT_STATUS_CONNECTION
;
1668 if (portStatus
& UHCI_PORTSC_ENABCHA
)
1669 status
->change
|= PORT_STATUS_ENABLE
;
1671 // ToDo: work out suspended/resume
1673 // there are no bits to indicate reset change
1674 if (fPortResetChange
& (1 << index
))
1675 status
->change
|= PORT_STATUS_RESET
;
1677 // the port is automagically powered on
1678 status
->status
|= PORT_STATUS_POWER
;
1684 UHCI::SetPortFeature(uint8 index
, uint16 feature
)
1691 return ResetPort(index
);
1694 // the ports are automatically powered
1703 UHCI::ClearPortFeature(uint8 index
, uint16 feature
)
1708 uint32 portRegister
= UHCI_PORTSC1
+ index
* 2;
1709 uint16 portStatus
= ReadReg16(portRegister
) & UHCI_PORTSC_DATAMASK
;
1713 fPortResetChange
&= ~(1 << index
);
1716 case C_PORT_CONNECTION
:
1717 WriteReg16(portRegister
, portStatus
| UHCI_PORTSC_STATCHA
);
1721 WriteReg16(portRegister
, portStatus
| UHCI_PORTSC_ENABCHA
);
1730 UHCI::ResetPort(uint8 index
)
1735 TRACE("reset port %d\n", index
);
1737 uint32 port
= UHCI_PORTSC1
+ index
* 2;
1738 uint16 status
= ReadReg16(port
);
1739 status
&= UHCI_PORTSC_DATAMASK
;
1740 WriteReg16(port
, status
| UHCI_PORTSC_RESET
);
1743 status
= ReadReg16(port
);
1744 status
&= UHCI_PORTSC_DATAMASK
;
1745 WriteReg16(port
, status
& ~UHCI_PORTSC_RESET
);
1748 for (int32 i
= 10; i
> 0; i
--) {
1749 // try to enable the port
1750 status
= ReadReg16(port
);
1751 status
&= UHCI_PORTSC_DATAMASK
;
1752 WriteReg16(port
, status
| UHCI_PORTSC_ENABLED
);
1755 status
= ReadReg16(port
);
1757 if ((status
& UHCI_PORTSC_CURSTAT
) == 0) {
1758 // no device connected. since we waited long enough we can assume
1759 // that the port was reset and no device is connected.
1763 if (status
& (UHCI_PORTSC_STATCHA
| UHCI_PORTSC_ENABCHA
)) {
1764 // port enabled changed or connection status were set.
1765 // acknowledge either / both and wait again.
1766 status
&= UHCI_PORTSC_DATAMASK
;
1767 WriteReg16(port
, status
| UHCI_PORTSC_STATCHA
| UHCI_PORTSC_ENABCHA
);
1771 if (status
& UHCI_PORTSC_ENABLED
) {
1772 // the port is enabled
1777 fPortResetChange
|= (1 << index
);
1778 TRACE("port was reset: 0x%04x\n", ReadReg16(port
));
1784 UHCI::InterruptHandler(void *data
)
1786 return ((UHCI
*)data
)->Interrupt();
1793 static spinlock lock
= B_SPINLOCK_INITIALIZER
;
1794 acquire_spinlock(&lock
);
1796 // Check if we really had an interrupt
1797 uint16 status
= ReadReg16(UHCI_USBSTS
);
1798 if ((status
& fEnabledInterrupts
) == 0) {
1800 TRACE("discarding not enabled interrupts 0x%08x\n", status
);
1801 WriteReg16(UHCI_USBSTS
, status
);
1804 release_spinlock(&lock
);
1805 return B_UNHANDLED_INTERRUPT
;
1808 uint16 acknowledge
= 0;
1809 bool finishTransfers
= false;
1810 int32 result
= B_HANDLED_INTERRUPT
;
1812 if (status
& UHCI_USBSTS_USBINT
) {
1813 TRACE_MODULE("transfer finished\n");
1814 acknowledge
|= UHCI_USBSTS_USBINT
;
1815 result
= B_INVOKE_SCHEDULER
;
1816 finishTransfers
= true;
1819 if (status
& UHCI_USBSTS_ERRINT
) {
1820 TRACE_MODULE("transfer error\n");
1821 acknowledge
|= UHCI_USBSTS_ERRINT
;
1822 result
= B_INVOKE_SCHEDULER
;
1823 finishTransfers
= true;
1826 if (status
& UHCI_USBSTS_RESDET
) {
1827 TRACE_MODULE("resume detected\n");
1828 acknowledge
|= UHCI_USBSTS_RESDET
;
1831 if (status
& UHCI_USBSTS_HOSTERR
) {
1832 TRACE_MODULE_ERROR("host system error\n");
1833 acknowledge
|= UHCI_USBSTS_HOSTERR
;
1836 if (status
& UHCI_USBSTS_HCPRERR
) {
1837 TRACE_MODULE_ERROR("process error\n");
1838 acknowledge
|= UHCI_USBSTS_HCPRERR
;
1841 if (status
& UHCI_USBSTS_HCHALT
) {
1842 TRACE_MODULE_ERROR("host controller halted\n");
1843 // at least disable interrupts so we do not flood the system
1844 WriteReg16(UHCI_USBINTR
, 0);
1845 fEnabledInterrupts
= 0;
1846 // ToDo: cancel all transfers and reset the host controller
1847 // acknowledge not needed
1851 WriteReg16(UHCI_USBSTS
, acknowledge
);
1853 release_spinlock(&lock
);
1855 if (finishTransfers
)
1856 release_sem_etc(fFinishTransfersSem
, 1, B_DO_NOT_RESCHEDULE
);
1863 UHCI::AddTo(Stack
*stack
)
1866 set_dprintf_enabled(true);
1867 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
1868 load_driver_symbols("uhci");
1873 status_t status
= get_module(B_PCI_MODULE_NAME
, (module_info
**)&sPCIModule
);
1874 if (status
< B_OK
) {
1875 TRACE_MODULE_ERROR("AddTo(): getting pci module failed! 0x%08"
1876 B_PRIx32
"\n", status
);
1881 TRACE_MODULE("AddTo(): setting up hardware\n");
1884 pci_info
*item
= new(std::nothrow
) pci_info
;
1887 put_module(B_PCI_MODULE_NAME
);
1891 // Try to get the PCI x86 module as well so we can enable possible MSIs.
1892 if (sPCIx86Module
== NULL
&& get_module(B_PCI_X86_MODULE_NAME
,
1893 (module_info
**)&sPCIx86Module
) != B_OK
) {
1894 // If it isn't there, that's not critical though.
1895 TRACE_MODULE_ERROR("failed to get pci x86 module\n");
1896 sPCIx86Module
= NULL
;
1899 for (int32 i
= 0; sPCIModule
->get_nth_pci_info(i
, item
) >= B_OK
; i
++) {
1901 if (item
->class_base
== PCI_serial_bus
&& item
->class_sub
== PCI_usb
1902 && item
->class_api
== PCI_usb_uhci
) {
1903 if (item
->u
.h0
.interrupt_line
== 0
1904 || item
->u
.h0
.interrupt_line
== 0xFF) {
1905 TRACE_MODULE_ERROR("AddTo(): found with invalid IRQ - check IRQ assignement\n");
1909 TRACE_MODULE("AddTo(): found at IRQ %u\n",
1910 item
->u
.h0
.interrupt_line
);
1911 UHCI
*bus
= new(std::nothrow
) UHCI(item
, stack
);
1915 put_module(B_PCI_MODULE_NAME
);
1919 if (bus
->InitCheck() < B_OK
) {
1920 TRACE_MODULE_ERROR("AddTo(): InitCheck() failed 0x%08" B_PRIx32
1921 "\n", bus
->InitCheck());
1926 // the bus took it away
1927 item
= new(std::nothrow
) pci_info
;
1930 stack
->AddBusManager(bus
);
1936 TRACE_MODULE_ERROR("no devices found\n");
1939 put_module(B_PCI_MODULE_NAME
);
1949 UHCI::CreateFilledTransfer(Transfer
*transfer
, uhci_td
**_firstDescriptor
,
1950 uhci_qh
**_transferQueue
)
1952 Pipe
*pipe
= transfer
->TransferPipe();
1953 bool directionIn
= (pipe
->Direction() == Pipe::In
);
1955 uhci_td
*firstDescriptor
= NULL
;
1956 uhci_td
*lastDescriptor
= NULL
;
1957 status_t result
= CreateDescriptorChain(pipe
, &firstDescriptor
,
1958 &lastDescriptor
, directionIn
? TD_TOKEN_IN
: TD_TOKEN_OUT
,
1959 transfer
->VectorLength());
1963 if (!firstDescriptor
|| !lastDescriptor
)
1966 lastDescriptor
->status
|= TD_CONTROL_IOC
;
1967 lastDescriptor
->link_phy
= TD_TERMINATE
;
1968 lastDescriptor
->link_log
= NULL
;
1971 WriteDescriptorChain(firstDescriptor
, transfer
->Vector(),
1972 transfer
->VectorCount());
1975 uhci_qh
*transferQueue
= CreateTransferQueue(firstDescriptor
);
1976 if (!transferQueue
) {
1977 FreeDescriptorChain(firstDescriptor
);
1981 *_firstDescriptor
= firstDescriptor
;
1982 *_transferQueue
= transferQueue
;
1988 UHCI::CreateTransferQueue(uhci_td
*descriptor
)
1991 phys_addr_t physicalAddress
;
1992 if (fStack
->AllocateChunk((void **)&queueHead
, &physicalAddress
,
1993 sizeof(uhci_qh
)) < B_OK
)
1996 queueHead
->this_phy
= (uint32
)physicalAddress
;
1997 queueHead
->element_phy
= descriptor
->this_phy
;
2003 UHCI::FreeTransferQueue(uhci_qh
*queueHead
)
2008 fStack
->FreeChunk(queueHead
, queueHead
->this_phy
, sizeof(uhci_qh
));
2013 UHCI::CreateDescriptor(Pipe
*pipe
, uint8 direction
, size_t bufferSize
)
2016 phys_addr_t physicalAddress
;
2018 if (fStack
->AllocateChunk((void **)&result
, &physicalAddress
,
2019 sizeof(uhci_td
)) < B_OK
) {
2020 TRACE_ERROR("failed to allocate a transfer descriptor\n");
2024 result
->this_phy
= (uint32
)physicalAddress
;
2025 result
->status
= TD_STATUS_ACTIVE
;
2026 if (pipe
->Type() & USB_OBJECT_ISO_PIPE
)
2027 result
->status
|= TD_CONTROL_ISOCHRONOUS
;
2029 result
->status
|= TD_CONTROL_3_ERRORS
;
2030 if (direction
== TD_TOKEN_IN
)
2031 result
->status
|= TD_CONTROL_SPD
;
2033 if (pipe
->Speed() == USB_SPEED_LOWSPEED
)
2034 result
->status
|= TD_CONTROL_LOWSPEED
;
2036 result
->buffer_size
= bufferSize
;
2037 if (bufferSize
== 0)
2038 result
->token
= TD_TOKEN_NULL_DATA
;
2040 result
->token
= (bufferSize
- 1) << TD_TOKEN_MAXLEN_SHIFT
;
2042 result
->token
|= (pipe
->EndpointAddress() << TD_TOKEN_ENDPTADDR_SHIFT
)
2043 | (pipe
->DeviceAddress() << 8) | direction
;
2045 result
->link_phy
= 0;
2046 result
->link_log
= NULL
;
2047 if (bufferSize
<= 0) {
2048 result
->buffer_log
= NULL
;
2049 result
->buffer_phy
= 0;
2053 if (fStack
->AllocateChunk(&result
->buffer_log
, &physicalAddress
,
2054 bufferSize
) < B_OK
) {
2055 TRACE_ERROR("unable to allocate space for the buffer\n");
2056 fStack
->FreeChunk(result
, result
->this_phy
, sizeof(uhci_td
));
2059 result
->buffer_phy
= physicalAddress
;
2066 UHCI::CreateDescriptorChain(Pipe
*pipe
, uhci_td
**_firstDescriptor
,
2067 uhci_td
**_lastDescriptor
, uint8 direction
, size_t bufferSize
)
2069 size_t packetSize
= pipe
->MaxPacketSize();
2070 int32 descriptorCount
= (bufferSize
+ packetSize
- 1) / packetSize
;
2071 if (descriptorCount
== 0)
2072 descriptorCount
= 1;
2074 bool dataToggle
= pipe
->DataToggle();
2075 uhci_td
*firstDescriptor
= NULL
;
2076 uhci_td
*lastDescriptor
= *_firstDescriptor
;
2077 for (int32 i
= 0; i
< descriptorCount
; i
++) {
2078 uhci_td
*descriptor
= CreateDescriptor(pipe
, direction
,
2079 min_c(packetSize
, bufferSize
));
2082 FreeDescriptorChain(firstDescriptor
);
2087 descriptor
->token
|= TD_TOKEN_DATA1
;
2091 LinkDescriptors(lastDescriptor
, descriptor
);
2093 dataToggle
= !dataToggle
;
2094 bufferSize
-= packetSize
;
2095 lastDescriptor
= descriptor
;
2096 if (!firstDescriptor
)
2097 firstDescriptor
= descriptor
;
2100 *_firstDescriptor
= firstDescriptor
;
2101 *_lastDescriptor
= lastDescriptor
;
2107 UHCI::FreeDescriptor(uhci_td
*descriptor
)
2112 if (descriptor
->buffer_log
) {
2113 fStack
->FreeChunk(descriptor
->buffer_log
,
2114 descriptor
->buffer_phy
, descriptor
->buffer_size
);
2117 fStack
->FreeChunk(descriptor
, descriptor
->this_phy
, sizeof(uhci_td
));
2122 UHCI::FreeDescriptorChain(uhci_td
*topDescriptor
)
2124 uhci_td
*current
= topDescriptor
;
2125 uhci_td
*next
= NULL
;
2128 next
= (uhci_td
*)current
->link_log
;
2129 FreeDescriptor(current
);
2136 UHCI::LinkDescriptors(uhci_td
*first
, uhci_td
*second
)
2138 first
->link_phy
= second
->this_phy
| TD_DEPTH_FIRST
;
2139 first
->link_log
= second
;
2144 UHCI::WriteDescriptorChain(uhci_td
*topDescriptor
, iovec
*vector
,
2147 uhci_td
*current
= topDescriptor
;
2148 size_t actualLength
= 0;
2149 size_t vectorIndex
= 0;
2150 size_t vectorOffset
= 0;
2151 size_t bufferOffset
= 0;
2154 if (!current
->buffer_log
)
2158 size_t length
= min_c(current
->buffer_size
- bufferOffset
,
2159 vector
[vectorIndex
].iov_len
- vectorOffset
);
2161 TRACE("copying %ld bytes to bufferOffset %ld from"
2162 " vectorOffset %ld at index %ld of %ld\n", length
, bufferOffset
,
2163 vectorOffset
, vectorIndex
, vectorCount
);
2164 memcpy((uint8
*)current
->buffer_log
+ bufferOffset
,
2165 (uint8
*)vector
[vectorIndex
].iov_base
+ vectorOffset
, length
);
2167 actualLength
+= length
;
2168 vectorOffset
+= length
;
2169 bufferOffset
+= length
;
2171 if (vectorOffset
>= vector
[vectorIndex
].iov_len
) {
2172 if (++vectorIndex
>= vectorCount
) {
2173 TRACE("wrote descriptor chain (%ld bytes, no more vectors)\n",
2175 return actualLength
;
2181 if (bufferOffset
>= current
->buffer_size
) {
2187 if (current
->link_phy
& TD_TERMINATE
)
2190 current
= (uhci_td
*)current
->link_log
;
2193 TRACE("wrote descriptor chain (%ld bytes)\n", actualLength
);
2194 return actualLength
;
2199 UHCI::ReadDescriptorChain(uhci_td
*topDescriptor
, iovec
*vector
,
2200 size_t vectorCount
, uint8
*lastDataToggle
)
2202 uint8 dataToggle
= 0;
2203 uhci_td
*current
= topDescriptor
;
2204 size_t actualLength
= 0;
2205 size_t vectorIndex
= 0;
2206 size_t vectorOffset
= 0;
2207 size_t bufferOffset
= 0;
2209 while (current
&& (current
->status
& TD_STATUS_ACTIVE
) == 0) {
2210 if (!current
->buffer_log
)
2213 dataToggle
= (current
->token
>> TD_TOKEN_DATA_TOGGLE_SHIFT
) & 0x01;
2214 size_t bufferSize
= uhci_td_actual_length(current
);
2217 size_t length
= min_c(bufferSize
- bufferOffset
,
2218 vector
[vectorIndex
].iov_len
- vectorOffset
);
2220 TRACE("copying %ld bytes to vectorOffset %ld from"
2221 " bufferOffset %ld at index %ld of %ld\n", length
, vectorOffset
,
2222 bufferOffset
, vectorIndex
, vectorCount
);
2223 memcpy((uint8
*)vector
[vectorIndex
].iov_base
+ vectorOffset
,
2224 (uint8
*)current
->buffer_log
+ bufferOffset
, length
);
2226 actualLength
+= length
;
2227 vectorOffset
+= length
;
2228 bufferOffset
+= length
;
2230 if (vectorOffset
>= vector
[vectorIndex
].iov_len
) {
2231 if (++vectorIndex
>= vectorCount
) {
2232 TRACE("read descriptor chain (%ld bytes, no more vectors)\n",
2235 *lastDataToggle
= dataToggle
;
2236 return actualLength
;
2242 if (bufferOffset
>= bufferSize
) {
2248 if (current
->link_phy
& TD_TERMINATE
)
2251 current
= (uhci_td
*)current
->link_log
;
2255 *lastDataToggle
= dataToggle
;
2257 TRACE("read descriptor chain (%ld bytes)\n", actualLength
);
2258 return actualLength
;
2263 UHCI::ReadActualLength(uhci_td
*topDescriptor
, uint8
*lastDataToggle
)
2265 size_t actualLength
= 0;
2266 uhci_td
*current
= topDescriptor
;
2267 uint8 dataToggle
= 0;
2269 while (current
&& (current
->status
& TD_STATUS_ACTIVE
) == 0) {
2270 actualLength
+= uhci_td_actual_length(current
);
2271 dataToggle
= (current
->token
>> TD_TOKEN_DATA_TOGGLE_SHIFT
) & 0x01;
2273 if (current
->link_phy
& TD_TERMINATE
)
2276 current
= (uhci_td
*)current
->link_log
;
2280 *lastDataToggle
= dataToggle
;
2282 TRACE("read actual length (%ld bytes)\n", actualLength
);
2283 return actualLength
;
2288 UHCI::WriteIsochronousDescriptorChain(uhci_td
**isoRequest
, uint32 packetCount
,
2291 size_t vectorOffset
= 0;
2292 for (uint32 i
= 0; i
< packetCount
; i
++) {
2293 size_t bufferSize
= isoRequest
[i
]->buffer_size
;
2294 memcpy((uint8
*)isoRequest
[i
]->buffer_log
,
2295 (uint8
*)vector
->iov_base
+ vectorOffset
, bufferSize
);
2296 vectorOffset
+= bufferSize
;
2302 UHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data
*transfer
,
2305 size_t vectorOffset
= 0;
2306 usb_isochronous_data
*isochronousData
2307 = transfer
->transfer
->IsochronousData();
2309 for (uint32 i
= 0; i
< isochronousData
->packet_count
; i
++) {
2310 uhci_td
*current
= transfer
->descriptors
[i
];
2312 size_t bufferSize
= current
->buffer_size
;
2313 size_t actualLength
= uhci_td_actual_length(current
);
2315 isochronousData
->packet_descriptors
[i
].actual_length
= actualLength
;
2317 if (actualLength
> 0)
2318 isochronousData
->packet_descriptors
[i
].status
= B_OK
;
2320 isochronousData
->packet_descriptors
[i
].status
= B_ERROR
;
2321 vectorOffset
+= bufferSize
;
2324 memcpy((uint8
*)vector
->iov_base
+ vectorOffset
,
2325 (uint8
*)current
->buffer_log
, bufferSize
);
2327 vectorOffset
+= bufferSize
;
2333 UHCI::LockIsochronous()
2335 return (mutex_lock(&fIsochronousLock
) == B_OK
);
2340 UHCI::UnlockIsochronous()
2342 mutex_unlock(&fIsochronousLock
);
2347 UHCI::WriteReg8(uint32 reg
, uint8 value
)
2349 sPCIModule
->write_io_8(fRegisterBase
+ reg
, value
);
2354 UHCI::WriteReg16(uint32 reg
, uint16 value
)
2356 sPCIModule
->write_io_16(fRegisterBase
+ reg
, value
);
2361 UHCI::WriteReg32(uint32 reg
, uint32 value
)
2363 sPCIModule
->write_io_32(fRegisterBase
+ reg
, value
);
2368 UHCI::ReadReg8(uint32 reg
)
2370 return sPCIModule
->read_io_8(fRegisterBase
+ reg
);
2375 UHCI::ReadReg16(uint32 reg
)
2377 return sPCIModule
->read_io_16(fRegisterBase
+ reg
);
2382 UHCI::ReadReg32(uint32 reg
)
2384 return sPCIModule
->read_io_32(fRegisterBase
+ reg
);