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