xref: /haiku/src/add-ons/kernel/busses/usb/ohci.cpp (revision 04b1c44b89086a9521bb478c8e99d024cef8f6a6)
1 /*
2  * Copyright 2005-2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Jan-Rixt Van Hoye
7  *		Salvatore Benedetto <salvatore.benedetto@gmail.com>
8  *		Michael Lotz <mmlr@mlotz.ch>
9  */
10 
11 #include <module.h>
12 #include <PCI.h>
13 #include <PCI_x86.h>
14 #include <USB3.h>
15 #include <KernelExport.h>
16 #include <util/AutoLock.h>
17 
18 #include "ohci.h"
19 
20 #define USB_MODULE_NAME "ohci"
21 
22 pci_module_info *OHCI::sPCIModule = NULL;
23 pci_x86_module_info *OHCI::sPCIx86Module = NULL;
24 
25 
26 static int32
27 ohci_std_ops(int32 op, ...)
28 {
29 	switch (op)	{
30 		case B_MODULE_INIT:
31 			TRACE_MODULE("init module\n");
32 			return B_OK;
33 		case B_MODULE_UNINIT:
34 			TRACE_MODULE("uninit module\n");
35 			return B_OK;
36 	}
37 
38 	return EINVAL;
39 }
40 
41 
42 usb_host_controller_info ohci_module = {
43 	{
44 		"busses/usb/ohci",
45 		0,
46 		ohci_std_ops
47 	},
48 	NULL,
49 	OHCI::AddTo
50 };
51 
52 
53 module_info *modules[] = {
54 	(module_info *)&ohci_module,
55 	NULL
56 };
57 
58 
59 OHCI::OHCI(pci_info *info, Stack *stack)
60 	:	BusManager(stack),
61 		fPCIInfo(info),
62 		fStack(stack),
63 		fOperationalRegisters(NULL),
64 		fRegisterArea(-1),
65 		fHccaArea(-1),
66 		fHcca(NULL),
67 		fInterruptEndpoints(NULL),
68 		fDummyControl(NULL),
69 		fDummyBulk(NULL),
70 		fDummyIsochronous(NULL),
71 		fFirstTransfer(NULL),
72 		fLastTransfer(NULL),
73 		fFinishTransfersSem(-1),
74 		fFinishThread(-1),
75 		fStopFinishThread(false),
76 		fProcessingPipe(NULL),
77 		fRootHub(NULL),
78 		fRootHubAddress(0),
79 		fPortCount(0)
80 {
81 	if (!fInitOK) {
82 		TRACE_ERROR("bus manager failed to init\n");
83 		return;
84 	}
85 
86 	TRACE("constructing new OHCI host controller driver\n");
87 	fInitOK = false;
88 
89 	mutex_init(&fEndpointLock, "ohci endpoint lock");
90 
91 	// enable busmaster and memory mapped access
92 	uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
93 		fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
94 	command &= ~PCI_command_io;
95 	command |= PCI_command_master | PCI_command_memory;
96 
97 	sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
98 		fPCIInfo->function, PCI_command, 2, command);
99 
100 	// map the registers
101 	uint32 offset = sPCIModule->read_pci_config(fPCIInfo->bus,
102 		fPCIInfo->device, fPCIInfo->function, PCI_base_registers, 4);
103 	offset &= PCI_address_memory_32_mask;
104 	TRACE_ALWAYS("iospace offset: 0x%lx\n", offset);
105 	fRegisterArea = map_physical_memory("OHCI memory mapped registers",
106 		offset,	B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS,
107 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA,
108 		(void **)&fOperationalRegisters);
109 	if (fRegisterArea < B_OK) {
110 		TRACE_ERROR("failed to map register memory\n");
111 		return;
112 	}
113 
114 	TRACE("mapped operational registers: %p\n", fOperationalRegisters);
115 
116 	// Check the revision of the controller, which should be 10h
117 	uint32 revision = _ReadReg(OHCI_REVISION) & 0xff;
118 	TRACE("version %ld.%ld%s\n", OHCI_REVISION_HIGH(revision),
119 		OHCI_REVISION_LOW(revision), OHCI_REVISION_LEGACY(revision)
120 		? ", legacy support" : "");
121 	if (OHCI_REVISION_HIGH(revision) != 1 || OHCI_REVISION_LOW(revision) != 0) {
122 		TRACE_ERROR("unsupported OHCI revision\n");
123 		return;
124 	}
125 
126 	void *hccaPhysicalAddress;
127 	fHccaArea = fStack->AllocateArea((void **)&fHcca, &hccaPhysicalAddress,
128 		sizeof(ohci_hcca), "USB OHCI Host Controller Communication Area");
129 
130 	if (fHccaArea < B_OK) {
131 		TRACE_ERROR("unable to create the HCCA block area\n");
132 		return;
133 	}
134 
135 	memset(fHcca, 0, sizeof(ohci_hcca));
136 
137 	// Set Up Host controller
138 	// Dummy endpoints
139 	fDummyControl = _AllocateEndpoint();
140 	if (!fDummyControl)
141 		return;
142 
143 	fDummyBulk = _AllocateEndpoint();
144 	if (!fDummyBulk) {
145 		_FreeEndpoint(fDummyControl);
146 		return;
147 	}
148 
149 	fDummyIsochronous = _AllocateEndpoint();
150 	if (!fDummyIsochronous) {
151 		_FreeEndpoint(fDummyControl);
152 		_FreeEndpoint(fDummyBulk);
153 		return;
154 	}
155 
156 	// Static endpoints that get linked in the HCCA
157 	fInterruptEndpoints = new(std::nothrow)
158 		ohci_endpoint_descriptor *[OHCI_STATIC_ENDPOINT_COUNT];
159 	if (!fInterruptEndpoints) {
160 		TRACE_ERROR("failed to allocate memory for interrupt endpoints\n");
161 		_FreeEndpoint(fDummyControl);
162 		_FreeEndpoint(fDummyBulk);
163 		_FreeEndpoint(fDummyIsochronous);
164 		return;
165 	}
166 
167 	for (int32 i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
168 		fInterruptEndpoints[i] = _AllocateEndpoint();
169 		if (!fInterruptEndpoints[i]) {
170 			TRACE_ERROR("failed to allocate interrupt endpoint %ld", i);
171 			while (--i >= 0)
172 				_FreeEndpoint(fInterruptEndpoints[i]);
173 			_FreeEndpoint(fDummyBulk);
174 			_FreeEndpoint(fDummyControl);
175 			_FreeEndpoint(fDummyIsochronous);
176 			return;
177 		}
178 	}
179 
180 	// build flat tree so that at each of the static interrupt endpoints
181 	// fInterruptEndpoints[i] == interrupt endpoint for interval 2^i
182 	uint32 interval = OHCI_BIGGEST_INTERVAL;
183 	uint32 intervalIndex = OHCI_STATIC_ENDPOINT_COUNT - 1;
184 	while (interval > 1) {
185 		uint32 insertIndex = interval / 2;
186 		while (insertIndex < OHCI_BIGGEST_INTERVAL) {
187 			fHcca->interrupt_table[insertIndex]
188 				= fInterruptEndpoints[intervalIndex]->physical_address;
189 			insertIndex += interval;
190 		}
191 
192 		intervalIndex--;
193 		interval /= 2;
194 	}
195 
196 	// setup the empty slot in the list and linking of all -> first
197 	fHcca->interrupt_table[0] = fInterruptEndpoints[0]->physical_address;
198 	for (int32 i = 1; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
199 		fInterruptEndpoints[i]->next_physical_endpoint
200 			= fInterruptEndpoints[0]->physical_address;
201 		fInterruptEndpoints[i]->next_logical_endpoint
202 			= fInterruptEndpoints[0];
203 	}
204 
205 	// Now link the first endpoint to the isochronous endpoint
206 	fInterruptEndpoints[0]->next_physical_endpoint
207 		= fDummyIsochronous->physical_address;
208 
209 	// When the handover from SMM takes place, all interrupts are routed to the
210 	// OS. As we don't yet have an interrupt handler installed at this point,
211 	// this may cause interrupt storms if the firmware does not disable the
212 	// interrupts during handover. Therefore we disable interrupts before
213 	// requesting ownership. We have to keep the ownership change interrupt
214 	// enabled though, as otherwise the SMM will not be notified of the
215 	// ownership change request we trigger below.
216 	_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS &
217 		~OHCI_OWNERSHIP_CHANGE) ;
218 
219 	// Determine in what context we are running (Kindly copied from FreeBSD)
220 	uint32 control = _ReadReg(OHCI_CONTROL);
221 	if (control & OHCI_INTERRUPT_ROUTING) {
222 		TRACE_ALWAYS("smm is in control of the host controller\n");
223 		uint32 status = _ReadReg(OHCI_COMMAND_STATUS);
224 		_WriteReg(OHCI_COMMAND_STATUS, status | OHCI_OWNERSHIP_CHANGE_REQUEST);
225 		for (uint32 i = 0; i < 100 && (control & OHCI_INTERRUPT_ROUTING); i++) {
226 			snooze(1000);
227 			control = _ReadReg(OHCI_CONTROL);
228 		}
229 
230 		if ((control & OHCI_INTERRUPT_ROUTING) != 0) {
231 			TRACE_ERROR("smm does not respond.\n");
232 
233 			// TODO: Enable this reset as soon as the non-specified
234 			// reset a few lines later is replaced by a better solution.
235 			//_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
236 			//snooze(USB_DELAY_BUS_RESET);
237 		} else
238 			TRACE_ALWAYS("ownership change successful\n");
239 	} else {
240 		TRACE("cold started\n");
241 		snooze(USB_DELAY_BUS_RESET);
242 	}
243 
244 	// TODO: This reset delays system boot time. It should not be necessary
245 	// according to the OHCI spec, but without it some controllers don't start.
246 	_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
247 	snooze(USB_DELAY_BUS_RESET);
248 
249 	// We now own the host controller and the bus has been reset
250 	uint32 frameInterval = _ReadReg(OHCI_FRAME_INTERVAL);
251 	uint32 intervalValue = OHCI_GET_INTERVAL_VALUE(frameInterval);
252 
253 	_WriteReg(OHCI_COMMAND_STATUS, OHCI_HOST_CONTROLLER_RESET);
254 	// Nominal time for a reset is 10 us
255 	uint32 reset = 0;
256 	for (uint32 i = 0; i < 10; i++) {
257 		spin(10);
258 		reset = _ReadReg(OHCI_COMMAND_STATUS) & OHCI_HOST_CONTROLLER_RESET;
259 		if (reset == 0)
260 			break;
261 	}
262 
263 	if (reset) {
264 		TRACE_ERROR("error resetting the host controller (timeout)\n");
265 		return;
266 	}
267 
268 	// The controller is now in SUSPEND state, we have 2ms to go OPERATIONAL.
269 
270 	// Set up host controller register
271 	_WriteReg(OHCI_HCCA, (uint32)hccaPhysicalAddress);
272 	_WriteReg(OHCI_CONTROL_HEAD_ED, (uint32)fDummyControl->physical_address);
273 	_WriteReg(OHCI_BULK_HEAD_ED, (uint32)fDummyBulk->physical_address);
274 	// Switch on desired functional features
275 	control = _ReadReg(OHCI_CONTROL);
276 	control &= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK | OHCI_ENABLE_LIST
277 		| OHCI_HC_FUNCTIONAL_STATE_MASK | OHCI_INTERRUPT_ROUTING);
278 	control |= OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4
279 		| OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL;
280 	// And finally start the controller
281 	_WriteReg(OHCI_CONTROL, control);
282 
283 	// The controller is now OPERATIONAL.
284 	frameInterval = (_ReadReg(OHCI_FRAME_INTERVAL) & OHCI_FRAME_INTERVAL_TOGGLE)
285 		^ OHCI_FRAME_INTERVAL_TOGGLE;
286 	frameInterval |= OHCI_FSMPS(intervalValue) | intervalValue;
287 	_WriteReg(OHCI_FRAME_INTERVAL, frameInterval);
288 	// 90% periodic
289 	uint32 periodic = OHCI_PERIODIC(intervalValue);
290 	_WriteReg(OHCI_PERIODIC_START, periodic);
291 
292 	// Fiddle the No Over Current Protection bit to avoid chip bug
293 	uint32 desca = _ReadReg(OHCI_RH_DESCRIPTOR_A);
294 	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca | OHCI_RH_NO_OVER_CURRENT_PROTECTION);
295 	_WriteReg(OHCI_RH_STATUS, OHCI_RH_LOCAL_POWER_STATUS_CHANGE);
296 	snooze(OHCI_ENABLE_POWER_DELAY);
297 	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca);
298 
299 	// The AMD756 requires a delay before re-reading the register,
300 	// otherwise it will occasionally report 0 ports.
301 	uint32 numberOfPorts = 0;
302 	for (uint32 i = 0; i < 10 && numberOfPorts == 0; i++) {
303 		snooze(OHCI_READ_DESC_DELAY);
304 		uint32 descriptor = _ReadReg(OHCI_RH_DESCRIPTOR_A);
305 		numberOfPorts = OHCI_RH_GET_PORT_COUNT(descriptor);
306 	}
307 	if (numberOfPorts > OHCI_MAX_PORT_COUNT)
308 		numberOfPorts = OHCI_MAX_PORT_COUNT;
309 	fPortCount = numberOfPorts;
310 	TRACE("port count is %d\n", fPortCount);
311 
312 	// Create semaphore the finisher thread will wait for
313 	fFinishTransfersSem = create_sem(0, "OHCI Finish Transfers");
314 	if (fFinishTransfersSem < B_OK) {
315 		TRACE_ERROR("failed to create semaphore\n");
316 		return;
317 	}
318 
319 	// Create the finisher service thread
320 	fFinishThread = spawn_kernel_thread(_FinishThread, "ohci finish thread",
321 		B_URGENT_DISPLAY_PRIORITY, (void *)this);
322 	resume_thread(fFinishThread);
323 
324 	// Find the right interrupt vector, using MSIs if available.
325 	uint8 interruptVector = fPCIInfo->u.h0.interrupt_line;
326 	if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus,
327 			fPCIInfo->device, fPCIInfo->function) >= 1) {
328 		uint8 msiVector = 0;
329 		if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device,
330 				fPCIInfo->function, 1, &msiVector) == B_OK
331 			&& sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device,
332 				fPCIInfo->function) == B_OK) {
333 			TRACE_ALWAYS("using message signaled interrupts\n");
334 			interruptVector = msiVector;
335 		}
336 	}
337 
338 	// Install the interrupt handler
339 	TRACE("installing interrupt handler\n");
340 	install_io_interrupt_handler(interruptVector, _InterruptHandler,
341 		(void *)this, 0);
342 
343 	// Enable interesting interrupts now that the handler is in place
344 	_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS
345 		| OHCI_MASTER_INTERRUPT_ENABLE);
346 
347 	TRACE("OHCI host controller driver constructed\n");
348 	fInitOK = true;
349 }
350 
351 
352 OHCI::~OHCI()
353 {
354 	int32 result = 0;
355 	fStopFinishThread = true;
356 	delete_sem(fFinishTransfersSem);
357 	wait_for_thread(fFinishThread, &result);
358 
359 	_LockEndpoints();
360 	mutex_destroy(&fEndpointLock);
361 
362 	if (fHccaArea >= B_OK)
363 		delete_area(fHccaArea);
364 	if (fRegisterArea >= B_OK)
365 		delete_area(fRegisterArea);
366 
367 	_FreeEndpoint(fDummyControl);
368 	_FreeEndpoint(fDummyBulk);
369 	_FreeEndpoint(fDummyIsochronous);
370 
371 	if (fInterruptEndpoints != NULL) {
372 		for (int i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++)
373 			_FreeEndpoint(fInterruptEndpoints[i]);
374 	}
375 
376 	delete [] fInterruptEndpoints;
377 	delete fRootHub;
378 
379 	put_module(B_PCI_MODULE_NAME);
380 }
381 
382 
383 status_t
384 OHCI::Start()
385 {
386 	TRACE("starting OHCI host controller\n");
387 
388 	uint32 control = _ReadReg(OHCI_CONTROL);
389 	if ((control & OHCI_HC_FUNCTIONAL_STATE_MASK)
390 		!= OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL) {
391 		TRACE_ERROR("controller not started (0x%08lx)!\n", control);
392 		return B_ERROR;
393 	} else
394 		TRACE("controller is operational!\n");
395 
396 	fRootHubAddress = AllocateAddress();
397 	fRootHub = new(std::nothrow) OHCIRootHub(RootObject(), fRootHubAddress);
398 	if (!fRootHub) {
399 		TRACE_ERROR("no memory to allocate root hub\n");
400 		return B_NO_MEMORY;
401 	}
402 
403 	if (fRootHub->InitCheck() < B_OK) {
404 		TRACE_ERROR("root hub failed init check\n");
405 		return B_ERROR;
406 	}
407 
408 	SetRootHub(fRootHub);
409 	TRACE_ALWAYS("successfully started the controller\n");
410 	return BusManager::Start();
411 }
412 
413 
414 status_t
415 OHCI::SubmitTransfer(Transfer *transfer)
416 {
417 	// short circuit the root hub
418 	if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
419 		return fRootHub->ProcessTransfer(this, transfer);
420 
421 	uint32 type = transfer->TransferPipe()->Type();
422 	if (type & USB_OBJECT_CONTROL_PIPE) {
423 		TRACE("submitting request\n");
424 		return _SubmitRequest(transfer);
425 	}
426 
427 	if ((type & USB_OBJECT_BULK_PIPE) || (type & USB_OBJECT_INTERRUPT_PIPE)) {
428 		TRACE("submitting %s transfer\n",
429 			(type & USB_OBJECT_BULK_PIPE) ? "bulk" : "interrupt");
430 		return _SubmitTransfer(transfer);
431 	}
432 
433 	if (type & USB_OBJECT_ISO_PIPE) {
434 		TRACE("submitting isochronous transfer\n");
435 		return _SubmitIsochronousTransfer(transfer);
436 	}
437 
438 	TRACE_ERROR("tried to submit transfer for unknown pipe type %lu\n", type);
439 	return B_ERROR;
440 }
441 
442 
443 status_t
444 OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
445 {
446 	if (pipe->Type() & USB_OBJECT_ISO_PIPE)
447 		return _CancelQueuedIsochronousTransfers(pipe, force);
448 
449 	if (!Lock())
450 		return B_ERROR;
451 
452 	struct transfer_entry {
453 		Transfer *			transfer;
454 		transfer_entry *	next;
455 	};
456 
457 	transfer_entry *list = NULL;
458 	transfer_data *current = fFirstTransfer;
459 	while (current) {
460 		if (current->transfer && current->transfer->TransferPipe() == pipe) {
461 			// Check if the skip bit is already set
462 			if (!(current->endpoint->flags & OHCI_ENDPOINT_SKIP)) {
463 				current->endpoint->flags |= OHCI_ENDPOINT_SKIP;
464 				// In case the controller is processing
465 				// this endpoint, wait for it to finish
466 				snooze(1000);
467 			}
468 
469 			// Clear the endpoint
470 			current->endpoint->head_physical_descriptor
471 				= current->endpoint->tail_physical_descriptor;
472 
473 			if (!force) {
474 				// If the transfer is canceled by force, the one causing the
475 				// cancel is probably not the one who initiated the transfer
476 				// and the callback is likely not safe anymore
477 				transfer_entry *entry
478 					= (transfer_entry *)malloc(sizeof(transfer_entry));
479 				if (entry != NULL) {
480 					entry->transfer = current->transfer;
481 					current->transfer = NULL;
482 					entry->next = list;
483 					list = entry;
484 				}
485 			}
486 			current->canceled = true;
487 		}
488 		current = current->link;
489 	}
490 
491 	Unlock();
492 
493 	while (list != NULL) {
494 		transfer_entry *next = list->next;
495 		list->transfer->Finished(B_CANCELED, 0);
496 		delete list->transfer;
497 		free(list);
498 		list = next;
499 	}
500 
501 	// wait for any transfers that might have made it before canceling
502 	while (fProcessingPipe == pipe)
503 		snooze(1000);
504 
505 	// notify the finisher so it can clean up the canceled transfers
506 	release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
507 	return B_OK;
508 }
509 
510 
511 status_t
512 OHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
513 {
514 	TRACE("pipe change %d for pipe 0x%08lx\n", change, (uint32)pipe);
515 	if (pipe->DeviceAddress() == fRootHubAddress) {
516 		// no need to insert/remove endpoint descriptors for the root hub
517 		return B_OK;
518 	}
519 
520 	switch (change) {
521 		case USB_CHANGE_CREATED:
522 			return _InsertEndpointForPipe(pipe);
523 
524 		case USB_CHANGE_DESTROYED:
525 			return _RemoveEndpointForPipe(pipe);
526 
527 		case USB_CHANGE_PIPE_POLICY_CHANGED:
528 			TRACE("pipe policy changing unhandled!\n");
529 			break;
530 
531 		default:
532 			TRACE_ERROR("unknown pipe change!\n");
533 			return B_ERROR;
534 	}
535 
536 	return B_OK;
537 }
538 
539 
540 status_t
541 OHCI::AddTo(Stack *stack)
542 {
543 #ifdef TRACE_USB
544 	set_dprintf_enabled(true);
545 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
546 	load_driver_symbols("ohci");
547 #endif
548 #endif
549 
550 	if (!sPCIModule) {
551 		status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
552 		if (status < B_OK) {
553 			TRACE_MODULE_ERROR("getting pci module failed! 0x%08lx\n", status);
554 			return status;
555 		}
556 	}
557 
558 	TRACE_MODULE("searching devices\n");
559 	bool found = false;
560 	pci_info *item = new(std::nothrow) pci_info;
561 	if (!item) {
562 		sPCIModule = NULL;
563 		put_module(B_PCI_MODULE_NAME);
564 		return B_NO_MEMORY;
565 	}
566 
567 	// Try to get the PCI x86 module as well so we can enable possible MSIs.
568 	if (sPCIx86Module == NULL && get_module(B_PCI_X86_MODULE_NAME,
569 			(module_info **)&sPCIx86Module) != B_OK) {
570 		// If it isn't there, that's not critical though.
571 		TRACE_MODULE_ERROR("failed to get pci x86 module\n");
572 		sPCIx86Module = NULL;
573 	}
574 
575 	for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
576 		if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
577 			&& item->class_api == PCI_usb_ohci) {
578 			if (item->u.h0.interrupt_line == 0
579 				|| item->u.h0.interrupt_line == 0xFF) {
580 				TRACE_MODULE_ERROR("found device with invalid IRQ -"
581 					" check IRQ assignement\n");
582 				continue;
583 			}
584 
585 			TRACE_MODULE("found device at IRQ %u\n",
586 				item->u.h0.interrupt_line);
587 			OHCI *bus = new(std::nothrow) OHCI(item, stack);
588 			if (!bus) {
589 				delete item;
590 				sPCIModule = NULL;
591 				put_module(B_PCI_MODULE_NAME);
592 
593 				if (sPCIx86Module != NULL) {
594 					sPCIx86Module = NULL;
595 					put_module(B_PCI_X86_MODULE_NAME);
596 				}
597 
598 				return B_NO_MEMORY;
599 			}
600 
601 			if (bus->InitCheck() < B_OK) {
602 				TRACE_MODULE_ERROR("bus failed init check\n");
603 				delete bus;
604 				continue;
605 			}
606 
607 			// the bus took it away
608 			item = new(std::nothrow) pci_info;
609 
610 			bus->Start();
611 			stack->AddBusManager(bus);
612 			found = true;
613 		}
614 	}
615 
616 	if (!found) {
617 		TRACE_MODULE_ERROR("no devices found\n");
618 		delete item;
619 		sPCIModule = NULL;
620 		put_module(B_PCI_MODULE_NAME);
621 
622 		if (sPCIx86Module != NULL) {
623 			sPCIx86Module = NULL;
624 			put_module(B_PCI_X86_MODULE_NAME);
625 		}
626 
627 		return ENODEV;
628 	}
629 
630 	delete item;
631 	return B_OK;
632 }
633 
634 
635 status_t
636 OHCI::GetPortStatus(uint8 index, usb_port_status *status)
637 {
638 	if (index >= fPortCount) {
639 		TRACE_ERROR("get port status for invalid port %u\n", index);
640 		return B_BAD_INDEX;
641 	}
642 
643 	status->status = status->change = 0;
644 	uint32 portStatus = _ReadReg(OHCI_RH_PORT_STATUS(index));
645 
646 	// status
647 	if (portStatus & OHCI_RH_PORTSTATUS_CCS)
648 		status->status |= PORT_STATUS_CONNECTION;
649 	if (portStatus & OHCI_RH_PORTSTATUS_PES)
650 		status->status |= PORT_STATUS_ENABLE;
651 	if (portStatus & OHCI_RH_PORTSTATUS_PSS)
652 		status->status |= PORT_STATUS_SUSPEND;
653 	if (portStatus & OHCI_RH_PORTSTATUS_POCI)
654 		status->status |= PORT_STATUS_OVER_CURRENT;
655 	if (portStatus & OHCI_RH_PORTSTATUS_PRS)
656 		status->status |= PORT_STATUS_RESET;
657 	if (portStatus & OHCI_RH_PORTSTATUS_PPS)
658 		status->status |= PORT_STATUS_POWER;
659 	if (portStatus & OHCI_RH_PORTSTATUS_LSDA)
660 		status->status |= PORT_STATUS_LOW_SPEED;
661 
662 	// change
663 	if (portStatus & OHCI_RH_PORTSTATUS_CSC)
664 		status->change |= PORT_STATUS_CONNECTION;
665 	if (portStatus & OHCI_RH_PORTSTATUS_PESC)
666 		status->change |= PORT_STATUS_ENABLE;
667 	if (portStatus & OHCI_RH_PORTSTATUS_PSSC)
668 		status->change |= PORT_STATUS_SUSPEND;
669 	if (portStatus & OHCI_RH_PORTSTATUS_OCIC)
670 		status->change |= PORT_STATUS_OVER_CURRENT;
671 	if (portStatus & OHCI_RH_PORTSTATUS_PRSC)
672 		status->change |= PORT_STATUS_RESET;
673 
674 	TRACE("port %u status 0x%04x change 0x%04x\n", index,
675 		status->status, status->change);
676 	return B_OK;
677 }
678 
679 
680 status_t
681 OHCI::SetPortFeature(uint8 index, uint16 feature)
682 {
683 	TRACE("set port feature index %u feature %u\n", index, feature);
684 	if (index > fPortCount)
685 		return B_BAD_INDEX;
686 
687 	switch (feature) {
688 		case PORT_ENABLE:
689 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PES);
690 			return B_OK;
691 
692 		case PORT_SUSPEND:
693 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSS);
694 			return B_OK;
695 
696 		case PORT_RESET:
697 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRS);
698 			return B_OK;
699 
700 		case PORT_POWER:
701 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PPS);
702 			return B_OK;
703 	}
704 
705 	return B_BAD_VALUE;
706 }
707 
708 
709 status_t
710 OHCI::ClearPortFeature(uint8 index, uint16 feature)
711 {
712 	TRACE("clear port feature index %u feature %u\n", index, feature);
713 	if (index > fPortCount)
714 		return B_BAD_INDEX;
715 
716 	switch (feature) {
717 		case PORT_ENABLE:
718 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CCS);
719 			return B_OK;
720 
721 		case PORT_SUSPEND:
722 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_POCI);
723 			return B_OK;
724 
725 		case PORT_POWER:
726 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_LSDA);
727 			return B_OK;
728 
729 		case C_PORT_CONNECTION:
730 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CSC);
731 			return B_OK;
732 
733 		case C_PORT_ENABLE:
734 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PESC);
735 			return B_OK;
736 
737 		case C_PORT_SUSPEND:
738 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSSC);
739 			return B_OK;
740 
741 		case C_PORT_OVER_CURRENT:
742 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_OCIC);
743 			return B_OK;
744 
745 		case C_PORT_RESET:
746 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRSC);
747 			return B_OK;
748 	}
749 
750 	return B_BAD_VALUE;
751 }
752 
753 
754 int32
755 OHCI::_InterruptHandler(void *data)
756 {
757 	return ((OHCI *)data)->_Interrupt();
758 }
759 
760 
761 int32
762 OHCI::_Interrupt()
763 {
764 	static spinlock lock = B_SPINLOCK_INITIALIZER;
765 	acquire_spinlock(&lock);
766 
767 	uint32 status = 0;
768 	uint32 acknowledge = 0;
769 	bool finishTransfers = false;
770 	int32 result = B_HANDLED_INTERRUPT;
771 
772 	// The LSb of done_head is used to inform the HCD that an interrupt
773 	// condition exists for both the done list and for another event recorded in
774 	// the HcInterruptStatus register. If done_head is 0, then the interrupt
775 	// was caused by other than the HccaDoneHead update and the
776 	// HcInterruptStatus register needs to be accessed to determine that exact
777 	// interrupt cause. If HccDoneHead is nonzero, then a done list update
778 	// interrupt is indicated and if the LSb of the Dword is nonzero, then an
779 	// additional interrupt event is indicated and HcInterruptStatus should be
780 	// checked to determine its cause.
781 	uint32 doneHead = fHcca->done_head;
782 	if (doneHead != 0) {
783 		status = OHCI_WRITEBACK_DONE_HEAD;
784 		if (doneHead & OHCI_DONE_INTERRUPTS)
785 			status |= _ReadReg(OHCI_INTERRUPT_STATUS)
786 				& _ReadReg(OHCI_INTERRUPT_ENABLE);
787 	} else {
788 		status = _ReadReg(OHCI_INTERRUPT_STATUS) & _ReadReg(OHCI_INTERRUPT_ENABLE)
789 			& ~OHCI_WRITEBACK_DONE_HEAD;
790 		if (status == 0) {
791 			// Nothing to be done (PCI shared interrupt)
792 			release_spinlock(&lock);
793 			return B_UNHANDLED_INTERRUPT;
794 		}
795 	}
796 
797 	if (status & OHCI_SCHEDULING_OVERRUN) {
798 		TRACE_MODULE("scheduling overrun occured\n");
799 		acknowledge |= OHCI_SCHEDULING_OVERRUN;
800 	}
801 
802 	if (status & OHCI_WRITEBACK_DONE_HEAD) {
803 		TRACE_MODULE("transfer descriptors processed\n");
804 		fHcca->done_head = 0;
805 		acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
806 		result = B_INVOKE_SCHEDULER;
807 		finishTransfers = true;
808 	}
809 
810 	if (status & OHCI_RESUME_DETECTED) {
811 		TRACE_MODULE("resume detected\n");
812 		acknowledge |= OHCI_RESUME_DETECTED;
813 	}
814 
815 	if (status & OHCI_UNRECOVERABLE_ERROR) {
816 		TRACE_MODULE_ERROR("unrecoverable error - controller halted\n");
817 		_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
818 		// TODO: clear all pending transfers, reset and resetup the controller
819 	}
820 
821 	if (status & OHCI_ROOT_HUB_STATUS_CHANGE) {
822 		TRACE_MODULE("root hub status change\n");
823 		// Disable the interrupt as it will otherwise be retriggered until the
824 		// port has been reset and the change is cleared explicitly.
825 		// TODO: renable it once we use status changes instead of polling
826 		_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ROOT_HUB_STATUS_CHANGE);
827 		acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE;
828 	}
829 
830 	if (acknowledge != 0)
831 		_WriteReg(OHCI_INTERRUPT_STATUS, acknowledge);
832 
833 	release_spinlock(&lock);
834 
835 	if (finishTransfers)
836 		release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
837 
838 	return result;
839 }
840 
841 
842 status_t
843 OHCI::_AddPendingTransfer(Transfer *transfer,
844 	ohci_endpoint_descriptor *endpoint, ohci_general_td *firstDescriptor,
845 	ohci_general_td *dataDescriptor, ohci_general_td *lastDescriptor,
846 	bool directionIn)
847 {
848 	if (!transfer || !endpoint || !lastDescriptor)
849 		return B_BAD_VALUE;
850 
851 	transfer_data *data = new(std::nothrow) transfer_data;
852 	if (!data)
853 		return B_NO_MEMORY;
854 
855 	status_t result = transfer->InitKernelAccess();
856 	if (result < B_OK) {
857 		delete data;
858 		return result;
859 	}
860 
861 	data->transfer = transfer;
862 	data->endpoint = endpoint;
863 	data->incoming = directionIn;
864 	data->canceled = false;
865 	data->link = NULL;
866 
867 	// the current tail will become the first descriptor
868 	data->first_descriptor = (ohci_general_td *)endpoint->tail_logical_descriptor;
869 
870 	// the data and first descriptors might be the same
871 	if (dataDescriptor == firstDescriptor)
872 		data->data_descriptor = data->first_descriptor;
873 	else
874 		data->data_descriptor = dataDescriptor;
875 
876 	// even the last and the first descriptor might be the same
877 	if (lastDescriptor == firstDescriptor)
878 		data->last_descriptor = data->first_descriptor;
879 	else
880 		data->last_descriptor = lastDescriptor;
881 
882 	if (!Lock()) {
883 		delete data;
884 		return B_ERROR;
885 	}
886 
887 	if (fLastTransfer)
888 		fLastTransfer->link = data;
889 	else
890 		fFirstTransfer = data;
891 
892 	fLastTransfer = data;
893 	Unlock();
894 
895 	return B_OK;
896 }
897 
898 
899 status_t
900 OHCI::_CancelQueuedIsochronousTransfers(Pipe *pipe, bool force)
901 {
902 	// TODO
903 	return B_ERROR;
904 }
905 
906 
907 int32
908 OHCI::_FinishThread(void *data)
909 {
910 	((OHCI *)data)->_FinishTransfers();
911 	return B_OK;
912 }
913 
914 
915 void
916 OHCI::_FinishTransfers()
917 {
918 	while (!fStopFinishThread) {
919 		if (acquire_sem(fFinishTransfersSem) < B_OK)
920 			continue;
921 
922 		// eat up sems that have been released by multiple interrupts
923 		int32 semCount = 0;
924 		get_sem_count(fFinishTransfersSem, &semCount);
925 		if (semCount > 0)
926 			acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
927 
928 		if (!Lock())
929 			continue;
930 
931 		TRACE("finishing transfers (first transfer: %p; last"
932 			" transfer: %p)\n", fFirstTransfer, fLastTransfer);
933 		transfer_data *lastTransfer = NULL;
934 		transfer_data *transfer = fFirstTransfer;
935 		Unlock();
936 
937 		while (transfer) {
938 			bool transferDone = false;
939 			ohci_general_td *descriptor = transfer->first_descriptor;
940 			ohci_endpoint_descriptor *endpoint = transfer->endpoint;
941 			status_t callbackStatus = B_OK;
942 
943 			MutexLocker endpointLocker(endpoint->lock);
944 
945 			if ((endpoint->head_physical_descriptor & OHCI_ENDPOINT_HEAD_MASK)
946 				!= endpoint->tail_physical_descriptor) {
947 				// there are still active transfers on this endpoint, we need
948 				// to wait for all of them to complete, otherwise we'd read
949 				// a potentially bogus data toggle value below
950 				TRACE("endpoint %p still has active tds\n", endpoint);
951 				lastTransfer = transfer;
952 				transfer = transfer->link;
953 				continue;
954 			}
955 
956 			endpointLocker.Unlock();
957 
958 			while (descriptor && !transfer->canceled) {
959 				uint32 status = OHCI_TD_GET_CONDITION_CODE(descriptor->flags);
960 				if (status == OHCI_TD_CONDITION_NOT_ACCESSED) {
961 					// td is still active
962 					TRACE("td %p still active\n", descriptor);
963 					break;
964 				}
965 
966 				if (status != OHCI_TD_CONDITION_NO_ERROR) {
967 					// an error occured, but we must ensure that the td
968 					// was actually done
969 					if (endpoint->head_physical_descriptor & OHCI_ENDPOINT_HALTED) {
970 						// the endpoint is halted, this guaratees us that this
971 						// descriptor has passed (we don't know if the endpoint
972 						// was halted because of this td, but we do not need
973 						// to know, as when it was halted by another td this
974 						// still ensures that this td was handled before).
975 						TRACE_ERROR("td error: 0x%08lx\n", status);
976 
977 						switch (status) {
978 							case OHCI_TD_CONDITION_CRC_ERROR:
979 							case OHCI_TD_CONDITION_BIT_STUFFING:
980 							case OHCI_TD_CONDITION_TOGGLE_MISMATCH:
981 								callbackStatus = B_DEV_CRC_ERROR;
982 								break;
983 
984 							case OHCI_TD_CONDITION_STALL:
985 								callbackStatus = B_DEV_STALLED;
986 								break;
987 
988 							case OHCI_TD_CONDITION_NO_RESPONSE:
989 								callbackStatus = B_TIMED_OUT;
990 								break;
991 
992 							case OHCI_TD_CONDITION_PID_CHECK_FAILURE:
993 								callbackStatus = B_DEV_BAD_PID;
994 								break;
995 
996 							case OHCI_TD_CONDITION_UNEXPECTED_PID:
997 								callbackStatus = B_DEV_UNEXPECTED_PID;
998 								break;
999 
1000 							case OHCI_TD_CONDITION_DATA_OVERRUN:
1001 								callbackStatus = B_DEV_DATA_OVERRUN;
1002 								break;
1003 
1004 							case OHCI_TD_CONDITION_DATA_UNDERRUN:
1005 								callbackStatus = B_DEV_DATA_UNDERRUN;
1006 								break;
1007 
1008 							case OHCI_TD_CONDITION_BUFFER_OVERRUN:
1009 								callbackStatus = B_DEV_FIFO_OVERRUN;
1010 								break;
1011 
1012 							case OHCI_TD_CONDITION_BUFFER_UNDERRUN:
1013 								callbackStatus = B_DEV_FIFO_UNDERRUN;
1014 								break;
1015 
1016 							default:
1017 								callbackStatus = B_ERROR;
1018 								break;
1019 						}
1020 
1021 						transferDone = true;
1022 						break;
1023 					} else {
1024 						// an error occured but the endpoint is not halted so
1025 						// the td is in fact still active
1026 						TRACE("td %p active with error\n", descriptor);
1027 						break;
1028 					}
1029 				}
1030 
1031 				// the td has completed without an error
1032 				TRACE("td %p done\n", descriptor);
1033 
1034 				if (descriptor == transfer->last_descriptor
1035 					|| descriptor->buffer_physical != 0) {
1036 					// this is the last td of the transfer or a short packet
1037 					callbackStatus = B_OK;
1038 					transferDone = true;
1039 					break;
1040 				}
1041 
1042 				descriptor
1043 					= (ohci_general_td *)descriptor->next_logical_descriptor;
1044 			}
1045 
1046 			if (transfer->canceled) {
1047 				// when a transfer is canceled, all transfers to that endpoint
1048 				// are canceled by setting the head pointer to the tail pointer
1049 				// which causes all of the tds to become "free" (as they are
1050 				// inaccessible and not accessed anymore (as setting the head
1051 				// pointer required disabling the endpoint))
1052 				callbackStatus = B_OK;
1053 				transferDone = true;
1054 			}
1055 
1056 			if (!transferDone) {
1057 				lastTransfer = transfer;
1058 				transfer = transfer->link;
1059 				continue;
1060 			}
1061 
1062 			// remove the transfer from the list first so we are sure
1063 			// it doesn't get canceled while we still process it
1064 			transfer_data *next = transfer->link;
1065 			if (Lock()) {
1066 				if (lastTransfer)
1067 					lastTransfer->link = transfer->link;
1068 
1069 				if (transfer == fFirstTransfer)
1070 					fFirstTransfer = transfer->link;
1071 				if (transfer == fLastTransfer)
1072 					fLastTransfer = lastTransfer;
1073 
1074 				// store the currently processing pipe here so we can wait
1075 				// in cancel if we are processing something on the target pipe
1076 				if (!transfer->canceled)
1077 					fProcessingPipe = transfer->transfer->TransferPipe();
1078 
1079 				transfer->link = NULL;
1080 				Unlock();
1081 			}
1082 
1083 			// break the descriptor chain on the last descriptor
1084 			transfer->last_descriptor->next_logical_descriptor = NULL;
1085 			TRACE("transfer %p done with status 0x%08lx\n",
1086 				transfer, callbackStatus);
1087 
1088 			// if canceled the callback has already been called
1089 			if (!transfer->canceled) {
1090 				size_t actualLength = 0;
1091 				if (callbackStatus == B_OK) {
1092 					if (transfer->data_descriptor && transfer->incoming) {
1093 						// data to read out
1094 						iovec *vector = transfer->transfer->Vector();
1095 						size_t vectorCount = transfer->transfer->VectorCount();
1096 
1097 						transfer->transfer->PrepareKernelAccess();
1098 						actualLength = _ReadDescriptorChain(
1099 							transfer->data_descriptor,
1100 							vector, vectorCount);
1101 					} else if (transfer->data_descriptor) {
1102 						// read the actual length that was sent
1103 						actualLength = _ReadActualLength(
1104 							transfer->data_descriptor);
1105 					}
1106 
1107 					// get the last data toggle and store it for next time
1108 					transfer->transfer->TransferPipe()->SetDataToggle(
1109 						(endpoint->head_physical_descriptor
1110 							& OHCI_ENDPOINT_TOGGLE_CARRY) != 0);
1111 
1112 					if (transfer->transfer->IsFragmented()) {
1113 						// this transfer may still have data left
1114 						TRACE("advancing fragmented transfer\n");
1115 						transfer->transfer->AdvanceByFragment(actualLength);
1116 						if (transfer->transfer->VectorLength() > 0) {
1117 							TRACE("still %ld bytes left on transfer\n",
1118 								transfer->transfer->VectorLength());
1119 							// TODO actually resubmit the transfer
1120 						}
1121 
1122 						// the transfer is done, but we already set the
1123 						// actualLength with AdvanceByFragment()
1124 						actualLength = 0;
1125 					}
1126 				}
1127 
1128 				transfer->transfer->Finished(callbackStatus, actualLength);
1129 				fProcessingPipe = NULL;
1130 			}
1131 
1132 			if (callbackStatus != B_OK) {
1133 				// remove the transfer and make the head pointer valid again
1134 				// (including clearing the halt state)
1135 				_RemoveTransferFromEndpoint(transfer);
1136 			}
1137 
1138 			// free the descriptors
1139 			_FreeDescriptorChain(transfer->first_descriptor);
1140 
1141 			delete transfer->transfer;
1142 			delete transfer;
1143 			transfer = next;
1144 		}
1145 	}
1146 }
1147 
1148 
1149 status_t
1150 OHCI::_SubmitRequest(Transfer *transfer)
1151 {
1152 	usb_request_data *requestData = transfer->RequestData();
1153 	bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) != 0;
1154 
1155 	ohci_general_td *setupDescriptor
1156 		= _CreateGeneralDescriptor(sizeof(usb_request_data));
1157 	if (!setupDescriptor) {
1158 		TRACE_ERROR("failed to allocate setup descriptor\n");
1159 		return B_NO_MEMORY;
1160 	}
1161 
1162 	setupDescriptor->flags = OHCI_TD_DIRECTION_PID_SETUP
1163 		| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1164 		| OHCI_TD_TOGGLE_0
1165 		| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
1166 
1167 	ohci_general_td *statusDescriptor = _CreateGeneralDescriptor(0);
1168 	if (!statusDescriptor) {
1169 		TRACE_ERROR("failed to allocate status descriptor\n");
1170 		_FreeGeneralDescriptor(setupDescriptor);
1171 		return B_NO_MEMORY;
1172 	}
1173 
1174 	statusDescriptor->flags
1175 		= (directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN)
1176 		| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1177 		| OHCI_TD_TOGGLE_1
1178 		| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1179 
1180 	iovec vector;
1181 	vector.iov_base = requestData;
1182 	vector.iov_len = sizeof(usb_request_data);
1183 	_WriteDescriptorChain(setupDescriptor, &vector, 1);
1184 
1185 	status_t result;
1186 	ohci_general_td *dataDescriptor = NULL;
1187 	if (transfer->VectorCount() > 0) {
1188 		ohci_general_td *lastDescriptor = NULL;
1189 		result = _CreateDescriptorChain(&dataDescriptor, &lastDescriptor,
1190 			directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT,
1191 			transfer->VectorLength());
1192 		if (result < B_OK) {
1193 			_FreeGeneralDescriptor(setupDescriptor);
1194 			_FreeGeneralDescriptor(statusDescriptor);
1195 			return result;
1196 		}
1197 
1198 		if (!directionIn) {
1199 			_WriteDescriptorChain(dataDescriptor, transfer->Vector(),
1200 				transfer->VectorCount());
1201 		}
1202 
1203 		_LinkDescriptors(setupDescriptor, dataDescriptor);
1204 		_LinkDescriptors(lastDescriptor, statusDescriptor);
1205 	} else {
1206 		_LinkDescriptors(setupDescriptor, statusDescriptor);
1207 	}
1208 
1209 	// Add to the transfer list
1210 	ohci_endpoint_descriptor *endpoint
1211 		= (ohci_endpoint_descriptor *)transfer->TransferPipe()->ControllerCookie();
1212 
1213 	MutexLocker endpointLocker(endpoint->lock);
1214 	result = _AddPendingTransfer(transfer, endpoint, setupDescriptor,
1215 		dataDescriptor, statusDescriptor, directionIn);
1216 	if (result < B_OK) {
1217 		TRACE_ERROR("failed to add pending transfer\n");
1218 		_FreeDescriptorChain(setupDescriptor);
1219 		return result;
1220 	}
1221 
1222 	// Add the descriptor chain to the endpoint
1223 	_SwitchEndpointTail(endpoint, setupDescriptor, statusDescriptor);
1224 	endpointLocker.Unlock();
1225 
1226 	// Tell the controller to process the control list
1227 	endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1228 	_WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED);
1229 	return B_OK;
1230 }
1231 
1232 
1233 status_t
1234 OHCI::_SubmitTransfer(Transfer *transfer)
1235 {
1236 	Pipe *pipe = transfer->TransferPipe();
1237 	bool directionIn = (pipe->Direction() == Pipe::In);
1238 
1239 	ohci_general_td *firstDescriptor = NULL;
1240 	ohci_general_td *lastDescriptor = NULL;
1241 	status_t result = _CreateDescriptorChain(&firstDescriptor, &lastDescriptor,
1242 		directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT,
1243 		transfer->VectorLength());
1244 
1245 	if (result < B_OK)
1246 		return result;
1247 
1248 	// Apply data toggle to the first descriptor (the others will use the carry)
1249 	firstDescriptor->flags &= ~OHCI_TD_TOGGLE_CARRY;
1250 	firstDescriptor->flags |= pipe->DataToggle() ? OHCI_TD_TOGGLE_1
1251 		: OHCI_TD_TOGGLE_0;
1252 
1253 	// Set the last descriptor to generate an interrupt
1254 	lastDescriptor->flags &= ~OHCI_TD_INTERRUPT_MASK;
1255 	lastDescriptor->flags |=
1256 		OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1257 
1258 	if (!directionIn) {
1259 		_WriteDescriptorChain(firstDescriptor, transfer->Vector(),
1260 			transfer->VectorCount());
1261 	}
1262 
1263 	// Add to the transfer list
1264 	ohci_endpoint_descriptor *endpoint
1265 		= (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1266 
1267 	MutexLocker endpointLocker(endpoint->lock);
1268 	result = _AddPendingTransfer(transfer, endpoint, firstDescriptor,
1269 		firstDescriptor, lastDescriptor, directionIn);
1270 	if (result < B_OK) {
1271 		TRACE_ERROR("failed to add pending transfer\n");
1272 		_FreeDescriptorChain(firstDescriptor);
1273 		return result;
1274 	}
1275 
1276 	// Add the descriptor chain to the endpoint
1277 	_SwitchEndpointTail(endpoint, firstDescriptor, lastDescriptor);
1278 	endpointLocker.Unlock();
1279 
1280 	endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1281 	if (pipe->Type() & USB_OBJECT_BULK_PIPE) {
1282 		// Tell the controller to process the bulk list
1283 		_WriteReg(OHCI_COMMAND_STATUS, OHCI_BULK_LIST_FILLED);
1284 	}
1285 
1286 	return B_OK;
1287 }
1288 
1289 
1290 status_t
1291 OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
1292 {
1293 	TRACE_ERROR("isochronous transfers not implemented\n");
1294 	return B_ERROR;
1295 }
1296 
1297 
1298 void
1299 OHCI::_SwitchEndpointTail(ohci_endpoint_descriptor *endpoint,
1300 	ohci_general_td *first, ohci_general_td *last)
1301 {
1302 	// fill in the information of the first descriptor into the current tail
1303 	ohci_general_td *tail = (ohci_general_td *)endpoint->tail_logical_descriptor;
1304 	tail->flags = first->flags;
1305 	tail->buffer_physical = first->buffer_physical;
1306 	tail->next_physical_descriptor = first->next_physical_descriptor;
1307 	tail->last_physical_byte_address = first->last_physical_byte_address;
1308 	tail->buffer_size = first->buffer_size;
1309 	tail->buffer_logical = first->buffer_logical;
1310 	tail->next_logical_descriptor = first->next_logical_descriptor;
1311 
1312 	// the first descriptor becomes the new tail
1313 	first->flags = 0;
1314 	first->buffer_physical = 0;
1315 	first->next_physical_descriptor = 0;
1316 	first->last_physical_byte_address = 0;
1317 	first->buffer_size = 0;
1318 	first->buffer_logical = NULL;
1319 	first->next_logical_descriptor = NULL;
1320 
1321 	if (first == last)
1322 		_LinkDescriptors(tail, first);
1323 	else
1324 		_LinkDescriptors(last, first);
1325 
1326 	// update the endpoint tail pointer to reflect the change
1327 	endpoint->tail_logical_descriptor = first;
1328 	endpoint->tail_physical_descriptor = (uint32)first->physical_address;
1329 	TRACE("switched tail from %p to %p\n", tail, first);
1330 
1331 #if 0
1332 	_PrintEndpoint(endpoint);
1333 	_PrintDescriptorChain(tail);
1334 #endif
1335 }
1336 
1337 
1338 void
1339 OHCI::_RemoveTransferFromEndpoint(transfer_data *transfer)
1340 {
1341 	// The transfer failed and the endpoint was halted. This means that the
1342 	// endpoint head pointer might point somewhere into the descriptor chain
1343 	// of this transfer. As we do not know if this transfer actually caused
1344 	// the halt on the endpoint we have to make sure this is the case. If we
1345 	// find the head to point to somewhere into the descriptor chain then
1346 	// simply advancing the head pointer to the link of the last transfer
1347 	// will bring the endpoint into a valid state again. This operation is
1348 	// safe as the endpoint is currently halted and we therefore can change
1349 	// the head pointer.
1350 	ohci_endpoint_descriptor *endpoint = transfer->endpoint;
1351 	ohci_general_td *descriptor = transfer->first_descriptor;
1352 	while (descriptor) {
1353 		if ((endpoint->head_physical_descriptor & OHCI_ENDPOINT_HEAD_MASK)
1354 			== descriptor->physical_address) {
1355 			// This descriptor caused the halt. Advance the head pointer. This
1356 			// will either move the head to the next valid transfer that can
1357 			// then be restarted, or it will move the head to the tail when
1358 			// there are no more transfer descriptors. Setting the head will
1359 			// also clear the halt state as it is stored in the first bit of
1360 			// the head pointer.
1361 			endpoint->head_physical_descriptor
1362 				= transfer->last_descriptor->next_physical_descriptor;
1363 			return;
1364 		}
1365 
1366 		descriptor = (ohci_general_td *)descriptor->next_logical_descriptor;
1367 	}
1368 }
1369 
1370 
1371 ohci_endpoint_descriptor *
1372 OHCI::_AllocateEndpoint()
1373 {
1374 	ohci_endpoint_descriptor *endpoint;
1375 	void *physicalAddress;
1376 
1377 	mutex *lock = (mutex *)malloc(sizeof(mutex));
1378 	if (lock == NULL) {
1379 		TRACE_ERROR("no memory to allocate endpoint lock\n");
1380 		return NULL;
1381 	}
1382 
1383 	// Allocate memory chunk
1384 	if (fStack->AllocateChunk((void **)&endpoint, &physicalAddress,
1385 		sizeof(ohci_endpoint_descriptor)) < B_OK) {
1386 		TRACE_ERROR("failed to allocate endpoint descriptor\n");
1387 		free(lock);
1388 		return NULL;
1389 	}
1390 
1391 	mutex_init(lock, "ohci endpoint lock");
1392 
1393 	endpoint->flags = OHCI_ENDPOINT_SKIP;
1394 	endpoint->physical_address = (addr_t)physicalAddress;
1395 	endpoint->head_physical_descriptor = 0;
1396 	endpoint->tail_logical_descriptor = NULL;
1397 	endpoint->tail_physical_descriptor = 0;
1398 	endpoint->next_logical_endpoint = NULL;
1399 	endpoint->next_physical_endpoint = 0;
1400 	endpoint->lock = lock;
1401 	return endpoint;
1402 }
1403 
1404 
1405 void
1406 OHCI::_FreeEndpoint(ohci_endpoint_descriptor *endpoint)
1407 {
1408 	if (!endpoint)
1409 		return;
1410 
1411 	mutex_destroy(endpoint->lock);
1412 	free(endpoint->lock);
1413 
1414 	fStack->FreeChunk((void *)endpoint, (void *)endpoint->physical_address,
1415 		sizeof(ohci_endpoint_descriptor));
1416 }
1417 
1418 
1419 status_t
1420 OHCI::_InsertEndpointForPipe(Pipe *pipe)
1421 {
1422 	TRACE("inserting endpoint for device %u endpoint %u\n",
1423 		pipe->DeviceAddress(), pipe->EndpointAddress());
1424 
1425 	ohci_endpoint_descriptor *endpoint = _AllocateEndpoint();
1426 	if (!endpoint) {
1427 		TRACE_ERROR("cannot allocate memory for endpoint\n");
1428 		return B_NO_MEMORY;
1429 	}
1430 
1431 	uint32 flags = OHCI_ENDPOINT_SKIP;
1432 
1433 	// Set up device and endpoint address
1434 	flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(pipe->DeviceAddress())
1435 		| OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(pipe->EndpointAddress());
1436 
1437 	// Set the direction
1438 	switch (pipe->Direction()) {
1439 		case Pipe::In:
1440 			flags |= OHCI_ENDPOINT_DIRECTION_IN;
1441 			break;
1442 
1443 		case Pipe::Out:
1444 			flags |= OHCI_ENDPOINT_DIRECTION_OUT;
1445 			break;
1446 
1447 		case Pipe::Default:
1448 			flags |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR;
1449 			break;
1450 
1451 		default:
1452 			TRACE_ERROR("direction unknown\n");
1453 			_FreeEndpoint(endpoint);
1454 			return B_ERROR;
1455 	}
1456 
1457 	// Set up the speed
1458 	switch (pipe->Speed()) {
1459 		case USB_SPEED_LOWSPEED:
1460 			flags |= OHCI_ENDPOINT_LOW_SPEED;
1461 			break;
1462 
1463 		case USB_SPEED_FULLSPEED:
1464 			flags |= OHCI_ENDPOINT_FULL_SPEED;
1465 			break;
1466 
1467 		default:
1468 			TRACE_ERROR("unacceptable speed\n");
1469 			_FreeEndpoint(endpoint);
1470 			return B_ERROR;
1471 	}
1472 
1473 	// Set the maximum packet size
1474 	flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(pipe->MaxPacketSize());
1475 	endpoint->flags = flags;
1476 
1477 	// Add the endpoint to the appropriate list
1478 	uint32 type = pipe->Type();
1479 	ohci_endpoint_descriptor *head = NULL;
1480 	if (type & USB_OBJECT_CONTROL_PIPE)
1481 		head = fDummyControl;
1482 	else if (type & USB_OBJECT_BULK_PIPE)
1483 		head = fDummyBulk;
1484 	else if (type & USB_OBJECT_INTERRUPT_PIPE)
1485 		head = _FindInterruptEndpoint(pipe->Interval());
1486 	else if (type & USB_OBJECT_ISO_PIPE)
1487 		head = fDummyIsochronous;
1488 	else
1489 		TRACE_ERROR("unknown pipe type\n");
1490 
1491 	if (head == NULL) {
1492 		TRACE_ERROR("no list found for endpoint\n");
1493 		_FreeEndpoint(endpoint);
1494 		return B_ERROR;
1495 	}
1496 
1497 	// Create (necessary) tail descriptor
1498 	if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
1499 		// Set the isochronous bit format
1500 		endpoint->flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
1501 		// TODO
1502 		_FreeEndpoint(endpoint);
1503 		return B_ERROR;
1504 	} else {
1505 		ohci_general_td *tail = _CreateGeneralDescriptor(0);
1506 		tail->flags = 0;
1507 		endpoint->tail_logical_descriptor = tail;
1508 		endpoint->head_physical_descriptor = tail->physical_address;
1509 		endpoint->tail_physical_descriptor = tail->physical_address;
1510 	}
1511 
1512 	if (!_LockEndpoints()) {
1513 		if (endpoint->tail_logical_descriptor) {
1514 			_FreeGeneralDescriptor(
1515 				(ohci_general_td *)endpoint->tail_logical_descriptor);
1516 		}
1517 
1518 		_FreeEndpoint(endpoint);
1519 		return B_ERROR;
1520 	}
1521 
1522 	pipe->SetControllerCookie((void *)endpoint);
1523 	endpoint->next_logical_endpoint = head->next_logical_endpoint;
1524 	endpoint->next_physical_endpoint = head->next_physical_endpoint;
1525 	head->next_logical_endpoint = (void *)endpoint;
1526 	head->next_physical_endpoint = (uint32)endpoint->physical_address;
1527 
1528 	_UnlockEndpoints();
1529 	return B_OK;
1530 }
1531 
1532 
1533 status_t
1534 OHCI::_RemoveEndpointForPipe(Pipe *pipe)
1535 {
1536 	TRACE("removing endpoint for device %u endpoint %u\n",
1537 		pipe->DeviceAddress(), pipe->EndpointAddress());
1538 
1539 	ohci_endpoint_descriptor *endpoint
1540 		= (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1541 	if (endpoint == NULL)
1542 		return B_OK;
1543 
1544 	// TODO implement properly, but at least disable it for now
1545 	endpoint->flags |= OHCI_ENDPOINT_SKIP;
1546 	return B_OK;
1547 }
1548 
1549 
1550 ohci_endpoint_descriptor *
1551 OHCI::_FindInterruptEndpoint(uint8 interval)
1552 {
1553 	uint32 index = 0;
1554 	uint32 power = 1;
1555 	while (power <= OHCI_BIGGEST_INTERVAL / 2) {
1556 		if (power * 2 > interval)
1557 			break;
1558 
1559 		power *= 2;
1560 		index++;
1561 	}
1562 
1563 	return fInterruptEndpoints[index];
1564 }
1565 
1566 
1567 ohci_general_td *
1568 OHCI::_CreateGeneralDescriptor(size_t bufferSize)
1569 {
1570 	ohci_general_td *descriptor;
1571 	void *physicalAddress;
1572 
1573 	if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
1574 		sizeof(ohci_general_td)) != B_OK) {
1575 		TRACE_ERROR("failed to allocate general descriptor\n");
1576 		return NULL;
1577 	}
1578 
1579 	descriptor->physical_address = (addr_t)physicalAddress;
1580 	descriptor->next_physical_descriptor = 0;
1581 	descriptor->next_logical_descriptor = NULL;
1582 	descriptor->buffer_size = bufferSize;
1583 	if (bufferSize == 0) {
1584 		descriptor->buffer_physical = 0;
1585 		descriptor->buffer_logical = NULL;
1586 		descriptor->last_physical_byte_address = 0;
1587 		return descriptor;
1588 	}
1589 
1590 	if (fStack->AllocateChunk(&descriptor->buffer_logical,
1591 		(void **)&descriptor->buffer_physical, bufferSize) != B_OK) {
1592 		TRACE_ERROR("failed to allocate space for buffer\n");
1593 		fStack->FreeChunk(descriptor, (void *)descriptor->physical_address,
1594 			sizeof(ohci_general_td));
1595 		return NULL;
1596 	}
1597 
1598 	descriptor->last_physical_byte_address
1599 		= descriptor->buffer_physical + bufferSize - 1;
1600 	return descriptor;
1601 }
1602 
1603 
1604 void
1605 OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor)
1606 {
1607 	if (!descriptor)
1608 		return;
1609 
1610 	if (descriptor->buffer_logical) {
1611 		fStack->FreeChunk(descriptor->buffer_logical,
1612 			(void *)descriptor->buffer_physical, descriptor->buffer_size);
1613 	}
1614 
1615 	fStack->FreeChunk((void *)descriptor, (void *)descriptor->physical_address,
1616 		sizeof(ohci_general_td));
1617 }
1618 
1619 
1620 status_t
1621 OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor,
1622 	ohci_general_td **_lastDescriptor, uint32 direction, size_t bufferSize)
1623 {
1624 	size_t blockSize = 8192;
1625 	int32 descriptorCount = (bufferSize + blockSize - 1) / blockSize;
1626 	if (descriptorCount == 0)
1627 		descriptorCount = 1;
1628 
1629 	ohci_general_td *firstDescriptor = NULL;
1630 	ohci_general_td *lastDescriptor = *_firstDescriptor;
1631 	for (int32 i = 0; i < descriptorCount; i++) {
1632 		ohci_general_td *descriptor = _CreateGeneralDescriptor(
1633 			min_c(blockSize, bufferSize));
1634 
1635 		if (!descriptor) {
1636 			_FreeDescriptorChain(firstDescriptor);
1637 			return B_NO_MEMORY;
1638 		}
1639 
1640 		descriptor->flags = direction
1641 			| OHCI_TD_BUFFER_ROUNDING
1642 			| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1643 			| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE)
1644 			| OHCI_TD_TOGGLE_CARRY;
1645 
1646 		// link to previous
1647 		if (lastDescriptor)
1648 			_LinkDescriptors(lastDescriptor, descriptor);
1649 
1650 		bufferSize -= blockSize;
1651 		lastDescriptor = descriptor;
1652 		if (!firstDescriptor)
1653 			firstDescriptor = descriptor;
1654 	}
1655 
1656 	*_firstDescriptor = firstDescriptor;
1657 	*_lastDescriptor = lastDescriptor;
1658 	return B_OK;
1659 }
1660 
1661 
1662 void
1663 OHCI::_FreeDescriptorChain(ohci_general_td *topDescriptor)
1664 {
1665 	ohci_general_td *current = topDescriptor;
1666 	ohci_general_td *next = NULL;
1667 
1668 	while (current) {
1669 		next = (ohci_general_td *)current->next_logical_descriptor;
1670 		_FreeGeneralDescriptor(current);
1671 		current = next;
1672 	}
1673 }
1674 
1675 
1676 size_t
1677 OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
1678 	size_t vectorCount)
1679 {
1680 	ohci_general_td *current = topDescriptor;
1681 	size_t actualLength = 0;
1682 	size_t vectorIndex = 0;
1683 	size_t vectorOffset = 0;
1684 	size_t bufferOffset = 0;
1685 
1686 	while (current) {
1687 		if (!current->buffer_logical)
1688 			break;
1689 
1690 		while (true) {
1691 			size_t length = min_c(current->buffer_size - bufferOffset,
1692 				vector[vectorIndex].iov_len - vectorOffset);
1693 
1694 			TRACE("copying %ld bytes to bufferOffset %ld from"
1695 				" vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
1696 				vectorOffset, vectorIndex, vectorCount);
1697 			memcpy((uint8 *)current->buffer_logical + bufferOffset,
1698 				(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
1699 
1700 			actualLength += length;
1701 			vectorOffset += length;
1702 			bufferOffset += length;
1703 
1704 			if (vectorOffset >= vector[vectorIndex].iov_len) {
1705 				if (++vectorIndex >= vectorCount) {
1706 					TRACE("wrote descriptor chain (%ld bytes, no"
1707 						" more vectors)\n", actualLength);
1708 					return actualLength;
1709 				}
1710 
1711 				vectorOffset = 0;
1712 			}
1713 
1714 			if (bufferOffset >= current->buffer_size) {
1715 				bufferOffset = 0;
1716 				break;
1717 			}
1718 		}
1719 
1720 		if (!current->next_logical_descriptor)
1721 			break;
1722 
1723 		current = (ohci_general_td *)current->next_logical_descriptor;
1724 	}
1725 
1726 	TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
1727 	return actualLength;
1728 }
1729 
1730 
1731 size_t
1732 OHCI::_ReadDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
1733 	size_t vectorCount)
1734 {
1735 	ohci_general_td *current = topDescriptor;
1736 	size_t actualLength = 0;
1737 	size_t vectorIndex = 0;
1738 	size_t vectorOffset = 0;
1739 	size_t bufferOffset = 0;
1740 
1741 	while (current && OHCI_TD_GET_CONDITION_CODE(current->flags)
1742 		!= OHCI_TD_CONDITION_NOT_ACCESSED) {
1743 		if (!current->buffer_logical)
1744 			break;
1745 
1746 		size_t bufferSize = current->buffer_size;
1747 		if (current->buffer_physical != 0) {
1748 			bufferSize -= current->last_physical_byte_address
1749 				- current->buffer_physical + 1;
1750 		}
1751 
1752 		while (true) {
1753 			size_t length = min_c(bufferSize - bufferOffset,
1754 				vector[vectorIndex].iov_len - vectorOffset);
1755 
1756 			TRACE("copying %ld bytes to vectorOffset %ld from"
1757 				" bufferOffset %ld at index %ld of %ld\n", length, vectorOffset,
1758 				bufferOffset, vectorIndex, vectorCount);
1759 			memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
1760 				(uint8 *)current->buffer_logical + bufferOffset, length);
1761 
1762 			actualLength += length;
1763 			vectorOffset += length;
1764 			bufferOffset += length;
1765 
1766 			if (vectorOffset >= vector[vectorIndex].iov_len) {
1767 				if (++vectorIndex >= vectorCount) {
1768 					TRACE("read descriptor chain (%ld bytes, no more vectors)\n",
1769 						actualLength);
1770 					return actualLength;
1771 				}
1772 
1773 				vectorOffset = 0;
1774 			}
1775 
1776 			if (bufferOffset >= bufferSize) {
1777 				bufferOffset = 0;
1778 				break;
1779 			}
1780 		}
1781 
1782 		current = (ohci_general_td *)current->next_logical_descriptor;
1783 	}
1784 
1785 	TRACE("read descriptor chain (%ld bytes)\n", actualLength);
1786 	return actualLength;
1787 }
1788 
1789 
1790 size_t
1791 OHCI::_ReadActualLength(ohci_general_td *topDescriptor)
1792 {
1793 	ohci_general_td *current = topDescriptor;
1794 	size_t actualLength = 0;
1795 
1796 	while (current && OHCI_TD_GET_CONDITION_CODE(current->flags)
1797 		!= OHCI_TD_CONDITION_NOT_ACCESSED) {
1798 		size_t length = current->buffer_size;
1799 		if (current->buffer_physical != 0) {
1800 			length -= current->last_physical_byte_address
1801 				- current->buffer_physical + 1;
1802 		}
1803 
1804 		actualLength += length;
1805 		current = (ohci_general_td *)current->next_logical_descriptor;
1806 	}
1807 
1808 	TRACE("read actual length (%ld bytes)\n", actualLength);
1809 	return actualLength;
1810 }
1811 
1812 
1813 void
1814 OHCI::_LinkDescriptors(ohci_general_td *first, ohci_general_td *second)
1815 {
1816 	first->next_physical_descriptor = second->physical_address;
1817 	first->next_logical_descriptor = second;
1818 }
1819 
1820 
1821 ohci_isochronous_td *
1822 OHCI::_CreateIsochronousDescriptor()
1823 {
1824 	// TODO
1825 	return NULL;
1826 }
1827 
1828 
1829 void
1830 OHCI::_FreeIsochronousDescriptor(ohci_isochronous_td *descriptor)
1831 {
1832 	// TODO
1833 }
1834 
1835 
1836 bool
1837 OHCI::_LockEndpoints()
1838 {
1839 	return (mutex_lock(&fEndpointLock) == B_OK);
1840 }
1841 
1842 
1843 void
1844 OHCI::_UnlockEndpoints()
1845 {
1846 	mutex_unlock(&fEndpointLock);
1847 }
1848 
1849 
1850 inline void
1851 OHCI::_WriteReg(uint32 reg, uint32 value)
1852 {
1853 	*(volatile uint32 *)(fOperationalRegisters + reg) = value;
1854 }
1855 
1856 
1857 inline uint32
1858 OHCI::_ReadReg(uint32 reg)
1859 {
1860 	return *(volatile uint32 *)(fOperationalRegisters + reg);
1861 }
1862 
1863 
1864 void
1865 OHCI::_PrintEndpoint(ohci_endpoint_descriptor *endpoint)
1866 {
1867 	TRACE_ALWAYS("endpoint %p\n", endpoint);
1868 	dprintf("\tflags........... 0x%08lx\n", endpoint->flags);
1869 	dprintf("\ttail_physical... 0x%08lx\n", endpoint->tail_physical_descriptor);
1870 	dprintf("\thead_physical... 0x%08lx\n", endpoint->head_physical_descriptor);
1871 	dprintf("\tnext_physical... 0x%08lx\n", endpoint->next_physical_endpoint);
1872 	dprintf("\tphysical........ 0x%08lx\n", endpoint->physical_address);
1873 	dprintf("\ttail_logical.... %p\n", endpoint->tail_logical_descriptor);
1874 	dprintf("\tnext_logical.... %p\n", endpoint->next_logical_endpoint);
1875 }
1876 
1877 
1878 void
1879 OHCI::_PrintDescriptorChain(ohci_general_td *topDescriptor)
1880 {
1881 	while (topDescriptor) {
1882 		TRACE_ALWAYS("descriptor %p\n", topDescriptor);
1883 		dprintf("\tflags........... 0x%08lx\n", topDescriptor->flags);
1884 		dprintf("\tbuffer_physical. 0x%08lx\n", topDescriptor->buffer_physical);
1885 		dprintf("\tnext_physical... 0x%08lx\n", topDescriptor->next_physical_descriptor);
1886 		dprintf("\tlast_byte....... 0x%08lx\n", topDescriptor->last_physical_byte_address);
1887 		dprintf("\tphysical........ 0x%08lx\n", topDescriptor->physical_address);
1888 		dprintf("\tbuffer_size..... %lu\n", topDescriptor->buffer_size);
1889 		dprintf("\tbuffer_logical.. %p\n", topDescriptor->buffer_logical);
1890 		dprintf("\tnext_logical.... %p\n", topDescriptor->next_logical_descriptor);
1891 
1892 		topDescriptor = (ohci_general_td *)topDescriptor->next_logical_descriptor;
1893 	}
1894 }
1895