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