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