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