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