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