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