xref: /haiku/src/add-ons/kernel/busses/usb/ehci.cpp (revision 445d4fd926c569e7b9ae28017da86280aaecbae2)
1 /*
2  * Copyright 2006-2011, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  *		Jérôme Duval <korli@users.berlios.de>
8  */
9 
10 
11 #include <stdio.h>
12 
13 #include <driver_settings.h>
14 #include <bus/PCI.h>
15 #include <USB3.h>
16 #include <KernelExport.h>
17 
18 #include "ehci.h"
19 
20 
21 #define CALLED(x...)	TRACE_MODULE("CALLED %s\n", __PRETTY_FUNCTION__)
22 
23 #define USB_MODULE_NAME	"ehci"
24 
25 
26 device_manager_info* gDeviceManager;
27 static usb_for_controller_interface* gUSB;
28 
29 
30 #define EHCI_PCI_DEVICE_MODULE_NAME "busses/usb/ehci/pci/driver_v1"
31 #define EHCI_PCI_USB_BUS_MODULE_NAME "busses/usb/ehci/device_v1"
32 
33 
34 typedef struct {
35 	EHCI* ehci;
36 	pci_device_module_info* pci;
37 	pci_device* device;
38 
39 	pci_info pciinfo;
40 
41 	device_node* node;
42 	device_node* driver_node;
43 } ehci_pci_sim_info;
44 
45 
46 //	#pragma mark -
47 
48 
49 static status_t
50 init_bus(device_node* node, void** bus_cookie)
51 {
52 	CALLED();
53 
54 	driver_module_info* driver;
55 	ehci_pci_sim_info* bus;
56 	device_node* parent = gDeviceManager->get_parent_node(node);
57 	gDeviceManager->get_driver(parent, &driver, (void**)&bus);
58 	gDeviceManager->put_node(parent);
59 
60 	Stack *stack;
61 	if (gUSB->get_stack((void**)&stack) != B_OK)
62 		return B_ERROR;
63 
64 	EHCI *ehci = new(std::nothrow) EHCI(&bus->pciinfo, bus->pci, bus->device, stack, node);
65 	if (ehci == NULL) {
66 		return B_NO_MEMORY;
67 	}
68 
69 	if (ehci->InitCheck() < B_OK) {
70 		TRACE_MODULE_ERROR("bus failed init check\n");
71 		delete ehci;
72 		return B_ERROR;
73 	}
74 
75 	if (ehci->Start() != B_OK) {
76 		delete ehci;
77 		return B_ERROR;
78 	}
79 
80 	*bus_cookie = ehci;
81 
82 	return B_OK;
83 }
84 
85 
86 static void
87 uninit_bus(void* bus_cookie)
88 {
89 	CALLED();
90 	EHCI* ehci = (EHCI*)bus_cookie;
91 	delete ehci;
92 }
93 
94 
95 static status_t
96 register_child_devices(void* cookie)
97 {
98 	CALLED();
99 	ehci_pci_sim_info* bus = (ehci_pci_sim_info*)cookie;
100 	device_node* node = bus->driver_node;
101 
102 	char prettyName[25];
103 	sprintf(prettyName, "EHCI Controller %" B_PRIu16, 0);
104 
105 	device_attr attrs[] = {
106 		// properties of this controller for the usb bus manager
107 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
108 			{ .string = prettyName }},
109 		{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
110 			{ .string = USB_FOR_CONTROLLER_MODULE_NAME }},
111 
112 		// private data to identify the device
113 		{ NULL }
114 	};
115 
116 	return gDeviceManager->register_node(node, EHCI_PCI_USB_BUS_MODULE_NAME,
117 		attrs, NULL, NULL);
118 }
119 
120 
121 static status_t
122 init_device(device_node* node, void** device_cookie)
123 {
124 	CALLED();
125 	ehci_pci_sim_info* bus = (ehci_pci_sim_info*)calloc(1,
126 		sizeof(ehci_pci_sim_info));
127 	if (bus == NULL)
128 		return B_NO_MEMORY;
129 
130 	pci_device_module_info* pci;
131 	pci_device* device;
132 	{
133 		device_node* pciParent = gDeviceManager->get_parent_node(node);
134 		gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
135 			(void**)&device);
136 		gDeviceManager->put_node(pciParent);
137 	}
138 
139 	bus->pci = pci;
140 	bus->device = device;
141 	bus->driver_node = node;
142 
143 	pci_info *pciInfo = &bus->pciinfo;
144 	pci->get_pci_info(device, pciInfo);
145 
146 	*device_cookie = bus;
147 	return B_OK;
148 }
149 
150 
151 static void
152 uninit_device(void* device_cookie)
153 {
154 	CALLED();
155 	ehci_pci_sim_info* bus = (ehci_pci_sim_info*)device_cookie;
156 	free(bus);
157 
158 }
159 
160 
161 static status_t
162 register_device(device_node* parent)
163 {
164 	CALLED();
165 	device_attr attrs[] = {
166 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "EHCI PCI"}},
167 		{}
168 	};
169 
170 	return gDeviceManager->register_node(parent,
171 		EHCI_PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL);
172 }
173 
174 
175 static float
176 supports_device(device_node* parent)
177 {
178 	CALLED();
179 	const char* bus;
180 	uint16 type, subType, api;
181 
182 	// make sure parent is a EHCI PCI device node
183 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
184 		< B_OK) {
185 		return -1;
186 	}
187 
188 	if (strcmp(bus, "pci") != 0)
189 		return 0.0f;
190 
191 	if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subType,
192 			false) < B_OK
193 		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &type,
194 			false) < B_OK
195 		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_INTERFACE, &api,
196 			false) < B_OK) {
197 		TRACE_MODULE("Could not find type/subtype/interface attributes\n");
198 		return -1;
199 	}
200 
201 	if (type == PCI_serial_bus && subType == PCI_usb && api == PCI_usb_ehci) {
202 		pci_device_module_info* pci;
203 		pci_device* device;
204 		gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
205 			(void**)&device);
206 		TRACE_MODULE("EHCI Device found!\n");
207 
208 		return 0.8f;
209 	}
210 
211 	return 0.0f;
212 }
213 
214 
215 module_dependency module_dependencies[] = {
216 	{ USB_FOR_CONTROLLER_MODULE_NAME, (module_info**)&gUSB },
217 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
218 	{}
219 };
220 
221 
222 static usb_bus_interface gEHCIPCIDeviceModule = {
223 	{
224 		{
225 			EHCI_PCI_USB_BUS_MODULE_NAME,
226 			0,
227 			NULL
228 		},
229 		NULL,  // supports device
230 		NULL,  // register device
231 		init_bus,
232 		uninit_bus,
233 		NULL,  // register child devices
234 		NULL,  // rescan
235 		NULL,  // device removed
236 	},
237 };
238 
239 // Root device that binds to the PCI bus. It will register an usb_bus_interface
240 // node for each device.
241 static driver_module_info sEHCIDevice = {
242 	{
243 		EHCI_PCI_DEVICE_MODULE_NAME,
244 		0,
245 		NULL
246 	},
247 	supports_device,
248 	register_device,
249 	init_device,
250 	uninit_device,
251 	register_child_devices,
252 	NULL, // rescan
253 	NULL, // device removed
254 };
255 
256 module_info* modules[] = {
257 	(module_info* )&sEHCIDevice,
258 	(module_info* )&gEHCIPCIDeviceModule,
259 	NULL
260 };
261 
262 
263 //
264 // #pragma mark -
265 //
266 
267 
268 #ifdef TRACE_USB
269 
270 void
271 print_descriptor_chain(ehci_qtd *descriptor)
272 {
273 	while (descriptor) {
274 		dprintf(" %08" B_PRIx32 " n%08" B_PRIx32 " a%08" B_PRIx32 " t%08"
275 			B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 " %08"
276 			B_PRIx32 " %08" B_PRIx32 " s%" B_PRIuSIZE "\n",
277 			descriptor->this_phy, descriptor->next_phy,
278 			descriptor->alt_next_phy, descriptor->token,
279 			descriptor->buffer_phy[0], descriptor->buffer_phy[1],
280 			descriptor->buffer_phy[2], descriptor->buffer_phy[3],
281 			descriptor->buffer_phy[4], descriptor->buffer_size);
282 
283 		if (descriptor->next_phy & EHCI_ITEM_TERMINATE)
284 			break;
285 
286 		descriptor = descriptor->next_log;
287 	}
288 }
289 
290 
291 void
292 print_queue(ehci_qh *queueHead)
293 {
294 	dprintf("queue:    t%08" B_PRIx32 " n%08" B_PRIx32 " ch%08" B_PRIx32
295 		" ca%08" B_PRIx32 " cu%08" B_PRIx32 "\n",
296 		queueHead->this_phy, queueHead->next_phy, queueHead->endpoint_chars,
297 		queueHead->endpoint_caps, queueHead->current_qtd_phy);
298 	dprintf("overlay:  n%08" B_PRIx32 " a%08" B_PRIx32 " t%08" B_PRIx32
299 		" %08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32
300 		" %08" B_PRIx32 "\n", queueHead->overlay.next_phy,
301 		queueHead->overlay.alt_next_phy, queueHead->overlay.token,
302 		queueHead->overlay.buffer_phy[0], queueHead->overlay.buffer_phy[1],
303 		queueHead->overlay.buffer_phy[2], queueHead->overlay.buffer_phy[3],
304 		queueHead->overlay.buffer_phy[4]);
305 	print_descriptor_chain(queueHead->element_log);
306 }
307 
308 
309 #endif // TRACE_USB
310 
311 
312 //
313 // #pragma mark -
314 //
315 
316 
317 EHCI::EHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stack *stack,
318 	device_node* node)
319 	:	BusManager(stack, node),
320 		fCapabilityRegisters(NULL),
321 		fOperationalRegisters(NULL),
322 		fRegisterArea(-1),
323 		fPCIInfo(info),
324 		fPci(pci),
325 		fDevice(device),
326 		fStack(stack),
327 		fEnabledInterrupts(0),
328 		fThreshold(0),
329 		fPeriodicFrameListArea(-1),
330 		fPeriodicFrameList(NULL),
331 		fInterruptEntries(NULL),
332 		fItdEntries(NULL),
333 		fSitdEntries(NULL),
334 		fAsyncQueueHead(NULL),
335 		fAsyncAdvanceSem(-1),
336 		fFirstTransfer(NULL),
337 		fLastTransfer(NULL),
338 		fFinishTransfersSem(-1),
339 		fFinishThread(-1),
340 		fProcessingPipe(NULL),
341 		fFreeListHead(NULL),
342 		fCleanupSem(-1),
343 		fCleanupThread(-1),
344 		fStopThreads(false),
345 		fNextStartingFrame(-1),
346 		fFrameBandwidth(NULL),
347 		fFirstIsochronousTransfer(NULL),
348 		fLastIsochronousTransfer(NULL),
349 		fFinishIsochronousTransfersSem(-1),
350 		fFinishIsochronousThread(-1),
351 		fRootHub(NULL),
352 		fRootHubAddress(0),
353 		fPortCount(0),
354 		fPortResetChange(0),
355 		fPortSuspendChange(0),
356 		fInterruptPollThread(-1),
357 		fIRQ(0),
358 		fUseMSI(false)
359 {
360 	// Create a lock for the isochronous transfer list
361 	mutex_init(&fIsochronousLock, "EHCI isochronous lock");
362 
363 	if (BusManager::InitCheck() != B_OK) {
364 		TRACE_ERROR("bus manager failed to init\n");
365 		return;
366 	}
367 
368 	TRACE("constructing new EHCI host controller driver\n");
369 	fInitOK = false;
370 
371 	// ATI/AMD SB600/SB700 periodic list cache workaround
372 	// Logic kindly borrowed from NetBSD PR 40056
373 	if (fPCIInfo->vendor_id == AMD_SBX00_VENDOR) {
374 		bool applyWorkaround = false;
375 
376 		if (fPCIInfo->device_id == AMD_SB600_EHCI_CONTROLLER) {
377 			// always apply on SB600
378 			applyWorkaround = true;
379 		} else if (fPCIInfo->device_id == AMD_SB700_SB800_EHCI_CONTROLLER) {
380 			// only apply on certain chipsets, determined by SMBus revision
381 			device_node *pciNode = NULL;
382 			device_node* deviceRoot = gDeviceManager->get_root_node();
383 			device_attr acpiAttrs[] = {
384 				{ B_DEVICE_BUS, B_STRING_TYPE, { .string = "pci" }},
385 				{ B_DEVICE_VENDOR_ID, B_UINT16_TYPE, { .ui16 = AMD_SBX00_VENDOR }},
386 				{ B_DEVICE_ID, B_UINT16_TYPE, { .ui16 = AMD_SBX00_SMBUS_CONTROLLER }},
387 				{ NULL }
388 			};
389 			if (gDeviceManager->find_child_node(deviceRoot, acpiAttrs,
390 					&pciNode) == B_OK) {
391 				pci_device_module_info *pci;
392 				pci_device *pciDevice;
393 				if (gDeviceManager->get_driver(pciNode, (driver_module_info **)&pci,
394 					(void **)&pciDevice) == B_OK) {
395 
396 					pci_info smbus;
397 					pci->get_pci_info(pciDevice, &smbus);
398 					// Only applies to chipsets < SB710 (rev A14)
399 					if (smbus.revision == 0x3a || smbus.revision == 0x3b)
400 						applyWorkaround = true;
401 				}
402 			}
403 		}
404 
405 		if (applyWorkaround) {
406 			// According to AMD errata of SB700 and SB600 register documentation
407 			// this disables the Periodic List Cache on SB600 and the Advanced
408 			// Periodic List Cache on early SB700. Both the BSDs and Linux use
409 			// this workaround.
410 
411 			TRACE_ALWAYS("disabling SB600/SB700 periodic list cache\n");
412 			uint32 workaround = fPci->read_pci_config(fDevice,
413 				AMD_SBX00_EHCI_MISC_REGISTER, 4);
414 
415 			fPci->write_pci_config(fDevice, AMD_SBX00_EHCI_MISC_REGISTER, 4,
416 				workaround | AMD_SBX00_EHCI_MISC_DISABLE_PERIODIC_LIST_CACHE);
417 		}
418 	}
419 
420 	// enable busmaster and memory mapped access
421 	uint16 command = fPci->read_pci_config(fDevice, PCI_command, 2);
422 	command &= ~PCI_command_io;
423 	command |= PCI_command_master | PCI_command_memory;
424 
425 	fPci->write_pci_config(fDevice, PCI_command, 2, command);
426 
427 	// map the registers
428 	uint32 offset = fPCIInfo->u.h0.base_registers[0] & (B_PAGE_SIZE - 1);
429 	phys_addr_t physicalAddress = fPCIInfo->u.h0.base_registers[0] - offset;
430 	size_t mapSize = (fPCIInfo->u.h0.base_register_sizes[0] + offset
431 		+ B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
432 
433 	TRACE("map physical memory 0x%08" B_PRIx32 " (base: 0x%08" B_PRIxPHYSADDR
434 		"; offset: %" B_PRIx32 "); size: %" B_PRIu32 "\n",
435 		fPCIInfo->u.h0.base_registers[0], physicalAddress, offset,
436 		fPCIInfo->u.h0.base_register_sizes[0]);
437 
438 	fRegisterArea = map_physical_memory("EHCI memory mapped registers",
439 		physicalAddress, mapSize, B_ANY_KERNEL_BLOCK_ADDRESS,
440 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
441 		(void **)&fCapabilityRegisters);
442 	if (fRegisterArea < 0) {
443 		TRACE_ERROR("failed to map register memory\n");
444 		return;
445 	}
446 
447 	fCapabilityRegisters += offset;
448 	fOperationalRegisters = fCapabilityRegisters + ReadCapReg8(EHCI_CAPLENGTH);
449 	TRACE("mapped capability registers: 0x%p\n", fCapabilityRegisters);
450 	TRACE("mapped operational registers: 0x%p\n", fOperationalRegisters);
451 
452 	TRACE("structural parameters: 0x%08" B_PRIx32 "\n",
453 		ReadCapReg32(EHCI_HCSPARAMS));
454 	TRACE("capability parameters: 0x%08" B_PRIx32 "\n",
455 		ReadCapReg32(EHCI_HCCPARAMS));
456 
457 	if (EHCI_HCCPARAMS_FRAME_CACHE(ReadCapReg32(EHCI_HCCPARAMS)))
458 		fThreshold = 2 + 8;
459 	else
460 		fThreshold = 2 + EHCI_HCCPARAMS_IPT(ReadCapReg32(EHCI_HCCPARAMS));
461 
462 	// read port count from capability register
463 	fPortCount = ReadCapReg32(EHCI_HCSPARAMS) & 0x0f;
464 
465 	uint32 extendedCapPointer = ReadCapReg32(EHCI_HCCPARAMS) >> EHCI_ECP_SHIFT;
466 	extendedCapPointer &= EHCI_ECP_MASK;
467 	if (extendedCapPointer > 0) {
468 		TRACE("extended capabilities register at %" B_PRIu32 "\n",
469 			extendedCapPointer);
470 
471 		uint32 legacySupport = fPci->read_pci_config(fDevice, extendedCapPointer, 4);
472 		if ((legacySupport & EHCI_LEGSUP_CAPID_MASK) == EHCI_LEGSUP_CAPID) {
473 			if ((legacySupport & EHCI_LEGSUP_BIOSOWNED) != 0) {
474 				TRACE_ALWAYS("the host controller is bios owned, claiming"
475 					" ownership\n");
476 
477 				fPci->write_pci_config(fDevice, extendedCapPointer + 3, 1, 1);
478 
479 				for (int32 i = 0; i < 20; i++) {
480 					legacySupport = fPci->read_pci_config(fDevice,
481 						extendedCapPointer, 4);
482 
483 					if ((legacySupport & EHCI_LEGSUP_BIOSOWNED) == 0)
484 						break;
485 
486 					TRACE_ALWAYS("controller is still bios owned, waiting\n");
487 					snooze(50000);
488 				}
489 			}
490 
491 			if (legacySupport & EHCI_LEGSUP_BIOSOWNED) {
492 				TRACE_ERROR("bios won't give up control over the host "
493 					"controller (ignoring)\n");
494 			} else if (legacySupport & EHCI_LEGSUP_OSOWNED) {
495 				TRACE_ALWAYS(
496 					"successfully took ownership of the host controller\n");
497 			}
498 
499 			// Force off the BIOS owned flag, and clear all SMIs. Some BIOSes
500 			// do indicate a successful handover but do not remove their SMIs
501 			// and then freeze the system when interrupts are generated.
502 			fPci->write_pci_config(fDevice, extendedCapPointer + 2, 1, 0);
503 			fPci->write_pci_config(fDevice, extendedCapPointer + 4, 4, 0);
504 		} else {
505 			TRACE_ALWAYS(
506 				"extended capability is not a legacy support register\n");
507 		}
508 	} else {
509 		TRACE_ALWAYS("no extended capabilities register\n");
510 	}
511 
512 	// disable interrupts
513 	WriteOpReg(EHCI_USBINTR, 0);
514 
515 	// reset the host controller
516 	if (ControllerReset() != B_OK) {
517 		TRACE_ERROR("host controller failed to reset\n");
518 		return;
519 	}
520 
521 	// reset the segment register
522 	WriteOpReg(EHCI_CTRDSSEGMENT, 0);
523 
524 	// create semaphores the finisher thread will wait for
525 	fAsyncAdvanceSem = create_sem(0, "EHCI Async Advance");
526 	fFinishTransfersSem = create_sem(0, "EHCI Finish Transfers");
527 	fCleanupSem = create_sem(0, "EHCI Cleanup");
528 	if (fFinishTransfersSem < 0 || fAsyncAdvanceSem < 0 || fCleanupSem < 0) {
529 		TRACE_ERROR("failed to create semaphores\n");
530 		return;
531 	}
532 
533 	// create finisher service thread
534 	fFinishThread = spawn_kernel_thread(FinishThread, "ehci finish thread",
535 		B_NORMAL_PRIORITY, (void *)this);
536 	resume_thread(fFinishThread);
537 
538 	// Create semaphore the isochronous finisher thread will wait for
539 	fFinishIsochronousTransfersSem = create_sem(0,
540 		"EHCI Isochronous Finish Transfers");
541 	if (fFinishIsochronousTransfersSem < 0) {
542 		TRACE_ERROR("failed to create isochronous finisher semaphore\n");
543 		return;
544 	}
545 
546 	// Create the isochronous finisher service thread
547 	fFinishIsochronousThread = spawn_kernel_thread(FinishIsochronousThread,
548 		"ehci isochronous finish thread", B_URGENT_DISPLAY_PRIORITY,
549 		(void *)this);
550 	resume_thread(fFinishIsochronousThread);
551 
552 	// create cleanup service thread
553 	fCleanupThread = spawn_kernel_thread(CleanupThread, "ehci cleanup thread",
554 		B_NORMAL_PRIORITY, (void *)this);
555 	resume_thread(fCleanupThread);
556 
557 	// set up interrupts or interrupt polling now that the controller is ready
558 	bool polling = false;
559 	void *settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
560 	if (settings != NULL) {
561 		polling = get_driver_boolean_parameter(settings, "ehci_polling", false,
562 			false);
563 		unload_driver_settings(settings);
564 	}
565 
566 	if (polling) {
567 		// create and run the polling thread
568 		TRACE_ALWAYS("enabling ehci polling\n");
569 		fInterruptPollThread = spawn_kernel_thread(InterruptPollThread,
570 			"ehci interrupt poll thread", B_NORMAL_PRIORITY, (void *)this);
571 		resume_thread(fInterruptPollThread);
572 	} else {
573 		// Find the right interrupt vector, using MSIs if available.
574 		fIRQ = fPCIInfo->u.h0.interrupt_line;
575 		if (fPci->get_msi_count(fDevice) >= 1) {
576 			uint8 msiVector = 0;
577 			if (fPci->configure_msi(fDevice, 1, &msiVector) == B_OK
578 				&& fPci->enable_msi(fDevice) == B_OK) {
579 				TRACE_ALWAYS("using message signaled interrupts\n");
580 				fIRQ = msiVector;
581 				fUseMSI = true;
582 			}
583 		}
584 
585 		if (fIRQ == 0 || fIRQ == 0xFF) {
586 			TRACE_MODULE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n",
587 				fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function);
588 			return;
589 		}
590 
591 		// install the interrupt handler and enable interrupts
592 		install_io_interrupt_handler(fIRQ, InterruptHandler,
593 			(void *)this, 0);
594 	}
595 
596 	// ensure that interrupts are en-/disabled on the PCI device
597 	command = fPci->read_pci_config(fDevice, PCI_command, 2);
598 	if ((polling || fUseMSI) == ((command & PCI_command_int_disable) == 0)) {
599 		if (polling || fUseMSI)
600 			command &= ~PCI_command_int_disable;
601 		else
602 			command |= PCI_command_int_disable;
603 
604 		fPci->write_pci_config(fDevice, PCI_command, 2, command);
605 	}
606 
607 	fEnabledInterrupts = EHCI_USBINTR_HOSTSYSERR | EHCI_USBINTR_USBERRINT
608 		| EHCI_USBINTR_USBINT | EHCI_USBINTR_INTONAA;
609 	WriteOpReg(EHCI_USBINTR, fEnabledInterrupts);
610 
611 	// structures don't span page boundaries
612 	size_t itdListSize = EHCI_VFRAMELIST_ENTRIES_COUNT
613 		/ (B_PAGE_SIZE / sizeof(itd_entry)) * B_PAGE_SIZE;
614 	size_t sitdListSize = EHCI_VFRAMELIST_ENTRIES_COUNT
615 		/ (B_PAGE_SIZE / sizeof(sitd_entry)) * B_PAGE_SIZE;
616 	size_t frameListSize = B_PAGE_SIZE + B_PAGE_SIZE + itdListSize
617 		+ sitdListSize;
618 
619 	// allocate the periodic frame list
620 	fPeriodicFrameListArea = fStack->AllocateArea((void **)&fPeriodicFrameList,
621 		&physicalAddress, frameListSize, "USB EHCI Periodic Framelist");
622 	if (fPeriodicFrameListArea < 0) {
623 		TRACE_ERROR("unable to allocate periodic framelist\n");
624 		return;
625 	}
626 
627 	if ((physicalAddress & 0xfff) != 0) {
628 		panic("EHCI_PERIODICLISTBASE not aligned on 4k: 0x%" B_PRIxPHYSADDR
629 			"\n", physicalAddress);
630 	}
631 
632 	// set the periodic frame list base on the controller
633 	WriteOpReg(EHCI_PERIODICLISTBASE, (uint32)physicalAddress);
634 
635 	// create the interrupt entries to support different polling intervals
636 	TRACE("creating interrupt entries\n");
637 	uint32_t physicalBase = physicalAddress + B_PAGE_SIZE;
638 	uint8 *logicalBase = (uint8 *)fPeriodicFrameList + B_PAGE_SIZE;
639 	memset(logicalBase, 0, B_PAGE_SIZE);
640 
641 	fInterruptEntries = (interrupt_entry *)logicalBase;
642 	for (int32 i = 0; i < EHCI_INTERRUPT_ENTRIES_COUNT; i++) {
643 		ehci_qh *queueHead = &fInterruptEntries[i].queue_head;
644 		queueHead->this_phy = physicalBase | EHCI_ITEM_TYPE_QH;
645 		queueHead->current_qtd_phy = 0;
646 		queueHead->overlay.next_phy = EHCI_ITEM_TERMINATE;
647 		queueHead->overlay.alt_next_phy = EHCI_ITEM_TERMINATE;
648 		queueHead->overlay.token = EHCI_QTD_STATUS_HALTED;
649 
650 		// set dummy endpoint information
651 		queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH
652 			| (3 << EHCI_QH_CHARS_RL_SHIFT) | (64 << EHCI_QH_CHARS_MPL_SHIFT)
653 			| EHCI_QH_CHARS_TOGGLE;
654 		queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT)
655 			| (0xff << EHCI_QH_CAPS_ISM_SHIFT);
656 
657 		physicalBase += sizeof(interrupt_entry);
658 		if ((physicalBase & 0x1f) != 0) {
659 			panic("physical base for interrupt entry %" B_PRId32
660 				" not aligned on 32, interrupt entry structure size %lu\n",
661 					i, sizeof(interrupt_entry));
662 		}
663 	}
664 
665 	// create the itd and sitd entries
666 	TRACE("build up iso entries\n");
667 	uint32_t itdPhysicalBase = physicalAddress + B_PAGE_SIZE + B_PAGE_SIZE;
668 	itd_entry* itds = (itd_entry *)((uint8 *)fPeriodicFrameList + B_PAGE_SIZE
669 		+ B_PAGE_SIZE);
670 	memset(itds, 0, itdListSize);
671 
672 	uint32_t sitdPhysicalBase = itdPhysicalBase + itdListSize;
673 	sitd_entry* sitds = (sitd_entry *)((uint8 *)fPeriodicFrameList + B_PAGE_SIZE
674 		+ B_PAGE_SIZE + itdListSize);
675 	memset(sitds, 0, sitdListSize);
676 
677 	fItdEntries = new(std::nothrow) ehci_itd *[EHCI_VFRAMELIST_ENTRIES_COUNT];
678 	fSitdEntries = new(std::nothrow) ehci_sitd *[EHCI_VFRAMELIST_ENTRIES_COUNT];
679 
680 	dprintf("sitd entry size %lu, itd entry size %lu\n", sizeof(sitd_entry),
681 		sizeof(itd_entry));
682 	for (int32 i = 0; i < EHCI_VFRAMELIST_ENTRIES_COUNT; i++) {
683 		ehci_sitd *sitd = &sitds[i].sitd;
684 		sitd->this_phy = sitdPhysicalBase | EHCI_ITEM_TYPE_SITD;
685 		sitd->back_phy = EHCI_ITEM_TERMINATE;
686 		fSitdEntries[i] = sitd;
687 		TRACE("sitd entry %" B_PRId32 " %p 0x%" B_PRIx32 "\n", i, sitd,
688 			sitd->this_phy);
689 
690 		ehci_itd *itd = &itds[i].itd;
691 		itd->this_phy = itdPhysicalBase | EHCI_ITEM_TYPE_ITD;
692 		itd->next_phy = sitd->this_phy;
693 		fItdEntries[i] = itd;
694 		TRACE("itd entry %" B_PRId32 " %p 0x%" B_PRIx32 "\n", i, itd,
695 			itd->this_phy);
696 
697 		sitdPhysicalBase += sizeof(sitd_entry);
698 		itdPhysicalBase += sizeof(itd_entry);
699 		if ((sitdPhysicalBase & 0x10) != 0 || (itdPhysicalBase & 0x10) != 0)
700 			panic("physical base for entry %" B_PRId32 " not aligned on 32\n",
701 				i);
702 	}
703 
704 	// build flat interrupt tree
705 	TRACE("build up interrupt links\n");
706 	uint32 interval = EHCI_VFRAMELIST_ENTRIES_COUNT;
707 	uint32 intervalIndex = EHCI_INTERRUPT_ENTRIES_COUNT - 1;
708 	while (interval > 1) {
709 		for (uint32 insertIndex = interval / 2;
710 			insertIndex < EHCI_VFRAMELIST_ENTRIES_COUNT;
711 			insertIndex += interval) {
712 			fSitdEntries[insertIndex]->next_phy
713 				= fInterruptEntries[intervalIndex].queue_head.this_phy;
714 		}
715 
716 		intervalIndex--;
717 		interval /= 2;
718 	}
719 
720 	// setup the empty slot in the list and linking of all -> first
721 	ehci_qh *firstLogical = &fInterruptEntries[0].queue_head;
722 	fSitdEntries[0]->next_phy = firstLogical->this_phy;
723 	for (int32 i = 1; i < EHCI_INTERRUPT_ENTRIES_COUNT; i++) {
724 		fInterruptEntries[i].queue_head.next_phy = firstLogical->this_phy;
725 		fInterruptEntries[i].queue_head.next_log = firstLogical;
726 		fInterruptEntries[i].queue_head.prev_log = NULL;
727 	}
728 
729 	// terminate the first entry
730 	firstLogical->next_phy = EHCI_ITEM_TERMINATE;
731 	firstLogical->next_log = NULL;
732 	firstLogical->prev_log = NULL;
733 
734 	for (int32 i = 0; i < EHCI_FRAMELIST_ENTRIES_COUNT; i++) {
735 		fPeriodicFrameList[i]
736 			= fItdEntries[i & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1)]->this_phy;
737 		TRACE("periodic entry %" B_PRId32 " linked to 0x%" B_PRIx32 "\n", i,
738 			fPeriodicFrameList[i]);
739 	}
740 
741 	// Create the array that will keep bandwidth information
742 	fFrameBandwidth = new(std::nothrow) uint16[EHCI_VFRAMELIST_ENTRIES_COUNT];
743 	for (int32 i = 0; i < EHCI_VFRAMELIST_ENTRIES_COUNT; i++) {
744 		fFrameBandwidth[i] = MAX_AVAILABLE_BANDWIDTH;
745 	}
746 
747 	// allocate a queue head that will always stay in the async frame list
748 	fAsyncQueueHead = CreateQueueHead();
749 	if (!fAsyncQueueHead) {
750 		TRACE_ERROR("unable to allocate stray async queue head\n");
751 		return;
752 	}
753 
754 	fAsyncQueueHead->next_phy = fAsyncQueueHead->this_phy;
755 	fAsyncQueueHead->next_log = fAsyncQueueHead;
756 	fAsyncQueueHead->prev_log = fAsyncQueueHead;
757 	fAsyncQueueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH
758 		| EHCI_QH_CHARS_RECHEAD;
759 	fAsyncQueueHead->endpoint_caps = 1 << EHCI_QH_CAPS_MULT_SHIFT;
760 	fAsyncQueueHead->overlay.next_phy = EHCI_ITEM_TERMINATE;
761 
762 	WriteOpReg(EHCI_ASYNCLISTADDR, (uint32)fAsyncQueueHead->this_phy);
763 	TRACE("set the async list addr to 0x%08" B_PRIx32 "\n",
764 		ReadOpReg(EHCI_ASYNCLISTADDR));
765 
766 	fInitOK = true;
767 	TRACE("EHCI host controller driver constructed\n");
768 }
769 
770 
771 EHCI::~EHCI()
772 {
773 	TRACE("tear down EHCI host controller driver\n");
774 
775 	WriteOpReg(EHCI_USBCMD, 0);
776 	WriteOpReg(EHCI_CONFIGFLAG, 0);
777 	CancelAllPendingTransfers();
778 
779 	int32 result = 0;
780 	fStopThreads = true;
781 	delete_sem(fAsyncAdvanceSem);
782 	delete_sem(fFinishTransfersSem);
783 	delete_sem(fFinishIsochronousTransfersSem);
784 	delete_sem(fCleanupSem);
785 	wait_for_thread(fFinishThread, &result);
786 	wait_for_thread(fCleanupThread, &result);
787 	wait_for_thread(fFinishIsochronousThread, &result);
788 
789 	if (fInterruptPollThread >= 0)
790 		wait_for_thread(fInterruptPollThread, &result);
791 	else
792 		remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this);
793 
794 	LockIsochronous();
795 	isochronous_transfer_data *isoTransfer = fFirstIsochronousTransfer;
796 	while (isoTransfer) {
797 		isochronous_transfer_data *next = isoTransfer->link;
798 		delete isoTransfer;
799 		isoTransfer = next;
800 	}
801 	mutex_destroy(&fIsochronousLock);
802 
803 	delete fRootHub;
804 	delete [] fFrameBandwidth;
805 	delete [] fItdEntries;
806 	delete [] fSitdEntries;
807 	delete_area(fPeriodicFrameListArea);
808 	delete_area(fRegisterArea);
809 
810 	if (fUseMSI) {
811 		fPci->disable_msi(fDevice);
812 		fPci->unconfigure_msi(fDevice);
813 	}
814 
815 }
816 
817 
818 status_t
819 EHCI::Start()
820 {
821 	TRACE("starting EHCI host controller\n");
822 	TRACE("usbcmd: 0x%08" B_PRIx32 "; usbsts: 0x%08" B_PRIx32 "\n",
823 		ReadOpReg(EHCI_USBCMD), ReadOpReg(EHCI_USBSTS));
824 
825 	bool hasPerPortChangeEvent = (ReadCapReg32(EHCI_HCCPARAMS)
826 		& EHCI_HCCPARAMS_PPCEC) != 0;
827 
828 	uint32 config = ReadOpReg(EHCI_USBCMD);
829 	config &= ~((EHCI_USBCMD_ITC_MASK << EHCI_USBCMD_ITC_SHIFT)
830 		| EHCI_USBCMD_PPCEE);
831 	uint32 frameListSize = (config >> EHCI_USBCMD_FLS_SHIFT)
832 		& EHCI_USBCMD_FLS_MASK;
833 
834 	WriteOpReg(EHCI_USBCMD, config | EHCI_USBCMD_RUNSTOP
835 		| (hasPerPortChangeEvent ? EHCI_USBCMD_PPCEE : 0)
836 		| EHCI_USBCMD_ASENABLE | EHCI_USBCMD_PSENABLE
837 		| (frameListSize << EHCI_USBCMD_FLS_SHIFT)
838 		| (1 << EHCI_USBCMD_ITC_SHIFT));
839 
840 	switch (frameListSize) {
841 		case 0:
842 			TRACE("frame list size 1024\n");
843 			break;
844 		case 1:
845 			TRACE("frame list size 512\n");
846 			break;
847 		case 2:
848 			TRACE("frame list size 256\n");
849 			break;
850 		default:
851 			TRACE_ALWAYS("unknown frame list size\n");
852 	}
853 
854 	bool running = false;
855 	for (int32 i = 0; i < 10; i++) {
856 		uint32 status = ReadOpReg(EHCI_USBSTS);
857 		TRACE("try %" B_PRId32 ": status 0x%08" B_PRIx32 "\n", i, status);
858 
859 		if (status & EHCI_USBSTS_HCHALTED) {
860 			snooze(10000);
861 		} else {
862 			running = true;
863 			break;
864 		}
865 	}
866 
867 	if (!running) {
868 		TRACE_ERROR("host controller didn't start\n");
869 		return B_ERROR;
870 	}
871 
872 	// route all ports to us
873 	WriteOpReg(EHCI_CONFIGFLAG, EHCI_CONFIGFLAG_FLAG);
874 	snooze(10000);
875 
876 	fRootHubAddress = AllocateAddress();
877 	fRootHub = new(std::nothrow) EHCIRootHub(RootObject(), fRootHubAddress);
878 	if (!fRootHub) {
879 		TRACE_ERROR("no memory to allocate root hub\n");
880 		return B_NO_MEMORY;
881 	}
882 
883 	if (fRootHub->InitCheck() != B_OK) {
884 		TRACE_ERROR("root hub failed init check\n");
885 		return fRootHub->InitCheck();
886 	}
887 
888 	SetRootHub(fRootHub);
889 
890 	fRootHub->RegisterNode(Node());
891 
892 	TRACE_ALWAYS("successfully started the controller\n");
893 	return BusManager::Start();
894 }
895 
896 
897 status_t
898 EHCI::StartDebugTransfer(Transfer *transfer)
899 {
900 	static transfer_data transferData;
901 
902 	transferData.queue_head = CreateQueueHead();
903 	if (transferData.queue_head == NULL)
904 		return B_NO_MEMORY;
905 
906 	Pipe *pipe = transfer->TransferPipe();
907 	status_t result = InitQueueHead(transferData.queue_head, pipe);
908 	if (result != B_OK) {
909 		FreeQueueHead(transferData.queue_head);
910 		return result;
911 	}
912 
913 	if ((pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0) {
914 		result = FillQueueWithRequest(transfer, transferData.queue_head,
915 			&transferData.data_descriptor, &transferData.incoming, false);
916 	} else {
917 		result = FillQueueWithData(transfer, transferData.queue_head,
918 			&transferData.data_descriptor, &transferData.incoming, false);
919 	}
920 
921 	if (result != B_OK) {
922 		FreeQueueHead(transferData.queue_head);
923 		return result;
924 	}
925 
926 	if ((pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) != 0)
927 		LinkPeriodicDebugQueueHead(transferData.queue_head, pipe);
928 	else
929 		LinkAsyncDebugQueueHead(transferData.queue_head);
930 
931 	// we abuse the callback cookie to hold our transfer data
932 	transfer->SetCallback(NULL, &transferData);
933 	return B_OK;
934 }
935 
936 
937 void
938 EHCI::LinkAsyncDebugQueueHead(ehci_qh *queueHead)
939 {
940 	ehci_qh *prevHead = fAsyncQueueHead->prev_log;
941 	queueHead->next_phy = fAsyncQueueHead->this_phy;
942 	queueHead->next_log = fAsyncQueueHead;
943 	queueHead->prev_log = prevHead;
944 	fAsyncQueueHead->prev_log = queueHead;
945 	prevHead->next_log = queueHead;
946 	prevHead->next_phy = queueHead->this_phy;
947 }
948 
949 
950 void
951 EHCI::LinkPeriodicDebugQueueHead(ehci_qh *queueHead, Pipe *pipe)
952 {
953 	if (pipe->Speed() == USB_SPEED_HIGHSPEED)
954 		queueHead->endpoint_caps |= (0xff << EHCI_QH_CAPS_ISM_SHIFT);
955 	else {
956 		queueHead->endpoint_caps |= (0x01 << EHCI_QH_CAPS_ISM_SHIFT);
957 		queueHead->endpoint_caps |= (0x1c << EHCI_QH_CAPS_SCM_SHIFT);
958 	}
959 
960 	ehci_qh *interruptQueue = &fInterruptEntries[0].queue_head;
961 	queueHead->next_phy = interruptQueue->next_phy;
962 	queueHead->next_log = interruptQueue->next_log;
963 	queueHead->prev_log = interruptQueue;
964 	if (interruptQueue->next_log)
965 		interruptQueue->next_log->prev_log = queueHead;
966 	interruptQueue->next_log = queueHead;
967 	interruptQueue->next_phy = queueHead->this_phy;
968 }
969 
970 
971 status_t
972 EHCI::CheckDebugTransfer(Transfer *transfer)
973 {
974 	bool transferOK = false;
975 	bool transferError = false;
976 	transfer_data *transferData = (transfer_data *)transfer->CallbackCookie();
977 	ehci_qtd *descriptor = transferData->queue_head->element_log;
978 
979 	while (descriptor) {
980 		uint32 status = descriptor->token;
981 		if ((status & EHCI_QTD_STATUS_ACTIVE) != 0) {
982 			// still in progress
983 			break;
984 		}
985 
986 		if ((status & EHCI_QTD_STATUS_ERRMASK) != 0) {
987 			transferError = true;
988 			break;
989 		}
990 
991 		if ((descriptor->next_phy & EHCI_ITEM_TERMINATE) != 0) {
992 			// we arrived at the last (stray) descriptor, we're done
993 			transferOK = true;
994 			break;
995 		}
996 
997 		if (((status >> EHCI_QTD_PID_SHIFT) & EHCI_QTD_PID_MASK)
998 				== EHCI_QTD_PID_IN
999 			&& ((status >> EHCI_QTD_BYTES_SHIFT) & EHCI_QTD_BYTES_MASK) != 0) {
1000 			// a short packet condition existed on this descriptor
1001 			if (descriptor->alt_next_log != NULL) {
1002 				descriptor = descriptor->alt_next_log;
1003 				continue;
1004 			}
1005 
1006 			transferOK = true;
1007 			break;
1008 		}
1009 
1010 		descriptor = descriptor->next_log;
1011 	}
1012 
1013 	if (!transferOK && !transferError) {
1014 		spin(75);
1015 		return B_DEV_PENDING;
1016 	}
1017 
1018 	if (transferOK) {
1019 		bool nextDataToggle = false;
1020 		if (transferData->data_descriptor != NULL && transferData->incoming) {
1021 			// data to read out
1022 			generic_io_vec *vector = transfer->Vector();
1023 			size_t vectorCount = transfer->VectorCount();
1024 
1025 			ReadDescriptorChain(transferData->data_descriptor,
1026 				vector, vectorCount, transfer->IsPhysical(), &nextDataToggle);
1027 		} else if (transferData->data_descriptor != NULL)
1028 			ReadActualLength(transferData->data_descriptor, &nextDataToggle);
1029 
1030 		transfer->TransferPipe()->SetDataToggle(nextDataToggle);
1031 	}
1032 
1033 	CleanupDebugTransfer(transfer);
1034 	return transferOK ? B_OK : B_IO_ERROR;
1035 }
1036 
1037 
1038 void
1039 EHCI::CancelDebugTransfer(Transfer *transfer)
1040 {
1041 	transfer_data *transferData = (transfer_data *)transfer->CallbackCookie();
1042 
1043 	// clear the active bit so the descriptors are canceled
1044 	ehci_qtd *descriptor = transferData->queue_head->element_log;
1045 	while (descriptor != NULL) {
1046 		descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE;
1047 		descriptor = descriptor->next_log;
1048 	}
1049 
1050 	transfer->Finished(B_CANCELED, 0);
1051 	CleanupDebugTransfer(transfer);
1052 }
1053 
1054 
1055 void
1056 EHCI::CleanupDebugTransfer(Transfer *transfer)
1057 {
1058 	transfer_data *transferData = (transfer_data *)transfer->CallbackCookie();
1059 	ehci_qh *queueHead = transferData->queue_head;
1060 	ehci_qh *prevHead = queueHead->prev_log;
1061 	if (prevHead != NULL) {
1062 		prevHead->next_phy = queueHead->next_phy;
1063 		prevHead->next_log = queueHead->next_log;
1064 	}
1065 
1066 	ehci_qh *nextHead = queueHead->next_log;
1067 	if (nextHead != NULL)
1068 		nextHead->prev_log = queueHead->prev_log;
1069 
1070 	queueHead->next_phy = fAsyncQueueHead->this_phy;
1071 	queueHead->prev_log = NULL;
1072 	queueHead->next_log = NULL;
1073 
1074 	// wait for async advance to ensure the controller does not access this
1075 	// queue head anymore.
1076 	spin(125);
1077 
1078 	FreeQueueHead(queueHead);
1079 }
1080 
1081 
1082 status_t
1083 EHCI::SubmitTransfer(Transfer *transfer)
1084 {
1085 	// short circuit the root hub
1086 	if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
1087 		return fRootHub->ProcessTransfer(this, transfer);
1088 
1089 	Pipe *pipe = transfer->TransferPipe();
1090 	if ((pipe->Type() & USB_OBJECT_ISO_PIPE) != 0)
1091 		return SubmitIsochronous(transfer);
1092 
1093 	status_t result = transfer->InitKernelAccess();
1094 	if (result != B_OK)
1095 		return result;
1096 
1097 	ehci_qh *queueHead = CreateQueueHead();
1098 	if (!queueHead) {
1099 		TRACE_ERROR("failed to allocate queue head\n");
1100 		return B_NO_MEMORY;
1101 	}
1102 
1103 	result = InitQueueHead(queueHead, pipe);
1104 	if (result != B_OK) {
1105 		TRACE_ERROR("failed to init queue head\n");
1106 		FreeQueueHead(queueHead);
1107 		return result;
1108 	}
1109 
1110 	bool directionIn;
1111 	ehci_qtd *dataDescriptor;
1112 	if ((pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0) {
1113 		result = FillQueueWithRequest(transfer, queueHead, &dataDescriptor,
1114 			&directionIn, true);
1115 	} else {
1116 		result = FillQueueWithData(transfer, queueHead, &dataDescriptor,
1117 			&directionIn, true);
1118 	}
1119 
1120 	if (result != B_OK) {
1121 		TRACE_ERROR("failed to fill transfer queue with data\n");
1122 		FreeQueueHead(queueHead);
1123 		return result;
1124 	}
1125 
1126 	result = AddPendingTransfer(transfer, queueHead, dataDescriptor,
1127 		directionIn);
1128 	if (result != B_OK) {
1129 		TRACE_ERROR("failed to add pending transfer\n");
1130 		FreeQueueHead(queueHead);
1131 		return result;
1132 	}
1133 
1134 #ifdef TRACE_USB
1135 	TRACE("linking queue\n");
1136 	print_queue(queueHead);
1137 #endif
1138 
1139 	if ((pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) != 0)
1140 		result = LinkInterruptQueueHead(queueHead, pipe);
1141 	else
1142 		result = LinkQueueHead(queueHead);
1143 
1144 	if (result != B_OK) {
1145 		TRACE_ERROR("failed to link queue head\n");
1146 		FreeQueueHead(queueHead);
1147 		return result;
1148 	}
1149 
1150 	return B_OK;
1151 }
1152 
1153 
1154 status_t
1155 EHCI::SubmitIsochronous(Transfer *transfer)
1156 {
1157 	Pipe *pipe = transfer->TransferPipe();
1158 	bool directionIn = (pipe->Direction() == Pipe::In);
1159 	usb_isochronous_data *isochronousData = transfer->IsochronousData();
1160 	size_t packetSize = transfer->DataLength();
1161 #ifdef TRACE_USB
1162 	size_t restSize = packetSize % isochronousData->packet_count;
1163 #endif
1164 	packetSize /= isochronousData->packet_count;
1165 	uint16 currentFrame;
1166 
1167 	if (packetSize > pipe->MaxPacketSize()) {
1168 		TRACE_ERROR(
1169 			"isochronous packetSize is bigger than pipe MaxPacketSize\n");
1170 		return B_BAD_VALUE;
1171 	}
1172 
1173 	status_t result = transfer->InitKernelAccess();
1174 	if (result != B_OK)
1175 		return result;
1176 
1177 	// Ignore the fact that the last descriptor might need less bandwidth.
1178 	// The overhead is not worthy.
1179 	uint16 bandwidth = transfer->Bandwidth() / isochronousData->packet_count;
1180 
1181 	TRACE("isochronous transfer descriptor bandwidth %d\n", bandwidth);
1182 
1183 	// The following holds the list of transfer descriptor of the
1184 	// isochronous request. It is used to quickly remove all the isochronous
1185 	// descriptors from the frame list, as descriptors are not link to each
1186 	// other in a queue like for every other transfer.
1187 	ehci_itd **isoRequest
1188 		= new(std::nothrow) ehci_itd *[isochronousData->packet_count];
1189 	if (isoRequest == NULL) {
1190 		TRACE("failed to create isoRequest array!\n");
1191 		return B_NO_MEMORY;
1192 	}
1193 
1194 	TRACE("isochronous submitted size=%" B_PRIuSIZE " bytes, TDs=%" B_PRIu32
1195 		", maxPacketSize=%" B_PRIuSIZE ", packetSize=%" B_PRIuSIZE
1196 		", restSize=%" B_PRIuSIZE "\n", transfer->DataLength(),
1197 		isochronousData->packet_count, pipe->MaxPacketSize(), packetSize,
1198 		restSize);
1199 
1200 	// Find the entry where to start inserting the first Isochronous descriptor
1201 	if ((isochronousData->flags & USB_ISO_ASAP) != 0 ||
1202 		isochronousData->starting_frame_number == NULL) {
1203 
1204 		if (fFirstIsochronousTransfer != NULL && fNextStartingFrame != -1)
1205 			currentFrame = fNextStartingFrame;
1206 		else {
1207 			uint32 threshold = fThreshold;
1208 			TRACE("threshold: %" B_PRIu32 "\n", threshold);
1209 
1210 			// find the first available frame with enough bandwidth.
1211 			// This should always be the case, as defining the starting frame
1212 			// number in the driver makes no sense for many reason, one of which
1213 			// is that frame numbers value are host controller specific, and the
1214 			// driver does not know which host controller is running.
1215 			currentFrame = ((ReadOpReg(EHCI_FRINDEX) + threshold) / 8)
1216 				& (EHCI_FRAMELIST_ENTRIES_COUNT - 1);
1217 		}
1218 
1219 		// Make sure that:
1220 		// 1. We are at least 5ms ahead the controller
1221 		// 2. We stay in the range 0-127
1222 		// 3. There is enough bandwidth in the first entry
1223 		currentFrame &= EHCI_VFRAMELIST_ENTRIES_COUNT - 1;
1224 	} else {
1225 		// Find out if the frame number specified has enough bandwidth,
1226 		// otherwise find the first next available frame with enough bandwidth
1227 		currentFrame = *isochronousData->starting_frame_number;
1228 	}
1229 
1230 	TRACE("isochronous starting frame=%d\n", currentFrame);
1231 
1232 	uint16 itdIndex = 0;
1233 	size_t dataLength = transfer->DataLength();
1234 	void* bufferLog;
1235 	phys_addr_t bufferPhy;
1236 	if (fStack->AllocateChunk(&bufferLog, &bufferPhy, dataLength) != B_OK) {
1237 		TRACE_ERROR("unable to allocate itd buffer\n");
1238 		delete[] isoRequest;
1239 		return B_NO_MEMORY;
1240 	}
1241 
1242 	memset(bufferLog, 0, dataLength);
1243 
1244 	phys_addr_t currentPhy = bufferPhy;
1245 	uint32 frameCount = 0;
1246 	while (dataLength > 0) {
1247 		ehci_itd* itd = CreateItdDescriptor();
1248 		isoRequest[itdIndex++] = itd;
1249 		uint16 pg = 0;
1250 		itd->buffer_phy[pg] = currentPhy & 0xfffff000;
1251 		uint32 offset = currentPhy & 0xfff;
1252 		TRACE("isochronous created itd, filling it with phy %" B_PRIxPHYSADDR
1253 			"\n", currentPhy);
1254 		for (int32 i = 0; i < 8 && dataLength > 0; i++) {
1255 			size_t length = min_c(dataLength, packetSize);
1256 			itd->token[i] = (EHCI_ITD_STATUS_ACTIVE << EHCI_ITD_STATUS_SHIFT)
1257 				| (length << EHCI_ITD_TLENGTH_SHIFT) | (pg << EHCI_ITD_PG_SHIFT)
1258 				| (offset << EHCI_ITD_TOFFSET_SHIFT);
1259 			itd->last_token = i;
1260 			TRACE("isochronous filled slot %" B_PRId32 " 0x%" B_PRIx32 "\n", i,
1261 				itd->token[i]);
1262 			dataLength -= length;
1263 			offset += length;
1264 			if (dataLength > 0 && offset > 0xfff) {
1265 				offset -= B_PAGE_SIZE;
1266 				currentPhy += B_PAGE_SIZE;
1267 				itd->buffer_phy[pg + 1] = currentPhy & 0xfffff000;
1268 				pg++;
1269 			}
1270 			if (dataLength <= 0)
1271 				itd->token[i] |= EHCI_ITD_IOC;
1272 		}
1273 
1274 		currentPhy += (offset & 0xfff) - (currentPhy & 0xfff);
1275 
1276 		itd->buffer_phy[0]
1277 			|= (pipe->EndpointAddress() << EHCI_ITD_ENDPOINT_SHIFT)
1278 				| (pipe->DeviceAddress() << EHCI_ITD_ADDRESS_SHIFT);
1279 		itd->buffer_phy[1]
1280 			|= (pipe->MaxPacketSize() & EHCI_ITD_MAXPACKETSIZE_MASK)
1281 				| (directionIn << EHCI_ITD_DIR_SHIFT);
1282 		itd->buffer_phy[2]
1283 			|= ((((pipe->MaxPacketSize() >> EHCI_ITD_MAXPACKETSIZE_LENGTH) + 1)
1284 				& EHCI_ITD_MUL_MASK) << EHCI_ITD_MUL_SHIFT);
1285 
1286 		TRACE("isochronous filled itd buffer_phy[0,1,2] 0x%" B_PRIx32 ", 0x%"
1287 			B_PRIx32 " 0x%" B_PRIx32 "\n",
1288 			itd->buffer_phy[0], itd->buffer_phy[1], itd->buffer_phy[2]);
1289 
1290 		if (!LockIsochronous())
1291 			continue;
1292 		LinkITDescriptors(itd, &fItdEntries[currentFrame]);
1293 		UnlockIsochronous();
1294 		fFrameBandwidth[currentFrame] -= bandwidth;
1295 		currentFrame = (currentFrame + 1) & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1);
1296 		frameCount++;
1297 	}
1298 
1299 	TRACE("isochronous filled itds count %d\n", itdIndex);
1300 
1301 	// Add transfer to the list
1302 	result = AddPendingIsochronousTransfer(transfer, isoRequest,
1303 		itdIndex - 1, directionIn, bufferPhy, bufferLog,
1304 		transfer->DataLength());
1305 	if (result != B_OK) {
1306 		TRACE_ERROR("failed to add pending isochronous transfer\n");
1307 		for (uint32 i = 0; i < itdIndex; i++)
1308 			FreeDescriptor(isoRequest[i]);
1309 		delete[] isoRequest;
1310 		return result;
1311 	}
1312 
1313 	TRACE("appended isochronous transfer by starting at frame number %d\n",
1314 		currentFrame);
1315 	fNextStartingFrame = currentFrame + 1;
1316 
1317 	// Wake up the isochronous finisher thread
1318 	release_sem_etc(fFinishIsochronousTransfersSem, 1 /*frameCount*/,
1319 		B_DO_NOT_RESCHEDULE);
1320 
1321 	return B_OK;
1322 }
1323 
1324 
1325 isochronous_transfer_data *
1326 EHCI::FindIsochronousTransfer(ehci_itd *itd)
1327 {
1328 	// Simply check every last descriptor of the isochronous transfer list
1329 	isochronous_transfer_data *transfer = fFirstIsochronousTransfer;
1330 	if (transfer) {
1331 		while (transfer->descriptors[transfer->last_to_process]
1332 			!= itd) {
1333 			transfer = transfer->link;
1334 			if (!transfer)
1335 				break;
1336 		}
1337 	}
1338 	return transfer;
1339 }
1340 
1341 
1342 status_t
1343 EHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
1344 {
1345 	TRACE("pipe change %d for pipe %p\n", change, pipe);
1346 	switch (change) {
1347 		case USB_CHANGE_CREATED:
1348 		case USB_CHANGE_DESTROYED: {
1349 			// ToDo: we should create and keep a single queue head
1350 			// for all transfers to/from this pipe
1351 			break;
1352 		}
1353 
1354 		case USB_CHANGE_PIPE_POLICY_CHANGED: {
1355 			// ToDo: for isochronous pipes we might need to adapt to new
1356 			// pipe policy settings here
1357 			break;
1358 		}
1359 	}
1360 
1361 	return B_OK;
1362 }
1363 
1364 
1365 status_t
1366 EHCI::GetPortStatus(uint8 index, usb_port_status *status)
1367 {
1368 	if (index >= fPortCount)
1369 		return B_BAD_INDEX;
1370 
1371 	status->status = status->change = 0;
1372 	uint32 portStatus = ReadOpReg(EHCI_PORTSC + index * sizeof(uint32));
1373 
1374 	// build the status
1375 	if (portStatus & EHCI_PORTSC_CONNSTATUS)
1376 		status->status |= PORT_STATUS_CONNECTION;
1377 	if (portStatus & EHCI_PORTSC_ENABLE)
1378 		status->status |= PORT_STATUS_ENABLE;
1379 	if (portStatus & EHCI_PORTSC_ENABLE)
1380 		status->status |= PORT_STATUS_HIGH_SPEED;
1381 	if (portStatus & EHCI_PORTSC_OCACTIVE)
1382 		status->status |= PORT_STATUS_OVER_CURRENT;
1383 	if (portStatus & EHCI_PORTSC_PORTRESET)
1384 		status->status |= PORT_STATUS_RESET;
1385 	if (portStatus & EHCI_PORTSC_PORTPOWER)
1386 		status->status |= PORT_STATUS_POWER;
1387 	if (portStatus & EHCI_PORTSC_SUSPEND)
1388 		status->status |= PORT_STATUS_SUSPEND;
1389 	if (portStatus & EHCI_PORTSC_DMINUS)
1390 		status->status |= PORT_STATUS_LOW_SPEED;
1391 
1392 	// build the change
1393 	if (portStatus & EHCI_PORTSC_CONNCHANGE)
1394 		status->change |= PORT_STATUS_CONNECTION;
1395 	if (portStatus & EHCI_PORTSC_ENABLECHANGE)
1396 		status->change |= PORT_STATUS_ENABLE;
1397 	if (portStatus & EHCI_PORTSC_OCCHANGE)
1398 		status->change |= PORT_STATUS_OVER_CURRENT;
1399 
1400 	// there are no bits to indicate suspend and reset change
1401 	if (fPortResetChange & (1 << index))
1402 		status->change |= PORT_STATUS_RESET;
1403 	if (fPortSuspendChange & (1 << index))
1404 		status->change |= PORT_STATUS_SUSPEND;
1405 
1406 	return B_OK;
1407 }
1408 
1409 
1410 status_t
1411 EHCI::SetPortFeature(uint8 index, uint16 feature)
1412 {
1413 	if (index >= fPortCount)
1414 		return B_BAD_INDEX;
1415 
1416 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
1417 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1418 
1419 	switch (feature) {
1420 		case PORT_SUSPEND:
1421 			return SuspendPort(index);
1422 
1423 		case PORT_RESET:
1424 			return ResetPort(index);
1425 
1426 		case PORT_POWER:
1427 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTPOWER);
1428 			return B_OK;
1429 	}
1430 
1431 	return B_BAD_VALUE;
1432 }
1433 
1434 
1435 status_t
1436 EHCI::ClearPortFeature(uint8 index, uint16 feature)
1437 {
1438 	if (index >= fPortCount)
1439 		return B_BAD_INDEX;
1440 
1441 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
1442 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1443 
1444 	switch (feature) {
1445 		case PORT_ENABLE:
1446 			WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_ENABLE);
1447 			return B_OK;
1448 
1449 		case PORT_POWER:
1450 			WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTPOWER);
1451 			return B_OK;
1452 
1453 		case C_PORT_CONNECTION:
1454 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_CONNCHANGE);
1455 			return B_OK;
1456 
1457 		case C_PORT_ENABLE:
1458 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_ENABLECHANGE);
1459 			return B_OK;
1460 
1461 		case C_PORT_OVER_CURRENT:
1462 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_OCCHANGE);
1463 			return B_OK;
1464 
1465 		case C_PORT_RESET:
1466 			fPortResetChange &= ~(1 << index);
1467 			return B_OK;
1468 
1469 		case C_PORT_SUSPEND:
1470 			fPortSuspendChange &= ~(1 << index);
1471 			return B_OK;
1472 	}
1473 
1474 	return B_BAD_VALUE;
1475 }
1476 
1477 
1478 status_t
1479 EHCI::ResetPort(uint8 index)
1480 {
1481 	TRACE("reset port %d\n", index);
1482 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
1483 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1484 
1485 	if (portStatus & EHCI_PORTSC_DMINUS) {
1486 		TRACE_ALWAYS("lowspeed device connected, giving up port ownership\n");
1487 		// there is a lowspeed device connected.
1488 		// we give the ownership to a companion controller.
1489 		WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER);
1490 		fPortResetChange |= (1 << index);
1491 		return B_OK;
1492 	}
1493 
1494 	// enable reset signaling
1495 	WriteOpReg(portRegister, (portStatus & ~EHCI_PORTSC_ENABLE)
1496 		| EHCI_PORTSC_PORTRESET);
1497 	snooze(50000);
1498 
1499 	// disable reset signaling
1500 	portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1501 	WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTRESET);
1502 	snooze(2000);
1503 
1504 	portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1505 	if (portStatus & EHCI_PORTSC_PORTRESET) {
1506 		TRACE_ERROR("port reset won't complete\n");
1507 		return B_ERROR;
1508 	}
1509 
1510 	if ((portStatus & EHCI_PORTSC_ENABLE) == 0) {
1511 		TRACE_ALWAYS("fullspeed device connected, giving up port ownership\n");
1512 		// the port was not enabled, this means that no high speed device is
1513 		// attached to this port. we give up ownership to a companion controler
1514 		WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER);
1515 	}
1516 
1517 	fPortResetChange |= (1 << index);
1518 	return B_OK;
1519 }
1520 
1521 
1522 status_t
1523 EHCI::SuspendPort(uint8 index)
1524 {
1525 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
1526 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1527 	WriteOpReg(portRegister, portStatus | EHCI_PORTSC_SUSPEND);
1528 	fPortSuspendChange |= (1 << index);
1529 	return B_OK;
1530 }
1531 
1532 
1533 status_t
1534 EHCI::ControllerReset()
1535 {
1536 	// halt the controller first
1537 	WriteOpReg(EHCI_USBCMD, 0);
1538 	snooze(10000);
1539 
1540 	// then reset it
1541 	WriteOpReg(EHCI_USBCMD, EHCI_USBCMD_HCRESET);
1542 
1543 	int32 tries = 5;
1544 	while (ReadOpReg(EHCI_USBCMD) & EHCI_USBCMD_HCRESET) {
1545 		snooze(10000);
1546 		if (tries-- < 0)
1547 			return B_ERROR;
1548 	}
1549 
1550 	return B_OK;
1551 }
1552 
1553 
1554 status_t
1555 EHCI::LightReset()
1556 {
1557 	return B_ERROR;
1558 }
1559 
1560 
1561 int32
1562 EHCI::InterruptHandler(void *data)
1563 {
1564 	return ((EHCI *)data)->Interrupt();
1565 }
1566 
1567 
1568 int32
1569 EHCI::Interrupt()
1570 {
1571 	static spinlock lock = B_SPINLOCK_INITIALIZER;
1572 	acquire_spinlock(&lock);
1573 
1574 	// check if any interrupt was generated
1575 	uint32 status = ReadOpReg(EHCI_USBSTS) & EHCI_USBSTS_INTMASK;
1576 	if ((status & fEnabledInterrupts) == 0) {
1577 		if (status != 0) {
1578 			TRACE("discarding not enabled interrupts 0x%08" B_PRIx32 "\n",
1579 				status);
1580 			WriteOpReg(EHCI_USBSTS, status);
1581 		}
1582 
1583 		release_spinlock(&lock);
1584 		return B_UNHANDLED_INTERRUPT;
1585 	}
1586 
1587 	bool asyncAdvance = false;
1588 	bool finishTransfers = false;
1589 	int32 result = B_HANDLED_INTERRUPT;
1590 
1591 	if (status & EHCI_USBSTS_USBINT) {
1592 		TRACE("transfer finished\n");
1593 		result = B_INVOKE_SCHEDULER;
1594 		finishTransfers = true;
1595 	}
1596 
1597 	if (status & EHCI_USBSTS_USBERRINT) {
1598 		TRACE("transfer error\n");
1599 		result = B_INVOKE_SCHEDULER;
1600 		finishTransfers = true;
1601 	}
1602 
1603 	if (status & EHCI_USBSTS_FLROLLOVER)
1604 		TRACE("frame list rollover\n");
1605 
1606 	if (status & EHCI_USBSTS_PORTCHANGE)
1607 		TRACE("port change detected\n");
1608 
1609 	if (status & EHCI_USBSTS_INTONAA) {
1610 		TRACE("interrupt on async advance\n");
1611 		asyncAdvance = true;
1612 		result = B_INVOKE_SCHEDULER;
1613 	}
1614 
1615 	if (status & EHCI_USBSTS_HOSTSYSERR)
1616 		TRACE_ERROR("host system error!\n");
1617 
1618 	WriteOpReg(EHCI_USBSTS, status);
1619 	release_spinlock(&lock);
1620 
1621 	if (asyncAdvance)
1622 		release_sem_etc(fAsyncAdvanceSem, 1, B_DO_NOT_RESCHEDULE);
1623 	if (finishTransfers)
1624 		release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
1625 
1626 	return result;
1627 }
1628 
1629 
1630 int32
1631 EHCI::InterruptPollThread(void *data)
1632 {
1633 	EHCI *ehci = (EHCI *)data;
1634 
1635 	while (!ehci->fStopThreads) {
1636 		// TODO: this could be handled much better by only polling when there
1637 		// are actual transfers going on...
1638 		snooze(1000);
1639 
1640 		cpu_status status = disable_interrupts();
1641 		ehci->Interrupt();
1642 		restore_interrupts(status);
1643 	}
1644 
1645 	return 0;
1646 }
1647 
1648 
1649 status_t
1650 EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead,
1651 	ehci_qtd *dataDescriptor, bool directionIn)
1652 {
1653 	transfer_data *data = new(std::nothrow) transfer_data;
1654 	if (!data)
1655 		return B_NO_MEMORY;
1656 
1657 	data->transfer = transfer;
1658 	data->queue_head = queueHead;
1659 	data->data_descriptor = dataDescriptor;
1660 	data->incoming = directionIn;
1661 	data->canceled = false;
1662 	data->link = NULL;
1663 
1664 	if (!Lock()) {
1665 		delete data;
1666 		return B_ERROR;
1667 	}
1668 
1669 	// We do not support queuing other transfers in tandem with a fragmented one.
1670 	transfer_data *it = fFirstTransfer;
1671 	while (it) {
1672 		if (it->transfer && it->transfer->TransferPipe() == transfer->TransferPipe()
1673 				&& it->transfer->IsFragmented()) {
1674 			TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n");
1675 
1676 			Unlock();
1677 			delete data;
1678 			return B_DEV_RESOURCE_CONFLICT;
1679 		}
1680 
1681 		it = it->link;
1682 	}
1683 
1684 	if (fLastTransfer)
1685 		fLastTransfer->link = data;
1686 	else
1687 		fFirstTransfer = data;
1688 
1689 	fLastTransfer = data;
1690 	Unlock();
1691 
1692 	return B_OK;
1693 }
1694 
1695 
1696 status_t
1697 EHCI::AddPendingIsochronousTransfer(Transfer *transfer, ehci_itd **isoRequest,
1698 	uint32 lastIndex, bool directionIn, addr_t bufferPhy, void* bufferLog,
1699 	size_t bufferSize)
1700 {
1701 	if (!transfer || !isoRequest)
1702 		return B_BAD_VALUE;
1703 
1704 	isochronous_transfer_data *data
1705 		= new(std::nothrow) isochronous_transfer_data;
1706 	if (!data)
1707 		return B_NO_MEMORY;
1708 
1709 	data->transfer = transfer;
1710 	data->descriptors = isoRequest;
1711 	data->last_to_process = lastIndex;
1712 	data->incoming = directionIn;
1713 	data->is_active = true;
1714 	data->link = NULL;
1715 	data->buffer_phy = bufferPhy;
1716 	data->buffer_log = bufferLog;
1717 	data->buffer_size = bufferSize;
1718 
1719 	// Put in the isochronous transfer list
1720 	if (!LockIsochronous()) {
1721 		delete data;
1722 		return B_ERROR;
1723 	}
1724 
1725 	if (fLastIsochronousTransfer)
1726 		fLastIsochronousTransfer->link = data;
1727 	else if (!fFirstIsochronousTransfer)
1728 		fFirstIsochronousTransfer = data;
1729 
1730 	fLastIsochronousTransfer = data;
1731 	UnlockIsochronous();
1732 	return B_OK;
1733 }
1734 
1735 
1736 status_t
1737 EHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
1738 {
1739 	if ((pipe->Type() & USB_OBJECT_ISO_PIPE) != 0)
1740 		return CancelQueuedIsochronousTransfers(pipe, force);
1741 
1742 	if (!Lock())
1743 		return B_ERROR;
1744 
1745 	struct transfer_entry {
1746 		Transfer *			transfer;
1747 		transfer_entry *	next;
1748 	};
1749 
1750 	transfer_entry *list = NULL;
1751 	transfer_data *current = fFirstTransfer;
1752 	while (current) {
1753 		if (current->transfer && current->transfer->TransferPipe() == pipe) {
1754 			// clear the active bit so the descriptors are canceled
1755 			ehci_qtd *descriptor = current->queue_head->element_log;
1756 			while (descriptor) {
1757 				descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE;
1758 				descriptor = descriptor->next_log;
1759 			}
1760 
1761 			if (!force) {
1762 				// if the transfer is canceled by force, the one causing the
1763 				// cancel is probably not the one who initiated the transfer
1764 				// and the callback is likely not safe anymore
1765 				transfer_entry *entry
1766 					= (transfer_entry *)malloc(sizeof(transfer_entry));
1767 				if (entry != NULL) {
1768 					entry->transfer = current->transfer;
1769 					current->transfer = NULL;
1770 					entry->next = list;
1771 					list = entry;
1772 				}
1773 			}
1774 
1775 			current->canceled = true;
1776 		}
1777 
1778 		current = current->link;
1779 	}
1780 
1781 	Unlock();
1782 
1783 	while (list != NULL) {
1784 		transfer_entry *next = list->next;
1785 		list->transfer->Finished(B_CANCELED, 0);
1786 		delete list->transfer;
1787 		free(list);
1788 		list = next;
1789 	}
1790 
1791 	// wait for any transfers that might have made it before canceling
1792 	while (fProcessingPipe == pipe)
1793 		snooze(1000);
1794 
1795 	// notify the finisher so it can clean up the canceled transfers
1796 	release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
1797 	return B_OK;
1798 }
1799 
1800 
1801 status_t
1802 EHCI::CancelQueuedIsochronousTransfers(Pipe *pipe, bool force)
1803 {
1804 	isochronous_transfer_data *current = fFirstIsochronousTransfer;
1805 
1806 	while (current) {
1807 		if (current->transfer->TransferPipe() == pipe) {
1808 			// TODO implement
1809 
1810 			// TODO: Use the force paramater in order to avoid calling
1811 			// invalid callbacks
1812 			current->is_active = false;
1813 		}
1814 
1815 		current = current->link;
1816 	}
1817 
1818 	TRACE_ERROR("no isochronous transfer found!\n");
1819 	return B_ERROR;
1820 }
1821 
1822 
1823 status_t
1824 EHCI::CancelAllPendingTransfers()
1825 {
1826 	if (!Lock())
1827 		return B_ERROR;
1828 
1829 	transfer_data *transfer = fFirstTransfer;
1830 	while (transfer) {
1831 		transfer->transfer->Finished(B_CANCELED, 0);
1832 		delete transfer->transfer;
1833 
1834 		transfer_data *next = transfer->link;
1835 		delete transfer;
1836 		transfer = next;
1837 	}
1838 
1839 	fFirstTransfer = NULL;
1840 	fLastTransfer = NULL;
1841 	Unlock();
1842 	return B_OK;
1843 }
1844 
1845 
1846 int32
1847 EHCI::FinishThread(void *data)
1848 {
1849 	((EHCI *)data)->FinishTransfers();
1850 	return B_OK;
1851 }
1852 
1853 
1854 void
1855 EHCI::FinishTransfers()
1856 {
1857 	while (!fStopThreads) {
1858 		if (acquire_sem(fFinishTransfersSem) != B_OK)
1859 			continue;
1860 
1861 		// eat up sems that have been released by multiple interrupts
1862 		int32 semCount = 0;
1863 		get_sem_count(fFinishTransfersSem, &semCount);
1864 		if (semCount > 0) {
1865 			acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT,
1866 				0);
1867 		}
1868 
1869 		if (!Lock())
1870 			continue;
1871 
1872 		TRACE("finishing transfers\n");
1873 		transfer_data *lastTransfer = NULL;
1874 		transfer_data *transfer = fFirstTransfer;
1875 		Unlock();
1876 
1877 		while (transfer) {
1878 			bool transferDone = false;
1879 			ehci_qtd *descriptor = transfer->queue_head->element_log;
1880 			status_t callbackStatus = B_OK;
1881 
1882 			while (descriptor) {
1883 				uint32 status = descriptor->token;
1884 				if (status & EHCI_QTD_STATUS_ACTIVE) {
1885 					// still in progress
1886 					TRACE("qtd (0x%08" B_PRIx32 ") still active\n",
1887 						descriptor->this_phy);
1888 					break;
1889 				}
1890 
1891 				if (status & EHCI_QTD_STATUS_ERRMASK) {
1892 					// a transfer error occured
1893 					TRACE_ERROR("qtd (0x%" B_PRIx32 ") error: 0x%08" B_PRIx32
1894 						"\n", descriptor->this_phy, status);
1895 
1896 					uint8 errorCount = status >> EHCI_QTD_ERRCOUNT_SHIFT;
1897 					errorCount &= EHCI_QTD_ERRCOUNT_MASK;
1898 					if (errorCount == 0) {
1899 						// the error counter counted down to zero, report why
1900 						int32 reasons = 0;
1901 						if (status & EHCI_QTD_STATUS_BUFFER) {
1902 							callbackStatus = transfer->incoming
1903 								? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN;
1904 							reasons++;
1905 						}
1906 						if (status & EHCI_QTD_STATUS_TERROR) {
1907 							callbackStatus = B_DEV_CRC_ERROR;
1908 							reasons++;
1909 						}
1910 						if ((transfer->queue_head->endpoint_chars
1911 								& EHCI_QH_CHARS_EPS_HIGH) == 0) {
1912 							// For full-/lowspeed endpoints the unused ping
1913 							// state bit is used as another error bit, it is
1914 							// unspecific however.
1915 							if ((status & EHCI_QTD_STATUS_LS_ERR) != 0) {
1916 								callbackStatus = B_DEV_STALLED;
1917 								reasons++;
1918 							}
1919 						}
1920 
1921 						if (reasons > 1)
1922 							callbackStatus = B_DEV_MULTIPLE_ERRORS;
1923 						else if (reasons == 0) {
1924 							TRACE_ERROR("error counter counted down to zero "
1925 								"but none of the error bits are set\n");
1926 							callbackStatus = B_DEV_STALLED;
1927 						}
1928 					} else if (status & EHCI_QTD_STATUS_BABBLE) {
1929 						// there is a babble condition
1930 						callbackStatus = transfer->incoming
1931 							? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN;
1932 					} else {
1933 						// if the error counter didn't count down to zero
1934 						// and there was no babble, then this halt was caused
1935 						// by a stall handshake
1936 						callbackStatus = B_DEV_STALLED;
1937 					}
1938 
1939 					transferDone = true;
1940 					break;
1941 				}
1942 
1943 				if (descriptor->next_phy & EHCI_ITEM_TERMINATE) {
1944 					// we arrived at the last (stray) descriptor, we're done
1945 					TRACE("qtd (0x%08" B_PRIx32 ") done\n",
1946 						descriptor->this_phy);
1947 					callbackStatus = B_OK;
1948 					transferDone = true;
1949 					break;
1950 				}
1951 
1952 				if (((status >> EHCI_QTD_PID_SHIFT) & EHCI_QTD_PID_MASK)
1953 						== EHCI_QTD_PID_IN
1954 					&& ((status >> EHCI_QTD_BYTES_SHIFT) & EHCI_QTD_BYTES_MASK)
1955 						!= 0) {
1956 					// a short packet condition existed on this descriptor,
1957 					// follow the alternate next pointer if set
1958 					if (descriptor->alt_next_log != NULL) {
1959 						descriptor = descriptor->alt_next_log;
1960 						continue;
1961 					}
1962 
1963 					// no alternate next, transfer is done
1964 					callbackStatus = B_OK;
1965 					transferDone = true;
1966 					break;
1967 				}
1968 
1969 				descriptor = descriptor->next_log;
1970 			}
1971 
1972 			if (!transferDone) {
1973 				lastTransfer = transfer;
1974 				transfer = transfer->link;
1975 				continue;
1976 			}
1977 
1978 			// remove the transfer from the list first so we are sure
1979 			// it doesn't get canceled while we still process it
1980 			transfer_data *next = transfer->link;
1981 			if (Lock()) {
1982 				if (lastTransfer)
1983 					lastTransfer->link = transfer->link;
1984 
1985 				if (transfer == fFirstTransfer)
1986 					fFirstTransfer = transfer->link;
1987 				if (transfer == fLastTransfer)
1988 					fLastTransfer = lastTransfer;
1989 
1990 				// store the currently processing pipe here so we can wait
1991 				// in cancel if we are processing something on the target pipe
1992 				if (!transfer->canceled)
1993 					fProcessingPipe = transfer->transfer->TransferPipe();
1994 
1995 				transfer->link = NULL;
1996 				Unlock();
1997 			}
1998 
1999 			// if canceled the callback has already been called
2000 			if (!transfer->canceled) {
2001 				size_t actualLength = 0;
2002 
2003 				if (callbackStatus == B_OK) {
2004 					bool nextDataToggle = false;
2005 					if (transfer->data_descriptor && transfer->incoming) {
2006 						// data to read out
2007 						generic_io_vec *vector = transfer->transfer->Vector();
2008 						size_t vectorCount = transfer->transfer->VectorCount();
2009 						callbackStatus = transfer->transfer->PrepareKernelAccess();
2010 						if (callbackStatus == B_OK) {
2011 							actualLength = ReadDescriptorChain(
2012 								transfer->data_descriptor,
2013 								vector, vectorCount, transfer->transfer->IsPhysical(),
2014 								&nextDataToggle);
2015 						}
2016 					} else if (transfer->data_descriptor) {
2017 						// calculate transfered length
2018 						actualLength = ReadActualLength(
2019 							transfer->data_descriptor, &nextDataToggle);
2020 					}
2021 
2022 					transfer->transfer->TransferPipe()->SetDataToggle(
2023 						nextDataToggle);
2024 				}
2025 
2026 				if (callbackStatus == B_OK && transfer->transfer->IsFragmented()) {
2027 					// this transfer may still have data left
2028 					transfer->transfer->AdvanceByFragment(actualLength);
2029 					if (transfer->transfer->FragmentLength() > 0) {
2030 						FreeDescriptorChain(transfer->data_descriptor);
2031 						status_t result = FillQueueWithData(
2032 							transfer->transfer,
2033 							transfer->queue_head,
2034 							&transfer->data_descriptor, NULL, true);
2035 
2036 						if (result == B_OK && Lock()) {
2037 							// reappend the transfer
2038 							if (fLastTransfer)
2039 								fLastTransfer->link = transfer;
2040 							if (!fFirstTransfer)
2041 								fFirstTransfer = transfer;
2042 
2043 							fLastTransfer = transfer;
2044 							Unlock();
2045 
2046 							transfer = next;
2047 							continue;
2048 						}
2049 					}
2050 
2051 					// the transfer is done, but we already set the
2052 					// actualLength with AdvanceByFragment()
2053 					actualLength = 0;
2054 				}
2055 
2056 				transfer->transfer->Finished(callbackStatus, actualLength);
2057 				fProcessingPipe = NULL;
2058 			}
2059 
2060 			// unlink hardware queue and delete the transfer
2061 			UnlinkQueueHead(transfer->queue_head, &fFreeListHead);
2062 			delete transfer->transfer;
2063 			delete transfer;
2064 			transfer = next;
2065 			release_sem(fCleanupSem);
2066 		}
2067 	}
2068 }
2069 
2070 
2071 int32
2072 EHCI::CleanupThread(void *data)
2073 {
2074 	((EHCI *)data)->Cleanup();
2075 	return B_OK;
2076 }
2077 
2078 
2079 void
2080 EHCI::Cleanup()
2081 {
2082 	ehci_qh *lastFreeListHead = NULL;
2083 
2084 	while (!fStopThreads) {
2085 		if (acquire_sem(fCleanupSem) != B_OK)
2086 			continue;
2087 
2088 		ehci_qh *freeListHead = fFreeListHead;
2089 		if (freeListHead == lastFreeListHead)
2090 			continue;
2091 
2092 		// set the doorbell and wait for the host controller to notify us
2093 		WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_INTONAAD);
2094 		if (acquire_sem(fAsyncAdvanceSem) != B_OK)
2095 			continue;
2096 
2097 		ehci_qh *current = freeListHead;
2098 		while (current != lastFreeListHead) {
2099 			ehci_qh *next = current->next_log;
2100 			FreeQueueHead(current);
2101 			current = next;
2102 		}
2103 
2104 		lastFreeListHead = freeListHead;
2105 	}
2106 }
2107 
2108 
2109 int32
2110 EHCI::FinishIsochronousThread(void *data)
2111 {
2112 	((EHCI *)data)->FinishIsochronousTransfers();
2113 	return B_OK;
2114 }
2115 
2116 
2117 void
2118 EHCI::FinishIsochronousTransfers()
2119 {
2120 	/* This thread stays one position behind the controller and processes every
2121 	* isochronous descriptor. Once it finds the last isochronous descriptor
2122 	* of a transfer, it processes the entire transfer.
2123 	*/
2124 	while (!fStopThreads) {
2125 		// Go to sleep if there are no isochronous transfers to process
2126 		if (acquire_sem(fFinishIsochronousTransfersSem) != B_OK)
2127 			return;
2128 
2129 		bool transferDone = false;
2130 
2131 		uint32 frame = (ReadOpReg(EHCI_FRINDEX) / 8 )
2132 			& (EHCI_FRAMELIST_ENTRIES_COUNT - 1);
2133 		uint32 currentFrame = (frame + EHCI_VFRAMELIST_ENTRIES_COUNT - 5)
2134 			& (EHCI_VFRAMELIST_ENTRIES_COUNT - 1);
2135 		uint32 loop = 0;
2136 
2137 		// Process the frame list until one transfer is processed
2138 		while (!transferDone && loop++ < EHCI_VFRAMELIST_ENTRIES_COUNT) {
2139 			// wait 1ms in order to be sure to be one position behind
2140 			// the controller
2141 			while (currentFrame == (((ReadOpReg(EHCI_FRINDEX) / 8)
2142 				& (EHCI_VFRAMELIST_ENTRIES_COUNT - 1)))) {
2143 				snooze(1000);
2144 			}
2145 
2146 			ehci_itd *itd = fItdEntries[currentFrame];
2147 
2148 			TRACE("FinishIsochronousTransfers itd %p phy 0x%" B_PRIx32
2149 				" prev (%p/0x%" B_PRIx32 ") at frame %" B_PRId32 "\n", itd,
2150 				itd->this_phy, itd->prev, itd->prev != NULL
2151 					? itd->prev->this_phy : 0, currentFrame);
2152 
2153 			if (!LockIsochronous())
2154 				continue;
2155 
2156 			// Process the frame till it has isochronous descriptors in it.
2157 			while (!(itd->next_phy & EHCI_ITEM_TERMINATE) && itd->prev != NULL) {
2158 				TRACE("FinishIsochronousTransfers checking itd %p last_token"
2159 					" %" B_PRId32 "\n", itd, itd->last_token);
2160 				TRACE("FinishIsochronousTransfers tokens 0x%" B_PRIx32 " 0x%"
2161 					B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32
2162 					" 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32 "\n",
2163 					itd->token[0], itd->token[1], itd->token[2], itd->token[3],
2164 					itd->token[4], itd->token[5], itd->token[6], itd->token[7]);
2165 				if (((itd->token[itd->last_token] >> EHCI_ITD_STATUS_SHIFT)
2166 					& EHCI_ITD_STATUS_ACTIVE) == EHCI_ITD_STATUS_ACTIVE) {
2167 					TRACE("FinishIsochronousTransfers unprocessed active itd\n");
2168 				}
2169 				UnlinkITDescriptors(itd, &fItdEntries[currentFrame]);
2170 
2171 				// Process the transfer if we found the last descriptor
2172 				isochronous_transfer_data *transfer
2173 					= FindIsochronousTransfer(itd);
2174 					// Process the descriptors only if it is still active and
2175 					// belongs to an inbound transfer. If the transfer is not
2176 					// active, it means the request has been removed, so simply
2177 					// remove the descriptors.
2178 				if (transfer && transfer->is_active) {
2179 					TRACE("FinishIsochronousTransfers active transfer\n");
2180 					size_t actualLength = 0;
2181 					status_t status = B_OK;
2182 					if (((itd->buffer_phy[1] >> EHCI_ITD_DIR_SHIFT) & 1) != 0) {
2183 						status = transfer->transfer->PrepareKernelAccess();
2184 						if (status == B_OK)
2185 							actualLength = ReadIsochronousDescriptorChain(transfer);
2186 					}
2187 
2188 					// Remove the transfer
2189 					if (transfer == fFirstIsochronousTransfer) {
2190 						fFirstIsochronousTransfer = transfer->link;
2191 						if (transfer == fLastIsochronousTransfer)
2192 							fLastIsochronousTransfer = NULL;
2193 					} else {
2194 						isochronous_transfer_data *temp
2195 							= fFirstIsochronousTransfer;
2196 						while (temp != NULL && transfer != temp->link)
2197 							temp = temp->link;
2198 
2199 						if (transfer == fLastIsochronousTransfer)
2200 							fLastIsochronousTransfer = temp;
2201 						if (temp != NULL && temp->link != NULL)
2202 							temp->link = temp->link->link;
2203 					}
2204 					transfer->link = NULL;
2205 
2206 					transfer->transfer->Finished(status, actualLength);
2207 
2208 					itd = itd->prev;
2209 
2210 					for (uint32 i = 0; i <= transfer->last_to_process; i++)
2211 						FreeDescriptor(transfer->descriptors[i]);
2212 
2213 					TRACE("FinishIsochronousTransfers descriptors freed\n");
2214 
2215 					delete [] transfer->descriptors;
2216 					delete transfer->transfer;
2217 					fStack->FreeChunk(transfer->buffer_log,
2218 						(phys_addr_t)transfer->buffer_phy,
2219 						transfer->buffer_size);
2220 					delete transfer;
2221 					transferDone = true;
2222 				} else {
2223 					TRACE("FinishIsochronousTransfers not end of transfer\n");
2224 					itd = itd->prev;
2225 				}
2226 			}
2227 
2228 			UnlockIsochronous();
2229 
2230 			TRACE("FinishIsochronousTransfers next frame\n");
2231 
2232 			// Make sure to reset the frame bandwidth
2233 			fFrameBandwidth[currentFrame] = MAX_AVAILABLE_BANDWIDTH;
2234 			currentFrame = (currentFrame + 1) % EHCI_VFRAMELIST_ENTRIES_COUNT;
2235 		}
2236 	}
2237 }
2238 
2239 
2240 ehci_qh *
2241 EHCI::CreateQueueHead()
2242 {
2243 	ehci_qh *result;
2244 	phys_addr_t physicalAddress;
2245 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
2246 			sizeof(ehci_qh)) != B_OK) {
2247 		TRACE_ERROR("failed to allocate queue head\n");
2248 		return NULL;
2249 	}
2250 
2251 	result->this_phy = (addr_t)physicalAddress | EHCI_ITEM_TYPE_QH;
2252 	result->next_phy = EHCI_ITEM_TERMINATE;
2253 	result->next_log = NULL;
2254 	result->prev_log = NULL;
2255 
2256 	ehci_qtd *descriptor = CreateDescriptor(0, 0);
2257 	if (!descriptor) {
2258 		TRACE_ERROR("failed to allocate initial qtd for queue head\n");
2259 		fStack->FreeChunk(result, physicalAddress, sizeof(ehci_qh));
2260 		return NULL;
2261 	}
2262 
2263 	descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE;
2264 	result->stray_log = descriptor;
2265 	result->element_log = descriptor;
2266 	result->current_qtd_phy = 0;
2267 	result->overlay.next_phy = descriptor->this_phy;
2268 	result->overlay.alt_next_phy = EHCI_ITEM_TERMINATE;
2269 	result->overlay.token = 0;
2270 	for (int32 i = 0; i < 5; i++) {
2271 		result->overlay.buffer_phy[i] = 0;
2272 		result->overlay.ext_buffer_phy[i] = 0;
2273 	}
2274 
2275 	return result;
2276 }
2277 
2278 
2279 status_t
2280 EHCI::InitQueueHead(ehci_qh *queueHead, Pipe *pipe)
2281 {
2282 	switch (pipe->Speed()) {
2283 		case USB_SPEED_LOWSPEED:
2284 			queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_LOW;
2285 			break;
2286 		case USB_SPEED_FULLSPEED:
2287 			queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_FULL;
2288 			break;
2289 		case USB_SPEED_HIGHSPEED:
2290 			queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH;
2291 			break;
2292 		default:
2293 			TRACE_ERROR("unknown pipe speed\n");
2294 			return B_ERROR;
2295 	}
2296 
2297 	queueHead->endpoint_chars |= (3 << EHCI_QH_CHARS_RL_SHIFT)
2298 		| (pipe->MaxPacketSize() << EHCI_QH_CHARS_MPL_SHIFT)
2299 		| (pipe->EndpointAddress() << EHCI_QH_CHARS_EPT_SHIFT)
2300 		| (pipe->DeviceAddress() << EHCI_QH_CHARS_DEV_SHIFT)
2301 		| EHCI_QH_CHARS_TOGGLE;
2302 
2303 	queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT);
2304 	if (pipe->Speed() != USB_SPEED_HIGHSPEED) {
2305 		if ((pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0)
2306 			queueHead->endpoint_chars |= EHCI_QH_CHARS_CONTROL;
2307 
2308 		queueHead->endpoint_caps |= (pipe->HubPort() << EHCI_QH_CAPS_PORT_SHIFT)
2309 			| (pipe->HubAddress() << EHCI_QH_CAPS_HUB_SHIFT);
2310 	}
2311 
2312 	return B_OK;
2313 }
2314 
2315 
2316 void
2317 EHCI::FreeQueueHead(ehci_qh *queueHead)
2318 {
2319 	if (!queueHead)
2320 		return;
2321 
2322 	FreeDescriptorChain(queueHead->element_log);
2323 	FreeDescriptor(queueHead->stray_log);
2324 	fStack->FreeChunk(queueHead, (phys_addr_t)queueHead->this_phy,
2325 		sizeof(ehci_qh));
2326 }
2327 
2328 
2329 status_t
2330 EHCI::LinkQueueHead(ehci_qh *queueHead)
2331 {
2332 	if (!Lock())
2333 		return B_ERROR;
2334 
2335 	ehci_qh *prevHead = fAsyncQueueHead->prev_log;
2336 	queueHead->next_phy = fAsyncQueueHead->this_phy;
2337 	queueHead->next_log = fAsyncQueueHead;
2338 	queueHead->prev_log = prevHead;
2339 	fAsyncQueueHead->prev_log = queueHead;
2340 	prevHead->next_log = queueHead;
2341 	prevHead->next_phy = queueHead->this_phy;
2342 
2343 	Unlock();
2344 	return B_OK;
2345 }
2346 
2347 
2348 status_t
2349 EHCI::LinkInterruptQueueHead(ehci_qh *queueHead, Pipe *pipe)
2350 {
2351 	uint8 interval = pipe->Interval();
2352 	if (pipe->Speed() == USB_SPEED_HIGHSPEED) {
2353 		// Allow interrupts to be scheduled on each possible micro frame.
2354 		queueHead->endpoint_caps |= (0xff << EHCI_QH_CAPS_ISM_SHIFT);
2355 	} else {
2356 		// As we do not yet support FSTNs to correctly reference low/full
2357 		// speed interrupt transfers, we simply put them into the 1 or 8 interval
2358 		// queue. This way we ensure that we reach them on every micro frame
2359 		// and can do the corresponding start/complete split transactions.
2360 		// ToDo: use FSTNs to correctly link non high speed interrupt transfers
2361 		if (pipe->Speed() == USB_SPEED_LOWSPEED) {
2362 			// Low speed devices can't be polled faster than 8ms, so just use
2363 			// that.
2364 			interval = 4;
2365 		} else
2366 			interval = 1;
2367 
2368 		// For now we also force start splits to be in micro frame 0 and
2369 		// complete splits to be in micro frame 2, 3 and 4.
2370 		queueHead->endpoint_caps |= (0x01 << EHCI_QH_CAPS_ISM_SHIFT);
2371 		queueHead->endpoint_caps |= (0x1c << EHCI_QH_CAPS_SCM_SHIFT);
2372 	}
2373 
2374 	// this should not happen
2375 	if (interval < 1)
2376 		interval = 1;
2377 
2378 	// this may happen as intervals can go up to 16; we limit the value to
2379 	// EHCI_INTERRUPT_ENTRIES_COUNT as you cannot support intervals above
2380 	// that with a frame list of just EHCI_VFRAMELIST_ENTRIES_COUNT entries...
2381 	if (interval > EHCI_INTERRUPT_ENTRIES_COUNT)
2382 		interval = EHCI_INTERRUPT_ENTRIES_COUNT;
2383 
2384 	if (!Lock())
2385 		return B_ERROR;
2386 
2387 	ehci_qh *interruptQueue = &fInterruptEntries[interval - 1].queue_head;
2388 	queueHead->next_phy = interruptQueue->next_phy;
2389 	queueHead->next_log = interruptQueue->next_log;
2390 	queueHead->prev_log = interruptQueue;
2391 	if (interruptQueue->next_log)
2392 		interruptQueue->next_log->prev_log = queueHead;
2393 	interruptQueue->next_log = queueHead;
2394 	interruptQueue->next_phy = queueHead->this_phy;
2395 
2396 	Unlock();
2397 	return B_OK;
2398 }
2399 
2400 
2401 status_t
2402 EHCI::UnlinkQueueHead(ehci_qh *queueHead, ehci_qh **freeListHead)
2403 {
2404 	if (!Lock())
2405 		return B_ERROR;
2406 
2407 	ehci_qh *prevHead = queueHead->prev_log;
2408 	ehci_qh *nextHead = queueHead->next_log;
2409 	if (prevHead) {
2410 		prevHead->next_phy = queueHead->next_phy;
2411 		prevHead->next_log = queueHead->next_log;
2412 	}
2413 
2414 	if (nextHead)
2415 		nextHead->prev_log = queueHead->prev_log;
2416 
2417 	queueHead->next_phy = fAsyncQueueHead->this_phy;
2418 	queueHead->prev_log = NULL;
2419 
2420 	queueHead->next_log = *freeListHead;
2421 	*freeListHead = queueHead;
2422 
2423 	Unlock();
2424 	return B_OK;
2425 }
2426 
2427 
2428 status_t
2429 EHCI::FillQueueWithRequest(Transfer *transfer, ehci_qh *queueHead,
2430 	ehci_qtd **_dataDescriptor, bool *_directionIn, bool prepareKernelAccess)
2431 {
2432 	Pipe *pipe = transfer->TransferPipe();
2433 	usb_request_data *requestData = transfer->RequestData();
2434 	bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0;
2435 
2436 	ehci_qtd *setupDescriptor = CreateDescriptor(sizeof(usb_request_data),
2437 		EHCI_QTD_PID_SETUP);
2438 	ehci_qtd *statusDescriptor = CreateDescriptor(0,
2439 		directionIn ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN);
2440 
2441 	if (!setupDescriptor || !statusDescriptor) {
2442 		TRACE_ERROR("failed to allocate descriptors\n");
2443 		FreeDescriptor(setupDescriptor);
2444 		FreeDescriptor(statusDescriptor);
2445 		return B_NO_MEMORY;
2446 	}
2447 
2448 	generic_io_vec vector;
2449 	vector.base = (generic_addr_t)requestData;
2450 	vector.length = sizeof(usb_request_data);
2451 	WriteDescriptorChain(setupDescriptor, &vector, 1, false);
2452 
2453 	ehci_qtd *strayDescriptor = queueHead->stray_log;
2454 	statusDescriptor->token |= EHCI_QTD_IOC | EHCI_QTD_DATA_TOGGLE;
2455 
2456 	ehci_qtd *dataDescriptor = NULL;
2457 	if (transfer->VectorCount() > 0) {
2458 		ehci_qtd *lastDescriptor = NULL;
2459 		status_t result = CreateDescriptorChain(pipe, &dataDescriptor,
2460 			&lastDescriptor, statusDescriptor, transfer->FragmentLength(),
2461 			directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT);
2462 
2463 		if (result != B_OK) {
2464 			FreeDescriptor(setupDescriptor);
2465 			FreeDescriptor(statusDescriptor);
2466 			return result;
2467 		}
2468 
2469 		if (!directionIn) {
2470 			if (prepareKernelAccess) {
2471 				result = transfer->PrepareKernelAccess();
2472 				if (result != B_OK) {
2473 					FreeDescriptor(setupDescriptor);
2474 					FreeDescriptor(statusDescriptor);
2475 					return result;
2476 				}
2477 			}
2478 			WriteDescriptorChain(dataDescriptor, transfer->Vector(),
2479 				transfer->VectorCount(), transfer->IsPhysical());
2480 		}
2481 
2482 		LinkDescriptors(setupDescriptor, dataDescriptor, strayDescriptor);
2483 		LinkDescriptors(lastDescriptor, statusDescriptor, statusDescriptor);
2484 	} else {
2485 		// no data: link setup and status descriptors directly
2486 		LinkDescriptors(setupDescriptor, statusDescriptor, strayDescriptor);
2487 	}
2488 
2489 	queueHead->element_log = setupDescriptor;
2490 	queueHead->overlay.next_phy = setupDescriptor->this_phy;
2491 	queueHead->overlay.alt_next_phy = EHCI_ITEM_TERMINATE;
2492 
2493 	*_dataDescriptor = dataDescriptor;
2494 	*_directionIn = directionIn;
2495 	return B_OK;
2496 }
2497 
2498 
2499 status_t
2500 EHCI::FillQueueWithData(Transfer *transfer, ehci_qh *queueHead,
2501 	ehci_qtd **_dataDescriptor, bool *_directionIn, bool prepareKernelAccess)
2502 {
2503 	Pipe *pipe = transfer->TransferPipe();
2504 	bool directionIn = (pipe->Direction() == Pipe::In);
2505 
2506 	ehci_qtd *firstDescriptor = NULL;
2507 	ehci_qtd *lastDescriptor = NULL;
2508 	ehci_qtd *strayDescriptor = queueHead->stray_log;
2509 	status_t result = CreateDescriptorChain(pipe, &firstDescriptor,
2510 		&lastDescriptor, strayDescriptor, transfer->FragmentLength(),
2511 		directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT);
2512 
2513 	if (result != B_OK)
2514 		return result;
2515 
2516 	lastDescriptor->token |= EHCI_QTD_IOC;
2517 	if (!directionIn) {
2518 		if (prepareKernelAccess) {
2519 			result = transfer->PrepareKernelAccess();
2520 			if (result != B_OK) {
2521 				FreeDescriptorChain(firstDescriptor);
2522 				return result;
2523 			}
2524 		}
2525 		WriteDescriptorChain(firstDescriptor, transfer->Vector(),
2526 			transfer->VectorCount(), transfer->IsPhysical());
2527 	}
2528 
2529 	queueHead->element_log = firstDescriptor;
2530 	queueHead->overlay.next_phy = firstDescriptor->this_phy;
2531 	queueHead->overlay.alt_next_phy = EHCI_ITEM_TERMINATE;
2532 
2533 	*_dataDescriptor = firstDescriptor;
2534 	if (_directionIn)
2535 		*_directionIn = directionIn;
2536 	return B_OK;
2537 }
2538 
2539 
2540 ehci_qtd *
2541 EHCI::CreateDescriptor(size_t bufferSize, uint8 pid)
2542 {
2543 	ehci_qtd *result;
2544 	phys_addr_t physicalAddress;
2545 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
2546 			sizeof(ehci_qtd)) != B_OK) {
2547 		TRACE_ERROR("failed to allocate a qtd\n");
2548 		return NULL;
2549 	}
2550 
2551 	result->this_phy = (addr_t)physicalAddress;
2552 	result->next_phy = EHCI_ITEM_TERMINATE;
2553 	result->next_log = NULL;
2554 	result->alt_next_phy = EHCI_ITEM_TERMINATE;
2555 	result->alt_next_log = NULL;
2556 	result->buffer_size = bufferSize;
2557 	result->token = bufferSize << EHCI_QTD_BYTES_SHIFT;
2558 	result->token |= 3 << EHCI_QTD_ERRCOUNT_SHIFT;
2559 	result->token |= pid << EHCI_QTD_PID_SHIFT;
2560 	result->token |= EHCI_QTD_STATUS_ACTIVE;
2561 	if (bufferSize == 0) {
2562 		result->buffer_log = NULL;
2563 		for (int32 i = 0; i < 5; i++) {
2564 			result->buffer_phy[i] = 0;
2565 			result->ext_buffer_phy[i] = 0;
2566 		}
2567 
2568 		return result;
2569 	}
2570 
2571 	if (fStack->AllocateChunk(&result->buffer_log, &physicalAddress,
2572 			bufferSize) != B_OK) {
2573 		TRACE_ERROR("unable to allocate qtd buffer\n");
2574 		fStack->FreeChunk(result, (phys_addr_t)result->this_phy,
2575 			sizeof(ehci_qtd));
2576 		return NULL;
2577 	}
2578 
2579 	addr_t physicalBase = (addr_t)physicalAddress;
2580 	result->buffer_phy[0] = physicalBase;
2581 	result->ext_buffer_phy[0] = 0;
2582 	for (int32 i = 1; i < 5; i++) {
2583 		physicalBase += B_PAGE_SIZE;
2584 		result->buffer_phy[i] = physicalBase & EHCI_QTD_PAGE_MASK;
2585 		result->ext_buffer_phy[i] = 0;
2586 	}
2587 
2588 	return result;
2589 }
2590 
2591 
2592 status_t
2593 EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **_firstDescriptor,
2594 	ehci_qtd **_lastDescriptor, ehci_qtd *strayDescriptor, size_t bufferSize,
2595 	uint8 pid)
2596 {
2597 	size_t packetSize = B_PAGE_SIZE * 4;
2598 	int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize;
2599 
2600 	bool dataToggle = pipe->DataToggle();
2601 	ehci_qtd *firstDescriptor = NULL;
2602 	ehci_qtd *lastDescriptor = *_firstDescriptor;
2603 	for (int32 i = 0; i < descriptorCount; i++) {
2604 		ehci_qtd *descriptor = CreateDescriptor(min_c(packetSize, bufferSize),
2605 			pid);
2606 
2607 		if (!descriptor) {
2608 			FreeDescriptorChain(firstDescriptor);
2609 			return B_NO_MEMORY;
2610 		}
2611 
2612 		if (dataToggle)
2613 			descriptor->token |= EHCI_QTD_DATA_TOGGLE;
2614 
2615 		if (lastDescriptor)
2616 			LinkDescriptors(lastDescriptor, descriptor, strayDescriptor);
2617 
2618 		bufferSize -= packetSize;
2619 		lastDescriptor = descriptor;
2620 		if (!firstDescriptor)
2621 			firstDescriptor = descriptor;
2622 	}
2623 
2624 	*_firstDescriptor = firstDescriptor;
2625 	*_lastDescriptor = lastDescriptor;
2626 	return B_OK;
2627 }
2628 
2629 
2630 void
2631 EHCI::FreeDescriptor(ehci_qtd *descriptor)
2632 {
2633 	if (!descriptor)
2634 		return;
2635 
2636 	if (descriptor->buffer_log) {
2637 		fStack->FreeChunk(descriptor->buffer_log,
2638 			(phys_addr_t)descriptor->buffer_phy[0], descriptor->buffer_size);
2639 	}
2640 
2641 	fStack->FreeChunk(descriptor, (phys_addr_t)descriptor->this_phy,
2642 		sizeof(ehci_qtd));
2643 }
2644 
2645 
2646 void
2647 EHCI::FreeDescriptorChain(ehci_qtd *topDescriptor)
2648 {
2649 	ehci_qtd *current = topDescriptor;
2650 	ehci_qtd *next = NULL;
2651 
2652 	while (current) {
2653 		next = current->next_log;
2654 		FreeDescriptor(current);
2655 		current = next;
2656 	}
2657 }
2658 
2659 
2660 ehci_itd *
2661 EHCI::CreateItdDescriptor()
2662 {
2663 	ehci_itd *result;
2664 	phys_addr_t physicalAddress;
2665 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
2666 			sizeof(ehci_itd)) != B_OK) {
2667 		TRACE_ERROR("failed to allocate a itd\n");
2668 		return NULL;
2669 	}
2670 
2671 	memset(result, 0, sizeof(ehci_itd));
2672 	result->this_phy = (addr_t)physicalAddress;
2673 	result->next_phy = EHCI_ITEM_TERMINATE;
2674 
2675 	return result;
2676 }
2677 
2678 
2679 ehci_sitd *
2680 EHCI::CreateSitdDescriptor()
2681 {
2682 	ehci_sitd *result;
2683 	phys_addr_t physicalAddress;
2684 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
2685 			sizeof(ehci_sitd)) != B_OK) {
2686 		TRACE_ERROR("failed to allocate a sitd\n");
2687 		return NULL;
2688 	}
2689 
2690 	memset(result, 0, sizeof(ehci_sitd));
2691 	result->this_phy = (addr_t)physicalAddress | EHCI_ITEM_TYPE_SITD;
2692 	result->next_phy = EHCI_ITEM_TERMINATE;
2693 
2694 	return result;
2695 }
2696 
2697 
2698 void
2699 EHCI::FreeDescriptor(ehci_itd *descriptor)
2700 {
2701 	if (!descriptor)
2702 		return;
2703 
2704 	fStack->FreeChunk(descriptor, (phys_addr_t)descriptor->this_phy,
2705 		sizeof(ehci_itd));
2706 }
2707 
2708 
2709 void
2710 EHCI::FreeDescriptor(ehci_sitd *descriptor)
2711 {
2712 	if (!descriptor)
2713 		return;
2714 
2715 	fStack->FreeChunk(descriptor, (phys_addr_t)descriptor->this_phy,
2716 		sizeof(ehci_sitd));
2717 }
2718 
2719 
2720 void
2721 EHCI::LinkDescriptors(ehci_qtd *first, ehci_qtd *last, ehci_qtd *alt)
2722 {
2723 	first->next_phy = last->this_phy;
2724 	first->next_log = last;
2725 
2726 	if (alt) {
2727 		first->alt_next_phy = alt->this_phy;
2728 		first->alt_next_log = alt;
2729 	} else {
2730 		first->alt_next_phy = EHCI_ITEM_TERMINATE;
2731 		first->alt_next_log = NULL;
2732 	}
2733 }
2734 
2735 
2736 void
2737 EHCI::LinkITDescriptors(ehci_itd *itd, ehci_itd **_last)
2738 {
2739 	ehci_itd *last = *_last;
2740 	itd->next_phy = last->next_phy;
2741 	itd->next = NULL;
2742 	itd->prev = last;
2743 	last->next = itd;
2744 	last->next_phy = itd->this_phy;
2745 	*_last = itd;
2746 }
2747 
2748 
2749 void
2750 EHCI::LinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **_last)
2751 {
2752 	ehci_sitd *last = *_last;
2753 	sitd->next_phy = last->next_phy;
2754 	sitd->next = NULL;
2755 	sitd->prev = last;
2756 	last->next = sitd;
2757 	last->next_phy = sitd->this_phy;
2758 	*_last = sitd;
2759 }
2760 
2761 
2762 void
2763 EHCI::UnlinkITDescriptors(ehci_itd *itd, ehci_itd **last)
2764 {
2765 	itd->prev->next_phy = itd->next_phy;
2766 	itd->prev->next = itd->next;
2767 	if (itd->next != NULL)
2768 		itd->next->prev = itd->prev;
2769 	if (itd == *last)
2770 		*last = itd->prev;
2771 }
2772 
2773 
2774 void
2775 EHCI::UnlinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **last)
2776 {
2777 	sitd->prev->next_phy = sitd->next_phy;
2778 	sitd->prev->next = sitd->next;
2779 	if (sitd->next != NULL)
2780 		sitd->next->prev = sitd->prev;
2781 	if (sitd == *last)
2782 		*last = sitd->prev;
2783 }
2784 
2785 
2786 size_t
2787 EHCI::WriteDescriptorChain(ehci_qtd *topDescriptor, generic_io_vec *vector,
2788 	size_t vectorCount, bool physical)
2789 {
2790 	ehci_qtd *current = topDescriptor;
2791 	size_t actualLength = 0;
2792 	size_t vectorIndex = 0;
2793 	size_t vectorOffset = 0;
2794 	size_t bufferOffset = 0;
2795 
2796 	while (current) {
2797 		if (!current->buffer_log)
2798 			break;
2799 
2800 		while (true) {
2801 			size_t length = min_c(current->buffer_size - bufferOffset,
2802 				vector[vectorIndex].length - vectorOffset);
2803 
2804 			status_t status = generic_memcpy(
2805 				(generic_addr_t)current->buffer_log + bufferOffset, false,
2806 				vector[vectorIndex].base + vectorOffset, physical, length);
2807 			ASSERT(status == B_OK);
2808 
2809 			actualLength += length;
2810 			vectorOffset += length;
2811 			bufferOffset += length;
2812 
2813 			if (vectorOffset >= vector[vectorIndex].length) {
2814 				if (++vectorIndex >= vectorCount) {
2815 					TRACE("wrote descriptor chain (%ld bytes, no more vectors)"
2816 						"\n", actualLength);
2817 					return actualLength;
2818 				}
2819 
2820 				vectorOffset = 0;
2821 			}
2822 
2823 			if (bufferOffset >= current->buffer_size) {
2824 				bufferOffset = 0;
2825 				break;
2826 			}
2827 		}
2828 
2829 		if (current->next_phy & EHCI_ITEM_TERMINATE)
2830 			break;
2831 
2832 		current = current->next_log;
2833 	}
2834 
2835 	TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
2836 	return actualLength;
2837 }
2838 
2839 
2840 size_t
2841 EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, generic_io_vec *vector,
2842 	size_t vectorCount, bool physical, bool *nextDataToggle)
2843 {
2844 	uint32 dataToggle = 0;
2845 	ehci_qtd *current = topDescriptor;
2846 	size_t actualLength = 0;
2847 	size_t vectorIndex = 0;
2848 	size_t vectorOffset = 0;
2849 	size_t bufferOffset = 0;
2850 
2851 	while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) {
2852 		if (!current->buffer_log)
2853 			break;
2854 
2855 		dataToggle = current->token & EHCI_QTD_DATA_TOGGLE;
2856 		size_t bufferSize = current->buffer_size;
2857 		bufferSize -= (current->token >> EHCI_QTD_BYTES_SHIFT)
2858 			& EHCI_QTD_BYTES_MASK;
2859 
2860 		while (true) {
2861 			size_t length = min_c(bufferSize - bufferOffset,
2862 				vector[vectorIndex].length - vectorOffset);
2863 
2864 			status_t status = generic_memcpy(
2865 				vector[vectorIndex].base + vectorOffset, physical,
2866 				(generic_addr_t)current->buffer_log + bufferOffset, false, length);
2867 			ASSERT(status == B_OK);
2868 
2869 			actualLength += length;
2870 			vectorOffset += length;
2871 			bufferOffset += length;
2872 
2873 			if (vectorOffset >= vector[vectorIndex].length) {
2874 				if (++vectorIndex >= vectorCount) {
2875 					TRACE("read descriptor chain (%ld bytes, no more vectors)"
2876 						"\n", actualLength);
2877 					*nextDataToggle = dataToggle > 0 ? true : false;
2878 					return actualLength;
2879 				}
2880 
2881 				vectorOffset = 0;
2882 			}
2883 
2884 			if (bufferOffset >= bufferSize) {
2885 				bufferOffset = 0;
2886 				break;
2887 			}
2888 		}
2889 
2890 		if (current->next_phy & EHCI_ITEM_TERMINATE)
2891 			break;
2892 
2893 		current = current->next_log;
2894 	}
2895 
2896 	TRACE("read descriptor chain (%ld bytes)\n", actualLength);
2897 	*nextDataToggle = dataToggle > 0 ? true : false;
2898 	return actualLength;
2899 }
2900 
2901 
2902 size_t
2903 EHCI::ReadActualLength(ehci_qtd *topDescriptor, bool *nextDataToggle)
2904 {
2905 	size_t actualLength = 0;
2906 	ehci_qtd *current = topDescriptor;
2907 	uint32 dataToggle = 0;
2908 
2909 	while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) {
2910 		dataToggle = current->token & EHCI_QTD_DATA_TOGGLE;
2911 		size_t length = current->buffer_size;
2912 		length -= (current->token >> EHCI_QTD_BYTES_SHIFT)
2913 			& EHCI_QTD_BYTES_MASK;
2914 		actualLength += length;
2915 
2916 		if (current->next_phy & EHCI_ITEM_TERMINATE)
2917 			break;
2918 
2919 		current = current->next_log;
2920 	}
2921 
2922 	TRACE("read actual length (%ld bytes)\n", actualLength);
2923 	*nextDataToggle = dataToggle > 0 ? true : false;
2924 	return actualLength;
2925 }
2926 
2927 
2928 size_t
2929 EHCI::WriteIsochronousDescriptorChain(isochronous_transfer_data *transfer)
2930 {
2931 	// TODO implement
2932 	return 0;
2933 }
2934 
2935 
2936 size_t
2937 EHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer)
2938 {
2939 	generic_io_vec *vector = transfer->transfer->Vector();
2940 	size_t vectorCount = transfer->transfer->VectorCount();
2941 	const bool physical = transfer->transfer->IsPhysical();
2942 	size_t vectorOffset = 0;
2943 	size_t vectorIndex = 0;
2944 	usb_isochronous_data *isochronousData
2945 		= transfer->transfer->IsochronousData();
2946 	uint32 packet = 0;
2947 	size_t totalLength = 0;
2948 	size_t bufferOffset = 0;
2949 
2950 	size_t packetSize = transfer->transfer->DataLength();
2951 	packetSize /= isochronousData->packet_count;
2952 
2953 	for (uint32 i = 0; i <= transfer->last_to_process; i++) {
2954 		ehci_itd *itd = transfer->descriptors[i];
2955 		for (uint32 j = 0; j <= itd->last_token
2956 			&& packet < isochronousData->packet_count; j++) {
2957 
2958 			size_t bufferSize = (itd->token[j] >> EHCI_ITD_TLENGTH_SHIFT)
2959 				& EHCI_ITD_TLENGTH_MASK;
2960 			if (((itd->token[j] >> EHCI_ITD_STATUS_SHIFT)
2961 				& EHCI_ITD_STATUS_MASK) != 0) {
2962 				bufferSize = 0;
2963 			}
2964 			isochronousData->packet_descriptors[packet].actual_length
2965 				= bufferSize;
2966 
2967 			if (bufferSize > 0)
2968 				isochronousData->packet_descriptors[packet].status = B_OK;
2969 			else
2970 				isochronousData->packet_descriptors[packet].status = B_ERROR;
2971 
2972 			totalLength += bufferSize;
2973 
2974 			size_t offset = bufferOffset;
2975 			size_t skipSize = packetSize - bufferSize;
2976 			while (bufferSize > 0) {
2977 				size_t length = min_c(bufferSize,
2978 					vector[vectorIndex].length - vectorOffset);
2979 				status_t status = generic_memcpy(
2980 					vector[vectorIndex].base + vectorOffset, physical,
2981 					(generic_addr_t)transfer->buffer_log + bufferOffset, false, length);
2982 				ASSERT(status == B_OK);
2983 
2984 				offset += length;
2985 				vectorOffset += length;
2986 				bufferSize -= length;
2987 
2988 				if (vectorOffset >= vector[vectorIndex].length) {
2989 					if (++vectorIndex >= vectorCount) {
2990 						TRACE("read isodescriptor chain (%ld bytes, no more "
2991 							"vectors)\n", totalLength);
2992 						return totalLength;
2993 					}
2994 
2995 					vectorOffset = 0;
2996 				}
2997 			}
2998 
2999 			// skip to next packet offset
3000 			while (skipSize > 0) {
3001 				size_t length = min_c(skipSize,
3002 					vector[vectorIndex].length - vectorOffset);
3003 				vectorOffset += length;
3004 				skipSize -= length;
3005 				if (vectorOffset >= vector[vectorIndex].length) {
3006 					if (++vectorIndex >= vectorCount) {
3007 						TRACE("read isodescriptor chain (%ld bytes, no more "
3008 							"vectors)\n", totalLength);
3009 						return totalLength;
3010 					}
3011 
3012 					vectorOffset = 0;
3013 				}
3014 			}
3015 
3016 			bufferOffset += packetSize;
3017 			if (bufferOffset >= transfer->buffer_size)
3018 				return totalLength;
3019 
3020 			packet++;
3021 		}
3022 	}
3023 
3024 	TRACE("ReadIsochronousDescriptorChain packet count %" B_PRId32 "\n",
3025 		packet);
3026 
3027 	return totalLength;
3028 }
3029 
3030 
3031 bool
3032 EHCI::LockIsochronous()
3033 {
3034 	return (mutex_lock(&fIsochronousLock) == B_OK);
3035 }
3036 
3037 
3038 void
3039 EHCI::UnlockIsochronous()
3040 {
3041 	mutex_unlock(&fIsochronousLock);
3042 }
3043 
3044 
3045 inline void
3046 EHCI::WriteOpReg(uint32 reg, uint32 value)
3047 {
3048 	*(volatile uint32 *)(fOperationalRegisters + reg) = value;
3049 }
3050 
3051 
3052 inline uint32
3053 EHCI::ReadOpReg(uint32 reg)
3054 {
3055 	return *(volatile uint32 *)(fOperationalRegisters + reg);
3056 }
3057 
3058 
3059 inline uint8
3060 EHCI::ReadCapReg8(uint32 reg)
3061 {
3062 	return *(volatile uint8 *)(fCapabilityRegisters + reg);
3063 }
3064 
3065 
3066 inline uint16
3067 EHCI::ReadCapReg16(uint32 reg)
3068 {
3069 	return *(volatile uint16 *)(fCapabilityRegisters + reg);
3070 }
3071 
3072 
3073 inline uint32
3074 EHCI::ReadCapReg32(uint32 reg)
3075 {
3076 	return *(volatile uint32 *)(fCapabilityRegisters + reg);
3077 }
3078