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