vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / busses / usb / ohci.cpp
blob77bc6a43e4a9a6a185a7457495510b6d6298f437
1 /*
2 * Copyright 2005-2013, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Jan-Rixt Van Hoye
7 * Salvatore Benedetto <salvatore.benedetto@gmail.com>
8 * Michael Lotz <mmlr@mlotz.ch>
9 * Siarzhuk Zharski <imker@gmx.li>
12 #include <module.h>
13 #include <PCI.h>
14 #include <PCI_x86.h>
15 #include <USB3.h>
16 #include <KernelExport.h>
17 #include <util/AutoLock.h>
19 #include "ohci.h"
21 #define USB_MODULE_NAME "ohci"
23 pci_module_info *OHCI::sPCIModule = NULL;
24 pci_x86_module_info *OHCI::sPCIx86Module = NULL;
27 static int32
28 ohci_std_ops(int32 op, ...)
30 switch (op) {
31 case B_MODULE_INIT:
32 TRACE_MODULE("init module\n");
33 return B_OK;
34 case B_MODULE_UNINIT:
35 TRACE_MODULE("uninit module\n");
36 return B_OK;
39 return EINVAL;
43 usb_host_controller_info ohci_module = {
45 "busses/usb/ohci",
47 ohci_std_ops
49 NULL,
50 OHCI::AddTo
54 module_info *modules[] = {
55 (module_info *)&ohci_module,
56 NULL
60 OHCI::OHCI(pci_info *info, Stack *stack)
61 : BusManager(stack),
62 fPCIInfo(info),
63 fStack(stack),
64 fOperationalRegisters(NULL),
65 fRegisterArea(-1),
66 fHccaArea(-1),
67 fHcca(NULL),
68 fInterruptEndpoints(NULL),
69 fDummyControl(NULL),
70 fDummyBulk(NULL),
71 fDummyIsochronous(NULL),
72 fFirstTransfer(NULL),
73 fLastTransfer(NULL),
74 fFinishTransfersSem(-1),
75 fFinishThread(-1),
76 fStopFinishThread(false),
77 fProcessingPipe(NULL),
78 fFrameBandwidth(NULL),
79 fRootHub(NULL),
80 fRootHubAddress(0),
81 fPortCount(0),
82 fIRQ(0),
83 fUseMSI(false)
85 if (!fInitOK) {
86 TRACE_ERROR("bus manager failed to init\n");
87 return;
90 TRACE("constructing new OHCI host controller driver\n");
91 fInitOK = false;
93 mutex_init(&fEndpointLock, "ohci endpoint lock");
95 // enable busmaster and memory mapped access
96 uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
97 fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
98 command &= ~PCI_command_io;
99 command |= PCI_command_master | PCI_command_memory;
101 sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
102 fPCIInfo->function, PCI_command, 2, command);
104 // map the registers
105 uint32 offset = sPCIModule->read_pci_config(fPCIInfo->bus,
106 fPCIInfo->device, fPCIInfo->function, PCI_base_registers, 4);
107 offset &= PCI_address_memory_32_mask;
108 TRACE_ALWAYS("iospace offset: 0x%" B_PRIx32 "\n", offset);
109 fRegisterArea = map_physical_memory("OHCI memory mapped registers",
110 offset, B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS,
111 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA,
112 (void **)&fOperationalRegisters);
113 if (fRegisterArea < B_OK) {
114 TRACE_ERROR("failed to map register memory\n");
115 return;
118 TRACE("mapped operational registers: %p\n", fOperationalRegisters);
120 // Check the revision of the controller, which should be 10h
121 uint32 revision = _ReadReg(OHCI_REVISION) & 0xff;
122 TRACE("version %" B_PRId32 ".%" B_PRId32 "%s\n",
123 OHCI_REVISION_HIGH(revision), OHCI_REVISION_LOW(revision),
124 OHCI_REVISION_LEGACY(revision) ? ", legacy support" : "");
126 if (OHCI_REVISION_HIGH(revision) != 1 || OHCI_REVISION_LOW(revision) != 0) {
127 TRACE_ERROR("unsupported OHCI revision\n");
128 return;
131 phys_addr_t hccaPhysicalAddress;
132 fHccaArea = fStack->AllocateArea((void **)&fHcca, &hccaPhysicalAddress,
133 sizeof(ohci_hcca), "USB OHCI Host Controller Communication Area");
135 if (fHccaArea < B_OK) {
136 TRACE_ERROR("unable to create the HCCA block area\n");
137 return;
140 memset(fHcca, 0, sizeof(ohci_hcca));
142 // Set Up Host controller
143 // Dummy endpoints
144 fDummyControl = _AllocateEndpoint();
145 if (!fDummyControl)
146 return;
148 fDummyBulk = _AllocateEndpoint();
149 if (!fDummyBulk) {
150 _FreeEndpoint(fDummyControl);
151 return;
154 fDummyIsochronous = _AllocateEndpoint();
155 if (!fDummyIsochronous) {
156 _FreeEndpoint(fDummyControl);
157 _FreeEndpoint(fDummyBulk);
158 return;
161 // Static endpoints that get linked in the HCCA
162 fInterruptEndpoints = new(std::nothrow)
163 ohci_endpoint_descriptor *[OHCI_STATIC_ENDPOINT_COUNT];
164 if (!fInterruptEndpoints) {
165 TRACE_ERROR("failed to allocate memory for interrupt endpoints\n");
166 _FreeEndpoint(fDummyControl);
167 _FreeEndpoint(fDummyBulk);
168 _FreeEndpoint(fDummyIsochronous);
169 return;
172 for (int32 i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
173 fInterruptEndpoints[i] = _AllocateEndpoint();
174 if (!fInterruptEndpoints[i]) {
175 TRACE_ERROR("failed to allocate interrupt endpoint %" B_PRId32 "\n",
177 while (--i >= 0)
178 _FreeEndpoint(fInterruptEndpoints[i]);
179 _FreeEndpoint(fDummyBulk);
180 _FreeEndpoint(fDummyControl);
181 _FreeEndpoint(fDummyIsochronous);
182 return;
186 // build flat tree so that at each of the static interrupt endpoints
187 // fInterruptEndpoints[i] == interrupt endpoint for interval 2^i
188 uint32 interval = OHCI_BIGGEST_INTERVAL;
189 uint32 intervalIndex = OHCI_STATIC_ENDPOINT_COUNT - 1;
190 while (interval > 1) {
191 uint32 insertIndex = interval / 2;
192 while (insertIndex < OHCI_BIGGEST_INTERVAL) {
193 fHcca->interrupt_table[insertIndex]
194 = fInterruptEndpoints[intervalIndex]->physical_address;
195 insertIndex += interval;
198 intervalIndex--;
199 interval /= 2;
202 // setup the empty slot in the list and linking of all -> first
203 fHcca->interrupt_table[0] = fInterruptEndpoints[0]->physical_address;
204 for (int32 i = 1; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
205 fInterruptEndpoints[i]->next_physical_endpoint
206 = fInterruptEndpoints[0]->physical_address;
207 fInterruptEndpoints[i]->next_logical_endpoint
208 = fInterruptEndpoints[0];
211 // Now link the first endpoint to the isochronous endpoint
212 fInterruptEndpoints[0]->next_physical_endpoint
213 = fDummyIsochronous->physical_address;
215 // When the handover from SMM takes place, all interrupts are routed to the
216 // OS. As we don't yet have an interrupt handler installed at this point,
217 // this may cause interrupt storms if the firmware does not disable the
218 // interrupts during handover. Therefore we disable interrupts before
219 // requesting ownership. We have to keep the ownership change interrupt
220 // enabled though, as otherwise the SMM will not be notified of the
221 // ownership change request we trigger below.
222 _WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS &
223 ~OHCI_OWNERSHIP_CHANGE) ;
225 // Determine in what context we are running (Kindly copied from FreeBSD)
226 uint32 control = _ReadReg(OHCI_CONTROL);
227 if (control & OHCI_INTERRUPT_ROUTING) {
228 TRACE_ALWAYS("smm is in control of the host controller\n");
229 uint32 status = _ReadReg(OHCI_COMMAND_STATUS);
230 _WriteReg(OHCI_COMMAND_STATUS, status | OHCI_OWNERSHIP_CHANGE_REQUEST);
231 for (uint32 i = 0; i < 100 && (control & OHCI_INTERRUPT_ROUTING); i++) {
232 snooze(1000);
233 control = _ReadReg(OHCI_CONTROL);
236 if ((control & OHCI_INTERRUPT_ROUTING) != 0) {
237 TRACE_ERROR("smm does not respond.\n");
239 // TODO: Enable this reset as soon as the non-specified
240 // reset a few lines later is replaced by a better solution.
241 //_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
242 //snooze(USB_DELAY_BUS_RESET);
243 } else
244 TRACE_ALWAYS("ownership change successful\n");
245 } else {
246 TRACE("cold started\n");
247 snooze(USB_DELAY_BUS_RESET);
250 // TODO: This reset delays system boot time. It should not be necessary
251 // according to the OHCI spec, but without it some controllers don't start.
252 _WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
253 snooze(USB_DELAY_BUS_RESET);
255 // We now own the host controller and the bus has been reset
256 uint32 frameInterval = _ReadReg(OHCI_FRAME_INTERVAL);
257 uint32 intervalValue = OHCI_GET_INTERVAL_VALUE(frameInterval);
259 _WriteReg(OHCI_COMMAND_STATUS, OHCI_HOST_CONTROLLER_RESET);
260 // Nominal time for a reset is 10 us
261 uint32 reset = 0;
262 for (uint32 i = 0; i < 10; i++) {
263 spin(10);
264 reset = _ReadReg(OHCI_COMMAND_STATUS) & OHCI_HOST_CONTROLLER_RESET;
265 if (reset == 0)
266 break;
269 if (reset) {
270 TRACE_ERROR("error resetting the host controller (timeout)\n");
271 return;
274 // The controller is now in SUSPEND state, we have 2ms to go OPERATIONAL.
276 // Set up host controller register
277 _WriteReg(OHCI_HCCA, (uint32)hccaPhysicalAddress);
278 _WriteReg(OHCI_CONTROL_HEAD_ED, (uint32)fDummyControl->physical_address);
279 _WriteReg(OHCI_BULK_HEAD_ED, (uint32)fDummyBulk->physical_address);
280 // Switch on desired functional features
281 control = _ReadReg(OHCI_CONTROL);
282 control &= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK | OHCI_ENABLE_LIST
283 | OHCI_HC_FUNCTIONAL_STATE_MASK | OHCI_INTERRUPT_ROUTING);
284 control |= OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4
285 | OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL;
286 // And finally start the controller
287 _WriteReg(OHCI_CONTROL, control);
289 // The controller is now OPERATIONAL.
290 frameInterval = (_ReadReg(OHCI_FRAME_INTERVAL) & OHCI_FRAME_INTERVAL_TOGGLE)
291 ^ OHCI_FRAME_INTERVAL_TOGGLE;
292 frameInterval |= OHCI_FSMPS(intervalValue) | intervalValue;
293 _WriteReg(OHCI_FRAME_INTERVAL, frameInterval);
294 // 90% periodic
295 uint32 periodic = OHCI_PERIODIC(intervalValue);
296 _WriteReg(OHCI_PERIODIC_START, periodic);
298 // Fiddle the No Over Current Protection bit to avoid chip bug
299 uint32 desca = _ReadReg(OHCI_RH_DESCRIPTOR_A);
300 _WriteReg(OHCI_RH_DESCRIPTOR_A, desca | OHCI_RH_NO_OVER_CURRENT_PROTECTION);
301 _WriteReg(OHCI_RH_STATUS, OHCI_RH_LOCAL_POWER_STATUS_CHANGE);
302 snooze(OHCI_ENABLE_POWER_DELAY);
303 _WriteReg(OHCI_RH_DESCRIPTOR_A, desca);
305 // The AMD756 requires a delay before re-reading the register,
306 // otherwise it will occasionally report 0 ports.
307 uint32 numberOfPorts = 0;
308 for (uint32 i = 0; i < 10 && numberOfPorts == 0; i++) {
309 snooze(OHCI_READ_DESC_DELAY);
310 uint32 descriptor = _ReadReg(OHCI_RH_DESCRIPTOR_A);
311 numberOfPorts = OHCI_RH_GET_PORT_COUNT(descriptor);
313 if (numberOfPorts > OHCI_MAX_PORT_COUNT)
314 numberOfPorts = OHCI_MAX_PORT_COUNT;
315 fPortCount = numberOfPorts;
316 TRACE("port count is %d\n", fPortCount);
318 // Create the array that will keep bandwidth information
319 fFrameBandwidth = new(std::nothrow) uint16[NUMBER_OF_FRAMES];
321 for (int32 i = 0; i < NUMBER_OF_FRAMES; i++)
322 fFrameBandwidth[i] = MAX_AVAILABLE_BANDWIDTH;
324 // Create semaphore the finisher thread will wait for
325 fFinishTransfersSem = create_sem(0, "OHCI Finish Transfers");
326 if (fFinishTransfersSem < B_OK) {
327 TRACE_ERROR("failed to create semaphore\n");
328 return;
331 // Create the finisher service thread
332 fFinishThread = spawn_kernel_thread(_FinishThread, "ohci finish thread",
333 B_URGENT_DISPLAY_PRIORITY, (void *)this);
334 resume_thread(fFinishThread);
336 // Find the right interrupt vector, using MSIs if available.
337 fIRQ = fPCIInfo->u.h0.interrupt_line;
338 if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus,
339 fPCIInfo->device, fPCIInfo->function) >= 1) {
340 uint8 msiVector = 0;
341 if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device,
342 fPCIInfo->function, 1, &msiVector) == B_OK
343 && sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device,
344 fPCIInfo->function) == B_OK) {
345 TRACE_ALWAYS("using message signaled interrupts\n");
346 fIRQ = msiVector;
347 fUseMSI = true;
351 // Install the interrupt handler
352 TRACE("installing interrupt handler\n");
353 install_io_interrupt_handler(fIRQ, _InterruptHandler, (void *)this, 0);
355 // Enable interesting interrupts now that the handler is in place
356 _WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS
357 | OHCI_MASTER_INTERRUPT_ENABLE);
359 TRACE("OHCI host controller driver constructed\n");
360 fInitOK = true;
364 OHCI::~OHCI()
366 int32 result = 0;
367 fStopFinishThread = true;
368 delete_sem(fFinishTransfersSem);
369 wait_for_thread(fFinishThread, &result);
371 remove_io_interrupt_handler(fIRQ, _InterruptHandler, (void *)this);
373 _LockEndpoints();
374 mutex_destroy(&fEndpointLock);
376 if (fHccaArea >= B_OK)
377 delete_area(fHccaArea);
378 if (fRegisterArea >= B_OK)
379 delete_area(fRegisterArea);
381 _FreeEndpoint(fDummyControl);
382 _FreeEndpoint(fDummyBulk);
383 _FreeEndpoint(fDummyIsochronous);
385 if (fInterruptEndpoints != NULL) {
386 for (int i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++)
387 _FreeEndpoint(fInterruptEndpoints[i]);
390 delete [] fFrameBandwidth;
391 delete [] fInterruptEndpoints;
392 delete fRootHub;
394 if (fUseMSI && sPCIx86Module != NULL) {
395 sPCIx86Module->disable_msi(fPCIInfo->bus,
396 fPCIInfo->device, fPCIInfo->function);
397 sPCIx86Module->unconfigure_msi(fPCIInfo->bus,
398 fPCIInfo->device, fPCIInfo->function);
400 put_module(B_PCI_MODULE_NAME);
401 if (sPCIx86Module != NULL) {
402 sPCIx86Module = NULL;
403 put_module(B_PCI_X86_MODULE_NAME);
408 status_t
409 OHCI::Start()
411 TRACE("starting OHCI host controller\n");
413 uint32 control = _ReadReg(OHCI_CONTROL);
414 if ((control & OHCI_HC_FUNCTIONAL_STATE_MASK)
415 != OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL) {
416 TRACE_ERROR("controller not started (0x%08" B_PRIx32 ")!\n", control);
417 return B_ERROR;
418 } else
419 TRACE("controller is operational!\n");
421 fRootHubAddress = AllocateAddress();
422 fRootHub = new(std::nothrow) OHCIRootHub(RootObject(), fRootHubAddress);
423 if (!fRootHub) {
424 TRACE_ERROR("no memory to allocate root hub\n");
425 return B_NO_MEMORY;
428 if (fRootHub->InitCheck() < B_OK) {
429 TRACE_ERROR("root hub failed init check\n");
430 return B_ERROR;
433 SetRootHub(fRootHub);
434 TRACE_ALWAYS("successfully started the controller\n");
435 return BusManager::Start();
439 status_t
440 OHCI::SubmitTransfer(Transfer *transfer)
442 // short circuit the root hub
443 if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
444 return fRootHub->ProcessTransfer(this, transfer);
446 uint32 type = transfer->TransferPipe()->Type();
447 if (type & USB_OBJECT_CONTROL_PIPE) {
448 TRACE("submitting request\n");
449 return _SubmitRequest(transfer);
452 if ((type & USB_OBJECT_BULK_PIPE) || (type & USB_OBJECT_INTERRUPT_PIPE)) {
453 TRACE("submitting %s transfer\n",
454 (type & USB_OBJECT_BULK_PIPE) ? "bulk" : "interrupt");
455 return _SubmitTransfer(transfer);
458 if (type & USB_OBJECT_ISO_PIPE) {
459 TRACE("submitting isochronous transfer\n");
460 return _SubmitIsochronousTransfer(transfer);
463 TRACE_ERROR("tried to submit transfer for unknown pipe type %" B_PRIu32 "\n",
464 type);
465 return B_ERROR;
469 status_t
470 OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
472 if (!Lock())
473 return B_ERROR;
475 struct transfer_entry {
476 Transfer * transfer;
477 transfer_entry * next;
480 transfer_entry *list = NULL;
481 transfer_data *current = fFirstTransfer;
482 while (current) {
483 if (current->transfer && current->transfer->TransferPipe() == pipe) {
484 // Check if the skip bit is already set
485 if (!(current->endpoint->flags & OHCI_ENDPOINT_SKIP)) {
486 current->endpoint->flags |= OHCI_ENDPOINT_SKIP;
487 // In case the controller is processing
488 // this endpoint, wait for it to finish
489 snooze(1000);
492 // Clear the endpoint
493 current->endpoint->head_physical_descriptor
494 = current->endpoint->tail_physical_descriptor;
496 if (!force) {
497 if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
498 ohci_isochronous_td *descriptor
499 = (ohci_isochronous_td *)current->first_descriptor;
500 while (descriptor) {
501 uint16 frame = OHCI_ITD_GET_STARTING_FRAME(
502 descriptor->flags);
503 _ReleaseIsochronousBandwidth(frame,
504 OHCI_ITD_GET_FRAME_COUNT(descriptor->flags));
505 if (descriptor
506 == (ohci_isochronous_td*)current->last_descriptor)
507 // this is the last ITD of the transfer
508 break;
510 descriptor
511 = (ohci_isochronous_td *)
512 descriptor->next_done_descriptor;
516 // If the transfer is canceled by force, the one causing the
517 // cancel is probably not the one who initiated the transfer
518 // and the callback is likely not safe anymore
519 transfer_entry *entry
520 = (transfer_entry *)malloc(sizeof(transfer_entry));
521 if (entry != NULL) {
522 entry->transfer = current->transfer;
523 current->transfer = NULL;
524 entry->next = list;
525 list = entry;
528 current->canceled = true;
530 current = current->link;
533 Unlock();
535 while (list != NULL) {
536 transfer_entry *next = list->next;
537 list->transfer->Finished(B_CANCELED, 0);
538 delete list->transfer;
539 free(list);
540 list = next;
543 // wait for any transfers that might have made it before canceling
544 while (fProcessingPipe == pipe)
545 snooze(1000);
547 // notify the finisher so it can clean up the canceled transfers
548 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
549 return B_OK;
553 status_t
554 OHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
556 TRACE("pipe change %d for pipe %p\n", change, pipe);
557 if (pipe->DeviceAddress() == fRootHubAddress) {
558 // no need to insert/remove endpoint descriptors for the root hub
559 return B_OK;
562 switch (change) {
563 case USB_CHANGE_CREATED:
564 return _InsertEndpointForPipe(pipe);
566 case USB_CHANGE_DESTROYED:
567 return _RemoveEndpointForPipe(pipe);
569 case USB_CHANGE_PIPE_POLICY_CHANGED:
570 TRACE("pipe policy changing unhandled!\n");
571 break;
573 default:
574 TRACE_ERROR("unknown pipe change!\n");
575 return B_ERROR;
578 return B_OK;
582 status_t
583 OHCI::AddTo(Stack *stack)
585 #ifdef TRACE_USB
586 set_dprintf_enabled(true);
587 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
588 load_driver_symbols("ohci");
589 #endif
590 #endif
592 if (!sPCIModule) {
593 status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
594 if (status < B_OK) {
595 TRACE_MODULE_ERROR("getting pci module failed! 0x%08" B_PRIx32 "\n",
596 status);
597 return status;
601 TRACE_MODULE("searching devices\n");
602 bool found = false;
603 pci_info *item = new(std::nothrow) pci_info;
604 if (!item) {
605 sPCIModule = NULL;
606 put_module(B_PCI_MODULE_NAME);
607 return B_NO_MEMORY;
610 // Try to get the PCI x86 module as well so we can enable possible MSIs.
611 if (sPCIx86Module == NULL && get_module(B_PCI_X86_MODULE_NAME,
612 (module_info **)&sPCIx86Module) != B_OK) {
613 // If it isn't there, that's not critical though.
614 TRACE_MODULE_ERROR("failed to get pci x86 module\n");
615 sPCIx86Module = NULL;
618 for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
619 if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
620 && item->class_api == PCI_usb_ohci) {
621 if (item->u.h0.interrupt_line == 0
622 || item->u.h0.interrupt_line == 0xFF) {
623 TRACE_MODULE_ERROR("found device with invalid IRQ -"
624 " check IRQ assignement\n");
625 continue;
628 TRACE_MODULE("found device at IRQ %u\n",
629 item->u.h0.interrupt_line);
630 OHCI *bus = new(std::nothrow) OHCI(item, stack);
631 if (!bus) {
632 delete item;
633 sPCIModule = NULL;
634 put_module(B_PCI_MODULE_NAME);
636 if (sPCIx86Module != NULL) {
637 sPCIx86Module = NULL;
638 put_module(B_PCI_X86_MODULE_NAME);
641 return B_NO_MEMORY;
644 if (bus->InitCheck() < B_OK) {
645 TRACE_MODULE_ERROR("bus failed init check\n");
646 delete bus;
647 continue;
650 // the bus took it away
651 item = new(std::nothrow) pci_info;
653 bus->Start();
654 stack->AddBusManager(bus);
655 found = true;
659 if (!found) {
660 TRACE_MODULE_ERROR("no devices found\n");
661 delete item;
662 sPCIModule = NULL;
663 put_module(B_PCI_MODULE_NAME);
665 if (sPCIx86Module != NULL) {
666 sPCIx86Module = NULL;
667 put_module(B_PCI_X86_MODULE_NAME);
670 return ENODEV;
673 delete item;
674 return B_OK;
678 status_t
679 OHCI::GetPortStatus(uint8 index, usb_port_status *status)
681 if (index >= fPortCount) {
682 TRACE_ERROR("get port status for invalid port %u\n", index);
683 return B_BAD_INDEX;
686 status->status = status->change = 0;
687 uint32 portStatus = _ReadReg(OHCI_RH_PORT_STATUS(index));
689 // status
690 if (portStatus & OHCI_RH_PORTSTATUS_CCS)
691 status->status |= PORT_STATUS_CONNECTION;
692 if (portStatus & OHCI_RH_PORTSTATUS_PES)
693 status->status |= PORT_STATUS_ENABLE;
694 if (portStatus & OHCI_RH_PORTSTATUS_PSS)
695 status->status |= PORT_STATUS_SUSPEND;
696 if (portStatus & OHCI_RH_PORTSTATUS_POCI)
697 status->status |= PORT_STATUS_OVER_CURRENT;
698 if (portStatus & OHCI_RH_PORTSTATUS_PRS)
699 status->status |= PORT_STATUS_RESET;
700 if (portStatus & OHCI_RH_PORTSTATUS_PPS)
701 status->status |= PORT_STATUS_POWER;
702 if (portStatus & OHCI_RH_PORTSTATUS_LSDA)
703 status->status |= PORT_STATUS_LOW_SPEED;
705 // change
706 if (portStatus & OHCI_RH_PORTSTATUS_CSC)
707 status->change |= PORT_STATUS_CONNECTION;
708 if (portStatus & OHCI_RH_PORTSTATUS_PESC)
709 status->change |= PORT_STATUS_ENABLE;
710 if (portStatus & OHCI_RH_PORTSTATUS_PSSC)
711 status->change |= PORT_STATUS_SUSPEND;
712 if (portStatus & OHCI_RH_PORTSTATUS_OCIC)
713 status->change |= PORT_STATUS_OVER_CURRENT;
714 if (portStatus & OHCI_RH_PORTSTATUS_PRSC)
715 status->change |= PORT_STATUS_RESET;
717 TRACE("port %u status 0x%04x change 0x%04x\n", index,
718 status->status, status->change);
719 return B_OK;
723 status_t
724 OHCI::SetPortFeature(uint8 index, uint16 feature)
726 TRACE("set port feature index %u feature %u\n", index, feature);
727 if (index > fPortCount)
728 return B_BAD_INDEX;
730 switch (feature) {
731 case PORT_ENABLE:
732 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PES);
733 return B_OK;
735 case PORT_SUSPEND:
736 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSS);
737 return B_OK;
739 case PORT_RESET:
740 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRS);
741 return B_OK;
743 case PORT_POWER:
744 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PPS);
745 return B_OK;
748 return B_BAD_VALUE;
752 status_t
753 OHCI::ClearPortFeature(uint8 index, uint16 feature)
755 TRACE("clear port feature index %u feature %u\n", index, feature);
756 if (index > fPortCount)
757 return B_BAD_INDEX;
759 switch (feature) {
760 case PORT_ENABLE:
761 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CCS);
762 return B_OK;
764 case PORT_SUSPEND:
765 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_POCI);
766 return B_OK;
768 case PORT_POWER:
769 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_LSDA);
770 return B_OK;
772 case C_PORT_CONNECTION:
773 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CSC);
774 return B_OK;
776 case C_PORT_ENABLE:
777 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PESC);
778 return B_OK;
780 case C_PORT_SUSPEND:
781 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSSC);
782 return B_OK;
784 case C_PORT_OVER_CURRENT:
785 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_OCIC);
786 return B_OK;
788 case C_PORT_RESET:
789 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRSC);
790 return B_OK;
793 return B_BAD_VALUE;
797 int32
798 OHCI::_InterruptHandler(void *data)
800 return ((OHCI *)data)->_Interrupt();
804 int32
805 OHCI::_Interrupt()
807 static spinlock lock = B_SPINLOCK_INITIALIZER;
808 acquire_spinlock(&lock);
810 uint32 status = 0;
811 uint32 acknowledge = 0;
812 bool finishTransfers = false;
813 int32 result = B_HANDLED_INTERRUPT;
815 // The LSb of done_head is used to inform the HCD that an interrupt
816 // condition exists for both the done list and for another event recorded in
817 // the HcInterruptStatus register. If done_head is 0, then the interrupt
818 // was caused by other than the HccaDoneHead update and the
819 // HcInterruptStatus register needs to be accessed to determine that exact
820 // interrupt cause. If HccDoneHead is nonzero, then a done list update
821 // interrupt is indicated and if the LSb of the Dword is nonzero, then an
822 // additional interrupt event is indicated and HcInterruptStatus should be
823 // checked to determine its cause.
824 uint32 doneHead = fHcca->done_head;
825 if (doneHead != 0) {
826 status = OHCI_WRITEBACK_DONE_HEAD;
827 if (doneHead & OHCI_DONE_INTERRUPTS)
828 status |= _ReadReg(OHCI_INTERRUPT_STATUS)
829 & _ReadReg(OHCI_INTERRUPT_ENABLE);
830 } else {
831 status = _ReadReg(OHCI_INTERRUPT_STATUS) & _ReadReg(OHCI_INTERRUPT_ENABLE)
832 & ~OHCI_WRITEBACK_DONE_HEAD;
833 if (status == 0) {
834 // Nothing to be done (PCI shared interrupt)
835 release_spinlock(&lock);
836 return B_UNHANDLED_INTERRUPT;
840 if (status & OHCI_SCHEDULING_OVERRUN) {
841 TRACE_MODULE("scheduling overrun occured\n");
842 acknowledge |= OHCI_SCHEDULING_OVERRUN;
845 if (status & OHCI_WRITEBACK_DONE_HEAD) {
846 TRACE_MODULE("transfer descriptors processed\n");
847 fHcca->done_head = 0;
848 acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
849 result = B_INVOKE_SCHEDULER;
850 finishTransfers = true;
853 if (status & OHCI_RESUME_DETECTED) {
854 TRACE_MODULE("resume detected\n");
855 acknowledge |= OHCI_RESUME_DETECTED;
858 if (status & OHCI_UNRECOVERABLE_ERROR) {
859 TRACE_MODULE_ERROR("unrecoverable error - controller halted\n");
860 _WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
861 // TODO: clear all pending transfers, reset and resetup the controller
864 if (status & OHCI_ROOT_HUB_STATUS_CHANGE) {
865 TRACE_MODULE("root hub status change\n");
866 // Disable the interrupt as it will otherwise be retriggered until the
867 // port has been reset and the change is cleared explicitly.
868 // TODO: renable it once we use status changes instead of polling
869 _WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ROOT_HUB_STATUS_CHANGE);
870 acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE;
873 if (acknowledge != 0)
874 _WriteReg(OHCI_INTERRUPT_STATUS, acknowledge);
876 release_spinlock(&lock);
878 if (finishTransfers)
879 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
881 return result;
885 status_t
886 OHCI::_AddPendingTransfer(Transfer *transfer,
887 ohci_endpoint_descriptor *endpoint, ohci_general_td *firstDescriptor,
888 ohci_general_td *dataDescriptor, ohci_general_td *lastDescriptor,
889 bool directionIn)
891 if (!transfer || !endpoint || !lastDescriptor)
892 return B_BAD_VALUE;
894 transfer_data *data = new(std::nothrow) transfer_data;
895 if (!data)
896 return B_NO_MEMORY;
898 status_t result = transfer->InitKernelAccess();
899 if (result < B_OK) {
900 delete data;
901 return result;
904 data->transfer = transfer;
905 data->endpoint = endpoint;
906 data->incoming = directionIn;
907 data->canceled = false;
908 data->link = NULL;
910 // the current tail will become the first descriptor
911 data->first_descriptor = (ohci_general_td *)endpoint->tail_logical_descriptor;
913 // the data and first descriptors might be the same
914 if (dataDescriptor == firstDescriptor)
915 data->data_descriptor = data->first_descriptor;
916 else
917 data->data_descriptor = dataDescriptor;
919 // even the last and the first descriptor might be the same
920 if (lastDescriptor == firstDescriptor)
921 data->last_descriptor = data->first_descriptor;
922 else
923 data->last_descriptor = lastDescriptor;
925 if (!Lock()) {
926 delete data;
927 return B_ERROR;
930 if (fLastTransfer)
931 fLastTransfer->link = data;
932 else
933 fFirstTransfer = data;
935 fLastTransfer = data;
936 Unlock();
938 return B_OK;
942 status_t
943 OHCI::_AddPendingIsochronousTransfer(Transfer *transfer,
944 ohci_endpoint_descriptor *endpoint, ohci_isochronous_td *firstDescriptor,
945 ohci_isochronous_td *lastDescriptor, bool directionIn)
947 if (!transfer || !endpoint || !lastDescriptor)
948 return B_BAD_VALUE;
950 transfer_data *data = new(std::nothrow) transfer_data;
951 if (!data)
952 return B_NO_MEMORY;
954 status_t result = transfer->InitKernelAccess();
955 if (result < B_OK) {
956 delete data;
957 return result;
960 data->transfer = transfer;
961 data->endpoint = endpoint;
962 data->incoming = directionIn;
963 data->canceled = false;
964 data->link = NULL;
966 // the current tail will become the first descriptor
967 data->first_descriptor = (ohci_general_td*)endpoint->tail_logical_descriptor;
969 // the data and first descriptors are the same
970 data->data_descriptor = data->first_descriptor;
972 // the last and the first descriptor might be the same
973 if (lastDescriptor == firstDescriptor)
974 data->last_descriptor = data->first_descriptor;
975 else
976 data->last_descriptor = (ohci_general_td*)lastDescriptor;
978 if (!Lock()) {
979 delete data;
980 return B_ERROR;
983 if (fLastTransfer)
984 fLastTransfer->link = data;
985 else
986 fFirstTransfer = data;
988 fLastTransfer = data;
989 Unlock();
991 return B_OK;
995 int32
996 OHCI::_FinishThread(void *data)
998 ((OHCI *)data)->_FinishTransfers();
999 return B_OK;
1003 void
1004 OHCI::_FinishTransfers()
1006 while (!fStopFinishThread) {
1007 if (acquire_sem(fFinishTransfersSem) < B_OK)
1008 continue;
1010 // eat up sems that have been released by multiple interrupts
1011 int32 semCount = 0;
1012 get_sem_count(fFinishTransfersSem, &semCount);
1013 if (semCount > 0)
1014 acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
1016 if (!Lock())
1017 continue;
1019 TRACE("finishing transfers (first transfer: %p; last"
1020 " transfer: %p)\n", fFirstTransfer, fLastTransfer);
1021 transfer_data *lastTransfer = NULL;
1022 transfer_data *transfer = fFirstTransfer;
1023 Unlock();
1025 while (transfer) {
1026 bool transferDone = false;
1027 ohci_general_td *descriptor = transfer->first_descriptor;
1028 ohci_endpoint_descriptor *endpoint = transfer->endpoint;
1029 status_t callbackStatus = B_OK;
1031 if (endpoint->flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT) {
1032 transfer_data *next = transfer->link;
1033 if (_FinishIsochronousTransfer(transfer, &lastTransfer)) {
1034 delete transfer->transfer;
1035 delete transfer;
1037 transfer = next;
1038 continue;
1041 MutexLocker endpointLocker(endpoint->lock);
1043 if ((endpoint->head_physical_descriptor & OHCI_ENDPOINT_HEAD_MASK)
1044 != endpoint->tail_physical_descriptor
1045 && (endpoint->head_physical_descriptor
1046 & OHCI_ENDPOINT_HALTED) == 0) {
1047 // there are still active transfers on this endpoint, we need
1048 // to wait for all of them to complete, otherwise we'd read
1049 // a potentially bogus data toggle value below
1050 TRACE("endpoint %p still has active tds\n", endpoint);
1051 lastTransfer = transfer;
1052 transfer = transfer->link;
1053 continue;
1056 endpointLocker.Unlock();
1058 while (descriptor && !transfer->canceled) {
1059 uint32 status = OHCI_TD_GET_CONDITION_CODE(descriptor->flags);
1060 if (status == OHCI_TD_CONDITION_NOT_ACCESSED) {
1061 // td is still active
1062 TRACE("td %p still active\n", descriptor);
1063 break;
1066 if (status != OHCI_TD_CONDITION_NO_ERROR) {
1067 // an error occured, but we must ensure that the td
1068 // was actually done
1069 if (endpoint->head_physical_descriptor & OHCI_ENDPOINT_HALTED) {
1070 // the endpoint is halted, this guaratees us that this
1071 // descriptor has passed (we don't know if the endpoint
1072 // was halted because of this td, but we do not need
1073 // to know, as when it was halted by another td this
1074 // still ensures that this td was handled before).
1075 TRACE_ERROR("td error: 0x%08" B_PRIx32 "\n", status);
1077 callbackStatus = _GetStatusOfConditionCode(status);
1079 transferDone = true;
1080 break;
1081 } else {
1082 // an error occured but the endpoint is not halted so
1083 // the td is in fact still active
1084 TRACE("td %p active with error\n", descriptor);
1085 break;
1089 // the td has completed without an error
1090 TRACE("td %p done\n", descriptor);
1092 if (descriptor == transfer->last_descriptor
1093 || descriptor->buffer_physical != 0) {
1094 // this is the last td of the transfer or a short packet
1095 callbackStatus = B_OK;
1096 transferDone = true;
1097 break;
1100 descriptor
1101 = (ohci_general_td *)descriptor->next_logical_descriptor;
1104 if (transfer->canceled) {
1105 // when a transfer is canceled, all transfers to that endpoint
1106 // are canceled by setting the head pointer to the tail pointer
1107 // which causes all of the tds to become "free" (as they are
1108 // inaccessible and not accessed anymore (as setting the head
1109 // pointer required disabling the endpoint))
1110 callbackStatus = B_OK;
1111 transferDone = true;
1114 if (!transferDone) {
1115 lastTransfer = transfer;
1116 transfer = transfer->link;
1117 continue;
1120 // remove the transfer from the list first so we are sure
1121 // it doesn't get canceled while we still process it
1122 transfer_data *next = transfer->link;
1123 if (Lock()) {
1124 if (lastTransfer)
1125 lastTransfer->link = transfer->link;
1127 if (transfer == fFirstTransfer)
1128 fFirstTransfer = transfer->link;
1129 if (transfer == fLastTransfer)
1130 fLastTransfer = lastTransfer;
1132 // store the currently processing pipe here so we can wait
1133 // in cancel if we are processing something on the target pipe
1134 if (!transfer->canceled)
1135 fProcessingPipe = transfer->transfer->TransferPipe();
1137 transfer->link = NULL;
1138 Unlock();
1141 // break the descriptor chain on the last descriptor
1142 transfer->last_descriptor->next_logical_descriptor = NULL;
1143 TRACE("transfer %p done with status 0x%08" B_PRIx32 "\n",
1144 transfer, callbackStatus);
1146 // if canceled the callback has already been called
1147 if (!transfer->canceled) {
1148 size_t actualLength = 0;
1149 if (callbackStatus == B_OK) {
1150 if (transfer->data_descriptor && transfer->incoming) {
1151 // data to read out
1152 iovec *vector = transfer->transfer->Vector();
1153 size_t vectorCount = transfer->transfer->VectorCount();
1155 transfer->transfer->PrepareKernelAccess();
1156 actualLength = _ReadDescriptorChain(
1157 transfer->data_descriptor,
1158 vector, vectorCount);
1159 } else if (transfer->data_descriptor) {
1160 // read the actual length that was sent
1161 actualLength = _ReadActualLength(
1162 transfer->data_descriptor);
1165 // get the last data toggle and store it for next time
1166 transfer->transfer->TransferPipe()->SetDataToggle(
1167 (endpoint->head_physical_descriptor
1168 & OHCI_ENDPOINT_TOGGLE_CARRY) != 0);
1170 if (transfer->transfer->IsFragmented()) {
1171 // this transfer may still have data left
1172 TRACE("advancing fragmented transfer\n");
1173 transfer->transfer->AdvanceByFragment(actualLength);
1174 if (transfer->transfer->VectorLength() > 0) {
1175 TRACE("still %ld bytes left on transfer\n",
1176 transfer->transfer->VectorLength());
1177 // TODO actually resubmit the transfer
1180 // the transfer is done, but we already set the
1181 // actualLength with AdvanceByFragment()
1182 actualLength = 0;
1186 transfer->transfer->Finished(callbackStatus, actualLength);
1187 fProcessingPipe = NULL;
1190 if (callbackStatus != B_OK) {
1191 // remove the transfer and make the head pointer valid again
1192 // (including clearing the halt state)
1193 _RemoveTransferFromEndpoint(transfer);
1196 // free the descriptors
1197 _FreeDescriptorChain(transfer->first_descriptor);
1199 delete transfer->transfer;
1200 delete transfer;
1201 transfer = next;
1207 bool
1208 OHCI::_FinishIsochronousTransfer(transfer_data *transfer,
1209 transfer_data **_lastTransfer)
1211 status_t callbackStatus = B_OK;
1212 size_t actualLength = 0;
1213 uint32 packet = 0;
1215 if (transfer->canceled)
1216 callbackStatus = B_CANCELED;
1217 else {
1218 // at first check if ALL ITDs are retired by HC
1219 ohci_isochronous_td *descriptor
1220 = (ohci_isochronous_td *)transfer->first_descriptor;
1221 while (descriptor) {
1222 if (OHCI_TD_GET_CONDITION_CODE(descriptor->flags)
1223 == OHCI_TD_CONDITION_NOT_ACCESSED) {
1224 TRACE("ITD %p still active\n", descriptor);
1225 *_lastTransfer = transfer;
1226 return false;
1229 if (descriptor == (ohci_isochronous_td*)transfer->last_descriptor) {
1230 // this is the last ITD of the transfer
1231 descriptor = (ohci_isochronous_td *)transfer->first_descriptor;
1232 break;
1235 descriptor
1236 = (ohci_isochronous_td *)descriptor->next_done_descriptor;
1239 while (descriptor) {
1240 uint32 status = OHCI_TD_GET_CONDITION_CODE(descriptor->flags);
1241 if (status != OHCI_TD_CONDITION_NO_ERROR) {
1242 TRACE_ERROR("ITD error: 0x%08" B_PRIx32 "\n", status);
1243 // spec says that in most cases condition code
1244 // of retired ITDs is set to NoError, but for the
1245 // time overrun it can be DataOverrun. We assume
1246 // the _first_ occurience of such error as status
1247 // reported to the callback
1248 if (callbackStatus == B_OK)
1249 callbackStatus = _GetStatusOfConditionCode(status);
1252 usb_isochronous_data *isochronousData
1253 = transfer->transfer->IsochronousData();
1255 uint32 frameCount = OHCI_ITD_GET_FRAME_COUNT(descriptor->flags);
1256 for (size_t i = 0; i < frameCount; i++, packet++) {
1257 usb_iso_packet_descriptor* packet_descriptor
1258 = &isochronousData->packet_descriptors[packet];
1260 uint16 offset = descriptor->offset[OHCI_ITD_OFFSET_IDX(i)];
1261 uint8 code = OHCI_ITD_GET_BUFFER_CONDITION_CODE(offset);
1262 packet_descriptor->status = _GetStatusOfConditionCode(code);
1264 // not touched by HC - sheduled too late to be processed
1265 // in the requested frame - so we ignore it too
1266 if (packet_descriptor->status == B_DEV_TOO_LATE)
1267 continue;
1269 size_t len = OHCI_ITD_GET_BUFFER_LENGTH(offset);
1270 if (!transfer->incoming)
1271 len = packet_descriptor->request_length - len;
1273 packet_descriptor->actual_length = len;
1274 actualLength += len;
1277 uint16 frame = OHCI_ITD_GET_STARTING_FRAME(descriptor->flags);
1278 _ReleaseIsochronousBandwidth(frame,
1279 OHCI_ITD_GET_FRAME_COUNT(descriptor->flags));
1281 TRACE("ITD %p done\n", descriptor);
1283 if (descriptor == (ohci_isochronous_td*)transfer->last_descriptor)
1284 break;
1286 descriptor
1287 = (ohci_isochronous_td *)descriptor->next_done_descriptor;
1291 // remove the transfer from the list first so we are sure
1292 // it doesn't get canceled while we still process it
1293 if (Lock()) {
1294 if (*_lastTransfer)
1295 (*_lastTransfer)->link = transfer->link;
1297 if (transfer == fFirstTransfer)
1298 fFirstTransfer = transfer->link;
1299 if (transfer == fLastTransfer)
1300 fLastTransfer = *_lastTransfer;
1302 // store the currently processing pipe here so we can wait
1303 // in cancel if we are processing something on the target pipe
1304 if (!transfer->canceled)
1305 fProcessingPipe = transfer->transfer->TransferPipe();
1307 transfer->link = NULL;
1308 Unlock();
1311 // break the descriptor chain on the last descriptor
1312 transfer->last_descriptor->next_logical_descriptor = NULL;
1313 TRACE("iso.transfer %p done with status 0x%08" B_PRIx32 " len:%ld\n",
1314 transfer, callbackStatus, actualLength);
1316 // if canceled the callback has already been called
1317 if (!transfer->canceled) {
1318 if (callbackStatus == B_OK && actualLength > 0) {
1319 if (transfer->data_descriptor && transfer->incoming) {
1320 // data to read out
1321 iovec *vector = transfer->transfer->Vector();
1322 size_t vectorCount = transfer->transfer->VectorCount();
1324 transfer->transfer->PrepareKernelAccess();
1325 _ReadIsochronousDescriptorChain(
1326 (ohci_isochronous_td*)transfer->data_descriptor,
1327 vector, vectorCount);
1331 transfer->transfer->Finished(callbackStatus, actualLength);
1332 fProcessingPipe = NULL;
1335 _FreeIsochronousDescriptorChain(
1336 (ohci_isochronous_td*)transfer->first_descriptor);
1338 return true;
1342 status_t
1343 OHCI::_SubmitRequest(Transfer *transfer)
1345 usb_request_data *requestData = transfer->RequestData();
1346 bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) != 0;
1348 ohci_general_td *setupDescriptor
1349 = _CreateGeneralDescriptor(sizeof(usb_request_data));
1350 if (!setupDescriptor) {
1351 TRACE_ERROR("failed to allocate setup descriptor\n");
1352 return B_NO_MEMORY;
1355 setupDescriptor->flags = OHCI_TD_DIRECTION_PID_SETUP
1356 | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1357 | OHCI_TD_TOGGLE_0
1358 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
1360 ohci_general_td *statusDescriptor = _CreateGeneralDescriptor(0);
1361 if (!statusDescriptor) {
1362 TRACE_ERROR("failed to allocate status descriptor\n");
1363 _FreeGeneralDescriptor(setupDescriptor);
1364 return B_NO_MEMORY;
1367 statusDescriptor->flags
1368 = (directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN)
1369 | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1370 | OHCI_TD_TOGGLE_1
1371 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1373 iovec vector;
1374 vector.iov_base = requestData;
1375 vector.iov_len = sizeof(usb_request_data);
1376 _WriteDescriptorChain(setupDescriptor, &vector, 1);
1378 status_t result;
1379 ohci_general_td *dataDescriptor = NULL;
1380 if (transfer->VectorCount() > 0) {
1381 ohci_general_td *lastDescriptor = NULL;
1382 result = _CreateDescriptorChain(&dataDescriptor, &lastDescriptor,
1383 directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT,
1384 transfer->VectorLength());
1385 if (result < B_OK) {
1386 _FreeGeneralDescriptor(setupDescriptor);
1387 _FreeGeneralDescriptor(statusDescriptor);
1388 return result;
1391 if (!directionIn) {
1392 _WriteDescriptorChain(dataDescriptor, transfer->Vector(),
1393 transfer->VectorCount());
1396 _LinkDescriptors(setupDescriptor, dataDescriptor);
1397 _LinkDescriptors(lastDescriptor, statusDescriptor);
1398 } else {
1399 _LinkDescriptors(setupDescriptor, statusDescriptor);
1402 // Add to the transfer list
1403 ohci_endpoint_descriptor *endpoint
1404 = (ohci_endpoint_descriptor *)transfer->TransferPipe()->ControllerCookie();
1406 MutexLocker endpointLocker(endpoint->lock);
1407 result = _AddPendingTransfer(transfer, endpoint, setupDescriptor,
1408 dataDescriptor, statusDescriptor, directionIn);
1409 if (result < B_OK) {
1410 TRACE_ERROR("failed to add pending transfer\n");
1411 _FreeDescriptorChain(setupDescriptor);
1412 return result;
1415 // Add the descriptor chain to the endpoint
1416 _SwitchEndpointTail(endpoint, setupDescriptor, statusDescriptor);
1417 endpointLocker.Unlock();
1419 // Tell the controller to process the control list
1420 endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1421 _WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED);
1422 return B_OK;
1426 status_t
1427 OHCI::_SubmitTransfer(Transfer *transfer)
1429 Pipe *pipe = transfer->TransferPipe();
1430 bool directionIn = (pipe->Direction() == Pipe::In);
1432 ohci_general_td *firstDescriptor = NULL;
1433 ohci_general_td *lastDescriptor = NULL;
1434 status_t result = _CreateDescriptorChain(&firstDescriptor, &lastDescriptor,
1435 directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT,
1436 transfer->VectorLength());
1438 if (result < B_OK)
1439 return result;
1441 // Apply data toggle to the first descriptor (the others will use the carry)
1442 firstDescriptor->flags &= ~OHCI_TD_TOGGLE_CARRY;
1443 firstDescriptor->flags |= pipe->DataToggle() ? OHCI_TD_TOGGLE_1
1444 : OHCI_TD_TOGGLE_0;
1446 // Set the last descriptor to generate an interrupt
1447 lastDescriptor->flags &= ~OHCI_TD_INTERRUPT_MASK;
1448 lastDescriptor->flags |=
1449 OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1451 if (!directionIn) {
1452 _WriteDescriptorChain(firstDescriptor, transfer->Vector(),
1453 transfer->VectorCount());
1456 // Add to the transfer list
1457 ohci_endpoint_descriptor *endpoint
1458 = (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1460 MutexLocker endpointLocker(endpoint->lock);
1461 result = _AddPendingTransfer(transfer, endpoint, firstDescriptor,
1462 firstDescriptor, lastDescriptor, directionIn);
1463 if (result < B_OK) {
1464 TRACE_ERROR("failed to add pending transfer\n");
1465 _FreeDescriptorChain(firstDescriptor);
1466 return result;
1469 // Add the descriptor chain to the endpoint
1470 _SwitchEndpointTail(endpoint, firstDescriptor, lastDescriptor);
1471 endpointLocker.Unlock();
1473 endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1474 if (pipe->Type() & USB_OBJECT_BULK_PIPE) {
1475 // Tell the controller to process the bulk list
1476 _WriteReg(OHCI_COMMAND_STATUS, OHCI_BULK_LIST_FILLED);
1479 return B_OK;
1483 status_t
1484 OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
1486 Pipe *pipe = transfer->TransferPipe();
1487 bool directionIn = (pipe->Direction() == Pipe::In);
1488 usb_isochronous_data *isochronousData = transfer->IsochronousData();
1490 ohci_isochronous_td *firstDescriptor = NULL;
1491 ohci_isochronous_td *lastDescriptor = NULL;
1492 status_t result = _CreateIsochronousDescriptorChain(&firstDescriptor,
1493 &lastDescriptor, transfer);
1495 if (firstDescriptor == 0 || lastDescriptor == 0)
1496 return B_ERROR;
1498 if (result < B_OK)
1499 return result;
1501 // Set the last descriptor to generate an interrupt
1502 lastDescriptor->flags &= ~OHCI_ITD_INTERRUPT_MASK;
1503 // let the controller retire last ITD
1504 lastDescriptor->flags |= OHCI_ITD_SET_DELAY_INTERRUPT(1);
1506 // If direction is out set every descriptor data
1507 if (pipe->Direction() == Pipe::Out)
1508 _WriteIsochronousDescriptorChain(firstDescriptor,
1509 transfer->Vector(), transfer->VectorCount());
1510 else
1511 // Initialize the packet descriptors
1512 for (uint32 i = 0; i < isochronousData->packet_count; i++) {
1513 isochronousData->packet_descriptors[i].actual_length = 0;
1514 isochronousData->packet_descriptors[i].status = B_NO_INIT;
1517 // Add to the transfer list
1518 ohci_endpoint_descriptor *endpoint
1519 = (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1521 MutexLocker endpointLocker(endpoint->lock);
1522 result = _AddPendingIsochronousTransfer(transfer, endpoint,
1523 firstDescriptor, lastDescriptor, directionIn);
1524 if (result < B_OK) {
1525 TRACE_ERROR("failed to add pending iso.transfer:"
1526 "0x%08" B_PRIx32 "\n", result);
1527 _FreeIsochronousDescriptorChain(firstDescriptor);
1528 return result;
1531 // Add the descriptor chain to the endpoint
1532 _SwitchIsochronousEndpointTail(endpoint, firstDescriptor, lastDescriptor);
1533 endpointLocker.Unlock();
1535 endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1537 return B_OK;
1541 void
1542 OHCI::_SwitchEndpointTail(ohci_endpoint_descriptor *endpoint,
1543 ohci_general_td *first, ohci_general_td *last)
1545 // fill in the information of the first descriptor into the current tail
1546 ohci_general_td *tail = (ohci_general_td *)endpoint->tail_logical_descriptor;
1547 tail->flags = first->flags;
1548 tail->buffer_physical = first->buffer_physical;
1549 tail->next_physical_descriptor = first->next_physical_descriptor;
1550 tail->last_physical_byte_address = first->last_physical_byte_address;
1551 tail->buffer_size = first->buffer_size;
1552 tail->buffer_logical = first->buffer_logical;
1553 tail->next_logical_descriptor = first->next_logical_descriptor;
1555 // the first descriptor becomes the new tail
1556 first->flags = 0;
1557 first->buffer_physical = 0;
1558 first->next_physical_descriptor = 0;
1559 first->last_physical_byte_address = 0;
1560 first->buffer_size = 0;
1561 first->buffer_logical = NULL;
1562 first->next_logical_descriptor = NULL;
1564 if (first == last)
1565 _LinkDescriptors(tail, first);
1566 else
1567 _LinkDescriptors(last, first);
1569 // update the endpoint tail pointer to reflect the change
1570 endpoint->tail_logical_descriptor = first;
1571 endpoint->tail_physical_descriptor = (uint32)first->physical_address;
1572 TRACE("switched tail from %p to %p\n", tail, first);
1574 #if 0
1575 _PrintEndpoint(endpoint);
1576 _PrintDescriptorChain(tail);
1577 #endif
1581 void
1582 OHCI::_SwitchIsochronousEndpointTail(ohci_endpoint_descriptor *endpoint,
1583 ohci_isochronous_td *first, ohci_isochronous_td *last)
1585 // fill in the information of the first descriptor into the current tail
1586 ohci_isochronous_td *tail
1587 = (ohci_isochronous_td*)endpoint->tail_logical_descriptor;
1588 tail->flags = first->flags;
1589 tail->buffer_page_byte_0 = first->buffer_page_byte_0;
1590 tail->next_physical_descriptor = first->next_physical_descriptor;
1591 tail->last_byte_address = first->last_byte_address;
1592 tail->buffer_size = first->buffer_size;
1593 tail->buffer_logical = first->buffer_logical;
1594 tail->next_logical_descriptor = first->next_logical_descriptor;
1595 tail->next_done_descriptor = first->next_done_descriptor;
1597 // the first descriptor becomes the new tail
1598 first->flags = 0;
1599 first->buffer_page_byte_0 = 0;
1600 first->next_physical_descriptor = 0;
1601 first->last_byte_address = 0;
1602 first->buffer_size = 0;
1603 first->buffer_logical = NULL;
1604 first->next_logical_descriptor = NULL;
1605 first->next_done_descriptor = NULL;
1607 for (int i = 0; i < OHCI_ITD_NOFFSET; i++) {
1608 tail->offset[i] = first->offset[i];
1609 first->offset[i] = 0;
1612 if (first == last)
1613 _LinkIsochronousDescriptors(tail, first, NULL);
1614 else
1615 _LinkIsochronousDescriptors(last, first, NULL);
1617 // update the endpoint tail pointer to reflect the change
1618 endpoint->tail_logical_descriptor = first;
1619 endpoint->tail_physical_descriptor = (uint32)first->physical_address;
1620 TRACE("switched tail from %p to %p\n", tail, first);
1622 #if 0
1623 _PrintEndpoint(endpoint);
1624 _PrintDescriptorChain(tail);
1625 #endif
1629 void
1630 OHCI::_RemoveTransferFromEndpoint(transfer_data *transfer)
1632 // The transfer failed and the endpoint was halted. This means that the
1633 // endpoint head pointer might point somewhere into the descriptor chain
1634 // of this transfer. As we do not know if this transfer actually caused
1635 // the halt on the endpoint we have to make sure this is the case. If we
1636 // find the head to point to somewhere into the descriptor chain then
1637 // simply advancing the head pointer to the link of the last transfer
1638 // will bring the endpoint into a valid state again. This operation is
1639 // safe as the endpoint is currently halted and we therefore can change
1640 // the head pointer.
1641 ohci_endpoint_descriptor *endpoint = transfer->endpoint;
1642 ohci_general_td *descriptor = transfer->first_descriptor;
1643 while (descriptor) {
1644 if ((endpoint->head_physical_descriptor & OHCI_ENDPOINT_HEAD_MASK)
1645 == descriptor->physical_address) {
1646 // This descriptor caused the halt. Advance the head pointer. This
1647 // will either move the head to the next valid transfer that can
1648 // then be restarted, or it will move the head to the tail when
1649 // there are no more transfer descriptors. Setting the head will
1650 // also clear the halt state as it is stored in the first bit of
1651 // the head pointer.
1652 endpoint->head_physical_descriptor
1653 = transfer->last_descriptor->next_physical_descriptor;
1654 return;
1657 descriptor = (ohci_general_td *)descriptor->next_logical_descriptor;
1662 ohci_endpoint_descriptor *
1663 OHCI::_AllocateEndpoint()
1665 ohci_endpoint_descriptor *endpoint;
1666 phys_addr_t physicalAddress;
1668 mutex *lock = (mutex *)malloc(sizeof(mutex));
1669 if (lock == NULL) {
1670 TRACE_ERROR("no memory to allocate endpoint lock\n");
1671 return NULL;
1674 // Allocate memory chunk
1675 if (fStack->AllocateChunk((void **)&endpoint, &physicalAddress,
1676 sizeof(ohci_endpoint_descriptor)) < B_OK) {
1677 TRACE_ERROR("failed to allocate endpoint descriptor\n");
1678 free(lock);
1679 return NULL;
1682 mutex_init(lock, "ohci endpoint lock");
1684 endpoint->flags = OHCI_ENDPOINT_SKIP;
1685 endpoint->physical_address = (uint32)physicalAddress;
1686 endpoint->head_physical_descriptor = 0;
1687 endpoint->tail_logical_descriptor = NULL;
1688 endpoint->tail_physical_descriptor = 0;
1689 endpoint->next_logical_endpoint = NULL;
1690 endpoint->next_physical_endpoint = 0;
1691 endpoint->lock = lock;
1692 return endpoint;
1696 void
1697 OHCI::_FreeEndpoint(ohci_endpoint_descriptor *endpoint)
1699 if (!endpoint)
1700 return;
1702 mutex_destroy(endpoint->lock);
1703 free(endpoint->lock);
1705 fStack->FreeChunk((void *)endpoint, endpoint->physical_address,
1706 sizeof(ohci_endpoint_descriptor));
1710 status_t
1711 OHCI::_InsertEndpointForPipe(Pipe *pipe)
1713 TRACE("inserting endpoint for device %u endpoint %u\n",
1714 pipe->DeviceAddress(), pipe->EndpointAddress());
1716 ohci_endpoint_descriptor *endpoint = _AllocateEndpoint();
1717 if (!endpoint) {
1718 TRACE_ERROR("cannot allocate memory for endpoint\n");
1719 return B_NO_MEMORY;
1722 uint32 flags = OHCI_ENDPOINT_SKIP;
1724 // Set up device and endpoint address
1725 flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(pipe->DeviceAddress())
1726 | OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(pipe->EndpointAddress());
1728 // Set the direction
1729 switch (pipe->Direction()) {
1730 case Pipe::In:
1731 flags |= OHCI_ENDPOINT_DIRECTION_IN;
1732 break;
1734 case Pipe::Out:
1735 flags |= OHCI_ENDPOINT_DIRECTION_OUT;
1736 break;
1738 case Pipe::Default:
1739 flags |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR;
1740 break;
1742 default:
1743 TRACE_ERROR("direction unknown\n");
1744 _FreeEndpoint(endpoint);
1745 return B_ERROR;
1748 // Set up the speed
1749 switch (pipe->Speed()) {
1750 case USB_SPEED_LOWSPEED:
1751 flags |= OHCI_ENDPOINT_LOW_SPEED;
1752 break;
1754 case USB_SPEED_FULLSPEED:
1755 flags |= OHCI_ENDPOINT_FULL_SPEED;
1756 break;
1758 default:
1759 TRACE_ERROR("unacceptable speed\n");
1760 _FreeEndpoint(endpoint);
1761 return B_ERROR;
1764 // Set the maximum packet size
1765 flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(pipe->MaxPacketSize());
1766 endpoint->flags = flags;
1768 // Add the endpoint to the appropriate list
1769 uint32 type = pipe->Type();
1770 ohci_endpoint_descriptor *head = NULL;
1771 if (type & USB_OBJECT_CONTROL_PIPE)
1772 head = fDummyControl;
1773 else if (type & USB_OBJECT_BULK_PIPE)
1774 head = fDummyBulk;
1775 else if (type & USB_OBJECT_INTERRUPT_PIPE)
1776 head = _FindInterruptEndpoint(pipe->Interval());
1777 else if (type & USB_OBJECT_ISO_PIPE)
1778 head = fDummyIsochronous;
1779 else
1780 TRACE_ERROR("unknown pipe type\n");
1782 if (head == NULL) {
1783 TRACE_ERROR("no list found for endpoint\n");
1784 _FreeEndpoint(endpoint);
1785 return B_ERROR;
1788 // Create (necessary) tail descriptor
1789 if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
1790 // Set the isochronous bit format
1791 endpoint->flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
1792 ohci_isochronous_td *tail = _CreateIsochronousDescriptor(0);
1793 tail->flags = 0;
1794 endpoint->tail_logical_descriptor = tail;
1795 endpoint->head_physical_descriptor = tail->physical_address;
1796 endpoint->tail_physical_descriptor = tail->physical_address;
1797 } else {
1798 ohci_general_td *tail = _CreateGeneralDescriptor(0);
1799 tail->flags = 0;
1800 endpoint->tail_logical_descriptor = tail;
1801 endpoint->head_physical_descriptor = tail->physical_address;
1802 endpoint->tail_physical_descriptor = tail->physical_address;
1805 if (!_LockEndpoints()) {
1806 if (endpoint->tail_logical_descriptor) {
1807 _FreeGeneralDescriptor(
1808 (ohci_general_td *)endpoint->tail_logical_descriptor);
1811 _FreeEndpoint(endpoint);
1812 return B_ERROR;
1815 pipe->SetControllerCookie((void *)endpoint);
1816 endpoint->next_logical_endpoint = head->next_logical_endpoint;
1817 endpoint->next_physical_endpoint = head->next_physical_endpoint;
1818 head->next_logical_endpoint = (void *)endpoint;
1819 head->next_physical_endpoint = (uint32)endpoint->physical_address;
1821 _UnlockEndpoints();
1822 return B_OK;
1826 status_t
1827 OHCI::_RemoveEndpointForPipe(Pipe *pipe)
1829 TRACE("removing endpoint for device %u endpoint %u\n",
1830 pipe->DeviceAddress(), pipe->EndpointAddress());
1832 ohci_endpoint_descriptor *endpoint
1833 = (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1834 if (endpoint == NULL)
1835 return B_OK;
1837 // TODO implement properly, but at least disable it for now
1838 endpoint->flags |= OHCI_ENDPOINT_SKIP;
1839 return B_OK;
1843 ohci_endpoint_descriptor *
1844 OHCI::_FindInterruptEndpoint(uint8 interval)
1846 uint32 index = 0;
1847 uint32 power = 1;
1848 while (power <= OHCI_BIGGEST_INTERVAL / 2) {
1849 if (power * 2 > interval)
1850 break;
1852 power *= 2;
1853 index++;
1856 return fInterruptEndpoints[index];
1860 ohci_general_td *
1861 OHCI::_CreateGeneralDescriptor(size_t bufferSize)
1863 ohci_general_td *descriptor;
1864 phys_addr_t physicalAddress;
1866 if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
1867 sizeof(ohci_general_td)) != B_OK) {
1868 TRACE_ERROR("failed to allocate general descriptor\n");
1869 return NULL;
1872 descriptor->physical_address = (uint32)physicalAddress;
1873 descriptor->next_physical_descriptor = 0;
1874 descriptor->next_logical_descriptor = NULL;
1875 descriptor->buffer_size = bufferSize;
1876 if (bufferSize == 0) {
1877 descriptor->buffer_physical = 0;
1878 descriptor->buffer_logical = NULL;
1879 descriptor->last_physical_byte_address = 0;
1880 return descriptor;
1883 if (fStack->AllocateChunk(&descriptor->buffer_logical,
1884 &physicalAddress, bufferSize) != B_OK) {
1885 TRACE_ERROR("failed to allocate space for buffer\n");
1886 fStack->FreeChunk(descriptor, descriptor->physical_address,
1887 sizeof(ohci_general_td));
1888 return NULL;
1890 descriptor->buffer_physical = physicalAddress;
1892 descriptor->last_physical_byte_address
1893 = descriptor->buffer_physical + bufferSize - 1;
1894 return descriptor;
1898 void
1899 OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor)
1901 if (!descriptor)
1902 return;
1904 if (descriptor->buffer_logical) {
1905 fStack->FreeChunk(descriptor->buffer_logical,
1906 descriptor->buffer_physical, descriptor->buffer_size);
1909 fStack->FreeChunk((void *)descriptor, descriptor->physical_address,
1910 sizeof(ohci_general_td));
1914 status_t
1915 OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor,
1916 ohci_general_td **_lastDescriptor, uint32 direction, size_t bufferSize)
1918 size_t blockSize = 8192;
1919 int32 descriptorCount = (bufferSize + blockSize - 1) / blockSize;
1920 if (descriptorCount == 0)
1921 descriptorCount = 1;
1923 ohci_general_td *firstDescriptor = NULL;
1924 ohci_general_td *lastDescriptor = *_firstDescriptor;
1925 for (int32 i = 0; i < descriptorCount; i++) {
1926 ohci_general_td *descriptor = _CreateGeneralDescriptor(
1927 min_c(blockSize, bufferSize));
1929 if (!descriptor) {
1930 _FreeDescriptorChain(firstDescriptor);
1931 return B_NO_MEMORY;
1934 descriptor->flags = direction
1935 | OHCI_TD_BUFFER_ROUNDING
1936 | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1937 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE)
1938 | OHCI_TD_TOGGLE_CARRY;
1940 // link to previous
1941 if (lastDescriptor)
1942 _LinkDescriptors(lastDescriptor, descriptor);
1944 bufferSize -= blockSize;
1945 lastDescriptor = descriptor;
1946 if (!firstDescriptor)
1947 firstDescriptor = descriptor;
1950 *_firstDescriptor = firstDescriptor;
1951 *_lastDescriptor = lastDescriptor;
1952 return B_OK;
1956 void
1957 OHCI::_FreeDescriptorChain(ohci_general_td *topDescriptor)
1959 ohci_general_td *current = topDescriptor;
1960 ohci_general_td *next = NULL;
1962 while (current) {
1963 next = (ohci_general_td *)current->next_logical_descriptor;
1964 _FreeGeneralDescriptor(current);
1965 current = next;
1970 ohci_isochronous_td *
1971 OHCI::_CreateIsochronousDescriptor(size_t bufferSize)
1973 ohci_isochronous_td *descriptor = NULL;
1974 phys_addr_t physicalAddress;
1976 if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
1977 sizeof(ohci_isochronous_td)) != B_OK) {
1978 TRACE_ERROR("failed to allocate isochronous descriptor\n");
1979 return NULL;
1982 descriptor->physical_address = (uint32)physicalAddress;
1983 descriptor->next_physical_descriptor = 0;
1984 descriptor->next_logical_descriptor = NULL;
1985 descriptor->next_done_descriptor = NULL;
1986 descriptor->buffer_size = bufferSize;
1987 if (bufferSize == 0) {
1988 descriptor->buffer_page_byte_0 = 0;
1989 descriptor->buffer_logical = NULL;
1990 descriptor->last_byte_address = 0;
1991 return descriptor;
1994 if (fStack->AllocateChunk(&descriptor->buffer_logical,
1995 &physicalAddress, bufferSize) != B_OK) {
1996 TRACE_ERROR("failed to allocate space for iso.buffer\n");
1997 fStack->FreeChunk(descriptor, descriptor->physical_address,
1998 sizeof(ohci_isochronous_td));
1999 return NULL;
2001 descriptor->buffer_page_byte_0 = (uint32)physicalAddress;
2002 descriptor->last_byte_address
2003 = descriptor->buffer_page_byte_0 + bufferSize - 1;
2005 return descriptor;
2009 void
2010 OHCI::_FreeIsochronousDescriptor(ohci_isochronous_td *descriptor)
2012 if (!descriptor)
2013 return;
2015 if (descriptor->buffer_logical) {
2016 fStack->FreeChunk(descriptor->buffer_logical,
2017 descriptor->buffer_page_byte_0, descriptor->buffer_size);
2020 fStack->FreeChunk((void *)descriptor, descriptor->physical_address,
2021 sizeof(ohci_general_td));
2025 status_t
2026 OHCI::_CreateIsochronousDescriptorChain(ohci_isochronous_td **_firstDescriptor,
2027 ohci_isochronous_td **_lastDescriptor, Transfer *transfer)
2029 Pipe *pipe = transfer->TransferPipe();
2030 usb_isochronous_data *isochronousData = transfer->IsochronousData();
2032 size_t dataLength = transfer->VectorLength();
2033 size_t packet_count = isochronousData->packet_count;
2035 if (packet_count == 0) {
2036 TRACE_ERROR("isochronous packet_count should not be equal to zero.");
2037 return B_BAD_VALUE;
2040 size_t packetSize = dataLength / packet_count;
2041 if (dataLength % packet_count != 0)
2042 packetSize++;
2044 if (packetSize > pipe->MaxPacketSize()) {
2045 TRACE_ERROR("isochronous packetSize %ld is bigger"
2046 " than pipe MaxPacketSize %ld.", packetSize, pipe->MaxPacketSize());
2047 return B_BAD_VALUE;
2050 uint16 bandwidth = transfer->Bandwidth() / packet_count;
2051 if (transfer->Bandwidth() % packet_count != 0)
2052 bandwidth++;
2054 ohci_isochronous_td *firstDescriptor = NULL;
2055 ohci_isochronous_td *lastDescriptor = *_firstDescriptor;
2057 // the frame number currently processed by the host controller
2058 uint16 currentFrame = fHcca->current_frame_number & 0xFFFF;
2059 uint16 safeFrames = 5;
2061 // The entry where to start inserting the first Isochronous descriptor
2062 // real frame number may differ in case provided one has not bandwidth
2063 if (isochronousData->flags & USB_ISO_ASAP ||
2064 isochronousData->starting_frame_number == NULL)
2065 // We should stay about 5-10 ms ahead of the controller
2066 // USB1 frame is equal to 1 ms
2067 currentFrame += safeFrames;
2068 else
2069 currentFrame = *isochronousData->starting_frame_number;
2071 uint16 packets = packet_count;
2072 uint16 frameOffset = 0;
2073 while (packets > 0) {
2074 // look for up to 8 continous frames with available bandwidth
2075 uint16 frameCount = 0;
2076 while (frameCount < min_c(OHCI_ITD_NOFFSET, packets)
2077 && _AllocateIsochronousBandwidth(frameOffset + currentFrame
2078 + frameCount, bandwidth))
2079 frameCount++;
2081 if (frameCount == 0) {
2082 // starting frame has no bandwidth for our transaction - try next
2083 if (++frameOffset >= 0xFFFF) {
2084 TRACE_ERROR("failed to allocate bandwidth\n");
2085 _FreeIsochronousDescriptorChain(firstDescriptor);
2086 return B_NO_MEMORY;
2088 continue;
2091 ohci_isochronous_td *descriptor = _CreateIsochronousDescriptor(
2092 packetSize * frameCount);
2094 if (!descriptor) {
2095 TRACE_ERROR("failed to allocate ITD\n");
2096 _ReleaseIsochronousBandwidth(currentFrame + frameOffset, frameCount);
2097 _FreeIsochronousDescriptorChain(firstDescriptor);
2098 return B_NO_MEMORY;
2101 uint16 pageOffset = descriptor->buffer_page_byte_0 & 0xfff;
2102 descriptor->buffer_page_byte_0 &= ~0xfff;
2103 for (uint16 i = 0; i < frameCount; i++) {
2104 descriptor->offset[OHCI_ITD_OFFSET_IDX(i)]
2105 = OHCI_ITD_MK_OFFS(pageOffset + packetSize * i);
2108 descriptor->flags = OHCI_ITD_SET_FRAME_COUNT(frameCount)
2109 | OHCI_ITD_SET_CONDITION_CODE(OHCI_ITD_CONDITION_NOT_ACCESSED)
2110 | OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_ITD_INTERRUPT_NONE)
2111 | OHCI_ITD_SET_STARTING_FRAME(currentFrame + frameOffset);
2113 // the last packet may be shorter than other ones in this transfer
2114 if (packets <= OHCI_ITD_NOFFSET)
2115 descriptor->last_byte_address
2116 += dataLength - packetSize * (packet_count);
2118 // link to previous
2119 if (lastDescriptor)
2120 _LinkIsochronousDescriptors(lastDescriptor, descriptor, descriptor);
2122 lastDescriptor = descriptor;
2123 if (!firstDescriptor)
2124 firstDescriptor = descriptor;
2126 packets -= frameCount;
2128 frameOffset += frameCount;
2130 if (packets == 0 && isochronousData->starting_frame_number)
2131 *isochronousData->starting_frame_number = currentFrame + frameOffset;
2134 *_firstDescriptor = firstDescriptor;
2135 *_lastDescriptor = lastDescriptor;
2137 return B_OK;
2141 void
2142 OHCI::_FreeIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor)
2144 ohci_isochronous_td *current = topDescriptor;
2145 ohci_isochronous_td *next = NULL;
2147 while (current) {
2148 next = (ohci_isochronous_td *)current->next_done_descriptor;
2149 _FreeIsochronousDescriptor(current);
2150 current = next;
2155 size_t
2156 OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
2157 size_t vectorCount)
2159 ohci_general_td *current = topDescriptor;
2160 size_t actualLength = 0;
2161 size_t vectorIndex = 0;
2162 size_t vectorOffset = 0;
2163 size_t bufferOffset = 0;
2165 while (current) {
2166 if (!current->buffer_logical)
2167 break;
2169 while (true) {
2170 size_t length = min_c(current->buffer_size - bufferOffset,
2171 vector[vectorIndex].iov_len - vectorOffset);
2173 TRACE("copying %ld bytes to bufferOffset %ld from"
2174 " vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
2175 vectorOffset, vectorIndex, vectorCount);
2176 memcpy((uint8 *)current->buffer_logical + bufferOffset,
2177 (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
2179 actualLength += length;
2180 vectorOffset += length;
2181 bufferOffset += length;
2183 if (vectorOffset >= vector[vectorIndex].iov_len) {
2184 if (++vectorIndex >= vectorCount) {
2185 TRACE("wrote descriptor chain (%ld bytes, no"
2186 " more vectors)\n", actualLength);
2187 return actualLength;
2190 vectorOffset = 0;
2193 if (bufferOffset >= current->buffer_size) {
2194 bufferOffset = 0;
2195 break;
2199 if (!current->next_logical_descriptor)
2200 break;
2202 current = (ohci_general_td *)current->next_logical_descriptor;
2205 TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
2206 return actualLength;
2210 size_t
2211 OHCI::_WriteIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor,
2212 iovec *vector, size_t vectorCount)
2214 ohci_isochronous_td *current = topDescriptor;
2215 size_t actualLength = 0;
2216 size_t vectorIndex = 0;
2217 size_t vectorOffset = 0;
2218 size_t bufferOffset = 0;
2220 while (current) {
2221 if (!current->buffer_logical)
2222 break;
2224 while (true) {
2225 size_t length = min_c(current->buffer_size - bufferOffset,
2226 vector[vectorIndex].iov_len - vectorOffset);
2228 TRACE("copying %ld bytes to bufferOffset %ld from"
2229 " vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
2230 vectorOffset, vectorIndex, vectorCount);
2231 memcpy((uint8 *)current->buffer_logical + bufferOffset,
2232 (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
2234 actualLength += length;
2235 vectorOffset += length;
2236 bufferOffset += length;
2238 if (vectorOffset >= vector[vectorIndex].iov_len) {
2239 if (++vectorIndex >= vectorCount) {
2240 TRACE("wrote descriptor chain (%ld bytes, no"
2241 " more vectors)\n", actualLength);
2242 return actualLength;
2245 vectorOffset = 0;
2248 if (bufferOffset >= current->buffer_size) {
2249 bufferOffset = 0;
2250 break;
2254 if (!current->next_logical_descriptor)
2255 break;
2257 current = (ohci_isochronous_td *)current->next_logical_descriptor;
2260 TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
2261 return actualLength;
2265 size_t
2266 OHCI::_ReadDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
2267 size_t vectorCount)
2269 ohci_general_td *current = topDescriptor;
2270 size_t actualLength = 0;
2271 size_t vectorIndex = 0;
2272 size_t vectorOffset = 0;
2273 size_t bufferOffset = 0;
2275 while (current && OHCI_TD_GET_CONDITION_CODE(current->flags)
2276 != OHCI_TD_CONDITION_NOT_ACCESSED) {
2277 if (!current->buffer_logical)
2278 break;
2280 size_t bufferSize = current->buffer_size;
2281 if (current->buffer_physical != 0) {
2282 bufferSize -= current->last_physical_byte_address
2283 - current->buffer_physical + 1;
2286 while (true) {
2287 size_t length = min_c(bufferSize - bufferOffset,
2288 vector[vectorIndex].iov_len - vectorOffset);
2290 TRACE("copying %ld bytes to vectorOffset %ld from"
2291 " bufferOffset %ld at index %ld of %ld\n", length, vectorOffset,
2292 bufferOffset, vectorIndex, vectorCount);
2293 memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
2294 (uint8 *)current->buffer_logical + bufferOffset, length);
2296 actualLength += length;
2297 vectorOffset += length;
2298 bufferOffset += length;
2300 if (vectorOffset >= vector[vectorIndex].iov_len) {
2301 if (++vectorIndex >= vectorCount) {
2302 TRACE("read descriptor chain (%ld bytes, no more vectors)\n",
2303 actualLength);
2304 return actualLength;
2307 vectorOffset = 0;
2310 if (bufferOffset >= bufferSize) {
2311 bufferOffset = 0;
2312 break;
2316 current = (ohci_general_td *)current->next_logical_descriptor;
2319 TRACE("read descriptor chain (%ld bytes)\n", actualLength);
2320 return actualLength;
2324 void
2325 OHCI::_ReadIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor,
2326 iovec *vector, size_t vectorCount)
2328 ohci_isochronous_td *current = topDescriptor;
2329 size_t actualLength = 0;
2330 size_t vectorIndex = 0;
2331 size_t vectorOffset = 0;
2332 size_t bufferOffset = 0;
2334 while (current && OHCI_ITD_GET_CONDITION_CODE(current->flags)
2335 != OHCI_ITD_CONDITION_NOT_ACCESSED) {
2336 size_t bufferSize = current->buffer_size;
2337 if (current->buffer_logical != NULL && bufferSize > 0) {
2338 while (true) {
2339 size_t length = min_c(bufferSize - bufferOffset,
2340 vector[vectorIndex].iov_len - vectorOffset);
2342 TRACE("copying %ld bytes to vectorOffset %ld from bufferOffset"
2343 " %ld at index %ld of %ld\n", length, vectorOffset,
2344 bufferOffset, vectorIndex, vectorCount);
2345 memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
2346 (uint8 *)current->buffer_logical + bufferOffset, length);
2348 actualLength += length;
2349 vectorOffset += length;
2350 bufferOffset += length;
2352 if (vectorOffset >= vector[vectorIndex].iov_len) {
2353 if (++vectorIndex >= vectorCount) {
2354 TRACE("read descriptor chain (%ld bytes, "
2355 "no more vectors)\n", actualLength);
2356 return;
2359 vectorOffset = 0;
2362 if (bufferOffset >= bufferSize) {
2363 bufferOffset = 0;
2364 break;
2369 current = (ohci_isochronous_td *)current->next_done_descriptor;
2372 TRACE("read descriptor chain (%ld bytes)\n", actualLength);
2373 return;
2377 size_t
2378 OHCI::_ReadActualLength(ohci_general_td *topDescriptor)
2380 ohci_general_td *current = topDescriptor;
2381 size_t actualLength = 0;
2383 while (current && OHCI_TD_GET_CONDITION_CODE(current->flags)
2384 != OHCI_TD_CONDITION_NOT_ACCESSED) {
2385 size_t length = current->buffer_size;
2386 if (current->buffer_physical != 0) {
2387 length -= current->last_physical_byte_address
2388 - current->buffer_physical + 1;
2391 actualLength += length;
2392 current = (ohci_general_td *)current->next_logical_descriptor;
2395 TRACE("read actual length (%ld bytes)\n", actualLength);
2396 return actualLength;
2400 void
2401 OHCI::_LinkDescriptors(ohci_general_td *first, ohci_general_td *second)
2403 first->next_physical_descriptor = second->physical_address;
2404 first->next_logical_descriptor = second;
2408 void
2409 OHCI::_LinkIsochronousDescriptors(ohci_isochronous_td *first,
2410 ohci_isochronous_td *second, ohci_isochronous_td *nextDone)
2412 first->next_physical_descriptor = second->physical_address;
2413 first->next_logical_descriptor = second;
2414 first->next_done_descriptor = nextDone;
2418 bool
2419 OHCI::_AllocateIsochronousBandwidth(uint16 frame, uint16 size)
2421 frame %= NUMBER_OF_FRAMES;
2422 if (size > fFrameBandwidth[frame])
2423 return false;
2425 fFrameBandwidth[frame]-= size;
2426 return true;
2430 void
2431 OHCI::_ReleaseIsochronousBandwidth(uint16 startFrame, uint16 frameCount)
2433 for (size_t index = 0; index < frameCount; index++) {
2434 uint16 frame = (startFrame + index) % NUMBER_OF_FRAMES;
2435 fFrameBandwidth[frame] = MAX_AVAILABLE_BANDWIDTH;
2440 status_t
2441 OHCI::_GetStatusOfConditionCode(uint8 conditionCode)
2443 switch (conditionCode) {
2444 case OHCI_TD_CONDITION_NO_ERROR:
2445 return B_OK;
2447 case OHCI_TD_CONDITION_CRC_ERROR:
2448 case OHCI_TD_CONDITION_BIT_STUFFING:
2449 case OHCI_TD_CONDITION_TOGGLE_MISMATCH:
2450 return B_DEV_CRC_ERROR;
2452 case OHCI_TD_CONDITION_STALL:
2453 return B_DEV_STALLED;
2455 case OHCI_TD_CONDITION_NO_RESPONSE:
2456 return B_TIMED_OUT;
2458 case OHCI_TD_CONDITION_PID_CHECK_FAILURE:
2459 return B_DEV_BAD_PID;
2461 case OHCI_TD_CONDITION_UNEXPECTED_PID:
2462 return B_DEV_UNEXPECTED_PID;
2464 case OHCI_TD_CONDITION_DATA_OVERRUN:
2465 return B_DEV_DATA_OVERRUN;
2467 case OHCI_TD_CONDITION_DATA_UNDERRUN:
2468 return B_DEV_DATA_UNDERRUN;
2470 case OHCI_TD_CONDITION_BUFFER_OVERRUN:
2471 return B_DEV_FIFO_OVERRUN;
2473 case OHCI_TD_CONDITION_BUFFER_UNDERRUN:
2474 return B_DEV_FIFO_UNDERRUN;
2476 case OHCI_TD_CONDITION_NOT_ACCESSED:
2477 return B_DEV_PENDING;
2479 case 0x0E:
2480 return B_DEV_TOO_LATE; // PSW: _NOT_ACCESSED
2482 default:
2483 break;
2486 return B_ERROR;
2490 bool
2491 OHCI::_LockEndpoints()
2493 return (mutex_lock(&fEndpointLock) == B_OK);
2497 void
2498 OHCI::_UnlockEndpoints()
2500 mutex_unlock(&fEndpointLock);
2504 inline void
2505 OHCI::_WriteReg(uint32 reg, uint32 value)
2507 *(volatile uint32 *)(fOperationalRegisters + reg) = value;
2511 inline uint32
2512 OHCI::_ReadReg(uint32 reg)
2514 return *(volatile uint32 *)(fOperationalRegisters + reg);
2518 void
2519 OHCI::_PrintEndpoint(ohci_endpoint_descriptor *endpoint)
2521 dprintf("endpoint %p\n", endpoint);
2522 dprintf("\tflags........... 0x%08" B_PRIx32 "\n", endpoint->flags);
2523 dprintf("\ttail_physical... 0x%08" B_PRIx32 "\n", endpoint->tail_physical_descriptor);
2524 dprintf("\thead_physical... 0x%08" B_PRIx32 "\n", endpoint->head_physical_descriptor);
2525 dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", endpoint->next_physical_endpoint);
2526 dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", endpoint->physical_address);
2527 dprintf("\ttail_logical.... %p\n", endpoint->tail_logical_descriptor);
2528 dprintf("\tnext_logical.... %p\n", endpoint->next_logical_endpoint);
2532 void
2533 OHCI::_PrintDescriptorChain(ohci_general_td *topDescriptor)
2535 while (topDescriptor) {
2536 dprintf("descriptor %p\n", topDescriptor);
2537 dprintf("\tflags........... 0x%08" B_PRIx32 "\n", topDescriptor->flags);
2538 dprintf("\tbuffer_physical. 0x%08" B_PRIx32 "\n", topDescriptor->buffer_physical);
2539 dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", topDescriptor->next_physical_descriptor);
2540 dprintf("\tlast_byte....... 0x%08" B_PRIx32 "\n", topDescriptor->last_physical_byte_address);
2541 dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", topDescriptor->physical_address);
2542 dprintf("\tbuffer_size..... %lu\n", topDescriptor->buffer_size);
2543 dprintf("\tbuffer_logical.. %p\n", topDescriptor->buffer_logical);
2544 dprintf("\tnext_logical.... %p\n", topDescriptor->next_logical_descriptor);
2546 topDescriptor = (ohci_general_td *)topDescriptor->next_logical_descriptor;
2551 void
2552 OHCI::_PrintDescriptorChain(ohci_isochronous_td *topDescriptor)
2554 while (topDescriptor) {
2555 dprintf("iso.descriptor %p\n", topDescriptor);
2556 dprintf("\tflags........... 0x%08" B_PRIx32 "\n", topDescriptor->flags);
2557 dprintf("\tbuffer_pagebyte0 0x%08" B_PRIx32 "\n", topDescriptor->buffer_page_byte_0);
2558 dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", topDescriptor->next_physical_descriptor);
2559 dprintf("\tlast_byte....... 0x%08" B_PRIx32 "\n", topDescriptor->last_byte_address);
2560 dprintf("\toffset:\n\t0x%04x 0x%04x 0x%04x 0x%04x\n"
2561 "\t0x%04x 0x%04x 0x%04x 0x%04x\n",
2562 topDescriptor->offset[0], topDescriptor->offset[1],
2563 topDescriptor->offset[2], topDescriptor->offset[3],
2564 topDescriptor->offset[4], topDescriptor->offset[5],
2565 topDescriptor->offset[6], topDescriptor->offset[7]);
2566 dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", topDescriptor->physical_address);
2567 dprintf("\tbuffer_size..... %lu\n", topDescriptor->buffer_size);
2568 dprintf("\tbuffer_logical.. %p\n", topDescriptor->buffer_logical);
2569 dprintf("\tnext_logical.... %p\n", topDescriptor->next_logical_descriptor);
2570 dprintf("\tnext_done....... %p\n", topDescriptor->next_done_descriptor);
2572 topDescriptor = (ohci_isochronous_td *)topDescriptor->next_done_descriptor;