xref: /haiku/src/add-ons/kernel/busses/usb/ehci.cpp (revision ab4411e89a079bc0a40d901995f3418d998c51b3)
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::SubmitTransfer(Transfer *transfer)
697 {
698 	// short circuit the root hub
699 	if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
700 		return fRootHub->ProcessTransfer(this, transfer);
701 
702 	Pipe *pipe = transfer->TransferPipe();
703 	if ((pipe->Type() & USB_OBJECT_ISO_PIPE) != 0)
704 		return SubmitIsochronous(transfer);
705 
706 	ehci_qh *queueHead = CreateQueueHead();
707 	if (!queueHead) {
708 		TRACE_ERROR("failed to allocate queue head\n");
709 		return B_NO_MEMORY;
710 	}
711 
712 	status_t result = InitQueueHead(queueHead, pipe);
713 	if (result < B_OK) {
714 		TRACE_ERROR("failed to init queue head\n");
715 		FreeQueueHead(queueHead);
716 		return result;
717 	}
718 
719 	bool directionIn;
720 	ehci_qtd *dataDescriptor;
721 	if ((pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0) {
722 		result = FillQueueWithRequest(transfer, queueHead, &dataDescriptor,
723 			&directionIn);
724 	} else {
725 		result = FillQueueWithData(transfer, queueHead, &dataDescriptor,
726 			&directionIn);
727 	}
728 
729 	if (result < B_OK) {
730 		TRACE_ERROR("failed to fill transfer queue with data\n");
731 		FreeQueueHead(queueHead);
732 		return result;
733 	}
734 
735 	result = AddPendingTransfer(transfer, queueHead, dataDescriptor,
736 		directionIn);
737 	if (result < B_OK) {
738 		TRACE_ERROR("failed to add pending transfer\n");
739 		FreeQueueHead(queueHead);
740 		return result;
741 	}
742 
743 #ifdef TRACE_USB
744 	TRACE("linking queue\n");
745 	print_queue(queueHead);
746 #endif
747 
748 	if ((pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) != 0)
749 		result = LinkInterruptQueueHead(queueHead, pipe);
750 	else
751 		result = LinkQueueHead(queueHead);
752 
753 	if (result < B_OK) {
754 		TRACE_ERROR("failed to link queue head\n");
755 		FreeQueueHead(queueHead);
756 		return result;
757 	}
758 
759 	return B_OK;
760 }
761 
762 
763 status_t
764 EHCI::SubmitIsochronous(Transfer *transfer)
765 {
766 	Pipe *pipe = transfer->TransferPipe();
767 	bool directionIn = (pipe->Direction() == Pipe::In);
768 	usb_isochronous_data *isochronousData = transfer->IsochronousData();
769 	size_t packetSize = transfer->DataLength();
770 #ifdef TRACE_USB
771 	size_t restSize = packetSize % isochronousData->packet_count;
772 #endif
773 	packetSize /= isochronousData->packet_count;
774 	uint16 currentFrame;
775 
776 	if (packetSize > pipe->MaxPacketSize()) {
777 		TRACE_ERROR(
778 			"isochronous packetSize is bigger than pipe MaxPacketSize\n");
779 		return B_BAD_VALUE;
780 	}
781 
782 	// Ignore the fact that the last descriptor might need less bandwidth.
783 	// The overhead is not worthy.
784 	uint16 bandwidth = transfer->Bandwidth() / isochronousData->packet_count;
785 
786 	TRACE("isochronous transfer descriptor bandwidth %d\n", bandwidth);
787 
788 	// The following holds the list of transfer descriptor of the
789 	// isochronous request. It is used to quickly remove all the isochronous
790 	// descriptors from the frame list, as descriptors are not link to each
791 	// other in a queue like for every other transfer.
792 	ehci_itd **isoRequest
793 		= new(std::nothrow) ehci_itd *[isochronousData->packet_count];
794 	if (isoRequest == NULL) {
795 		TRACE("failed to create isoRequest array!\n");
796 		return B_NO_MEMORY;
797 	}
798 
799 	TRACE("isochronous submitted size=%" B_PRIuSIZE " bytes, TDs=%" B_PRIu32
800 		", maxPacketSize=%" B_PRIuSIZE ", packetSize=%" B_PRIuSIZE
801 		", restSize=%" B_PRIuSIZE "\n", transfer->DataLength(),
802 		isochronousData->packet_count, pipe->MaxPacketSize(), packetSize,
803 		restSize);
804 
805 	// Find the entry where to start inserting the first Isochronous descriptor
806 	if ((isochronousData->flags & USB_ISO_ASAP) != 0 ||
807 		isochronousData->starting_frame_number == NULL) {
808 
809 		if (fFirstIsochronousTransfer != NULL && fNextStartingFrame != -1)
810 			currentFrame = fNextStartingFrame;
811 		else {
812 			uint32 threshold = fThreshold;
813 			TRACE("threshold: %" B_PRIu32 "\n", threshold);
814 
815 			// find the first available frame with enough bandwidth.
816 			// This should always be the case, as defining the starting frame
817 			// number in the driver makes no sense for many reason, one of which
818 			// is that frame numbers value are host controller specific, and the
819 			// driver does not know which host controller is running.
820 			currentFrame = ((ReadOpReg(EHCI_FRINDEX) + threshold) / 8)
821 				& (EHCI_FRAMELIST_ENTRIES_COUNT - 1);
822 		}
823 
824 		// Make sure that:
825 		// 1. We are at least 5ms ahead the controller
826 		// 2. We stay in the range 0-127
827 		// 3. There is enough bandwidth in the first entry
828 		currentFrame &= EHCI_VFRAMELIST_ENTRIES_COUNT - 1;
829 	} else {
830 		// Find out if the frame number specified has enough bandwidth,
831 		// otherwise find the first next available frame with enough bandwidth
832 		currentFrame = *isochronousData->starting_frame_number;
833 	}
834 
835 	TRACE("isochronous starting frame=%d\n", currentFrame);
836 
837 	uint16 itdIndex = 0;
838 	size_t dataLength = transfer->DataLength();
839 	void* bufferLog;
840 	phys_addr_t bufferPhy;
841 	if (fStack->AllocateChunk(&bufferLog, &bufferPhy, dataLength) < B_OK) {
842 		TRACE_ERROR("unable to allocate itd buffer\n");
843 		delete[] isoRequest;
844 		return B_NO_MEMORY;
845 	}
846 
847 	memset(bufferLog, 0, dataLength);
848 
849 	phys_addr_t currentPhy = bufferPhy;
850 	uint32 frameCount = 0;
851 	while (dataLength > 0) {
852 		ehci_itd* itd = CreateItdDescriptor();
853 		isoRequest[itdIndex++] = itd;
854 		uint16 pg = 0;
855 		itd->buffer_phy[pg] = currentPhy & 0xfffff000;
856 		uint32 offset = currentPhy & 0xfff;
857 		TRACE("isochronous created itd, filling it with phy %" B_PRIxPHYSADDR
858 			"\n", currentPhy);
859 		for (int32 i = 0; i < 8 && dataLength > 0; i++) {
860 			size_t length = min_c(dataLength, packetSize);
861 			itd->token[i] = (EHCI_ITD_STATUS_ACTIVE << EHCI_ITD_STATUS_SHIFT)
862 				| (length << EHCI_ITD_TLENGTH_SHIFT) | (pg << EHCI_ITD_PG_SHIFT)
863 				| (offset << EHCI_ITD_TOFFSET_SHIFT);
864 			itd->last_token = i;
865 			TRACE("isochronous filled slot %" B_PRId32 " 0x%" B_PRIx32 "\n", i,
866 				itd->token[i]);
867 			dataLength -= length;
868 			offset += length;
869 			if (dataLength > 0 && offset > 0xfff) {
870 				offset -= B_PAGE_SIZE;
871 				currentPhy += B_PAGE_SIZE;
872 				itd->buffer_phy[pg + 1] = currentPhy & 0xfffff000;
873 				pg++;
874 			}
875 			if (dataLength <= 0)
876 				itd->token[i] |= EHCI_ITD_IOC;
877 		}
878 
879 		currentPhy += (offset & 0xfff) - (currentPhy & 0xfff);
880 
881 		itd->buffer_phy[0]
882 			|= (pipe->EndpointAddress() << EHCI_ITD_ENDPOINT_SHIFT)
883 				| (pipe->DeviceAddress() << EHCI_ITD_ADDRESS_SHIFT);
884 		itd->buffer_phy[1]
885 			|= (pipe->MaxPacketSize() & EHCI_ITD_MAXPACKETSIZE_MASK)
886 				| (directionIn << EHCI_ITD_DIR_SHIFT);
887 		itd->buffer_phy[2]
888 			|= ((((pipe->MaxPacketSize() >> EHCI_ITD_MAXPACKETSIZE_LENGTH) + 1)
889 				& EHCI_ITD_MUL_MASK) << EHCI_ITD_MUL_SHIFT);
890 
891 		TRACE("isochronous filled itd buffer_phy[0,1,2] 0x%" B_PRIx32 ", 0x%"
892 			B_PRIx32 " 0x%" B_PRIx32 "\n",
893 			itd->buffer_phy[0], itd->buffer_phy[1], itd->buffer_phy[2]);
894 
895 		if (!LockIsochronous())
896 			continue;
897 		LinkITDescriptors(itd, &fItdEntries[currentFrame]);
898 		UnlockIsochronous();
899 		fFrameBandwidth[currentFrame] -= bandwidth;
900 		currentFrame = (currentFrame + 1) & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1);
901 		frameCount++;
902 	}
903 
904 	TRACE("isochronous filled itds count %d\n", itdIndex);
905 
906 	// Add transfer to the list
907 	status_t result = AddPendingIsochronousTransfer(transfer, isoRequest,
908 		itdIndex - 1, directionIn, bufferPhy, bufferLog,
909 		transfer->DataLength());
910 	if (result < B_OK) {
911 		TRACE_ERROR("failed to add pending isochronous transfer\n");
912 		for (uint32 i = 0; i < itdIndex; i++)
913 			FreeDescriptor(isoRequest[i]);
914 		delete[] isoRequest;
915 		return result;
916 	}
917 
918 	TRACE("appended isochronous transfer by starting at frame number %d\n",
919 		currentFrame);
920 	fNextStartingFrame = currentFrame + 1;
921 
922 	// Wake up the isochronous finisher thread
923 	release_sem_etc(fFinishIsochronousTransfersSem, 1 /*frameCount*/,
924 		B_DO_NOT_RESCHEDULE);
925 
926 	return B_OK;
927 }
928 
929 
930 isochronous_transfer_data *
931 EHCI::FindIsochronousTransfer(ehci_itd *itd)
932 {
933 	// Simply check every last descriptor of the isochronous transfer list
934 	isochronous_transfer_data *transfer = fFirstIsochronousTransfer;
935 	if (transfer) {
936 		while (transfer->descriptors[transfer->last_to_process]
937 			!= itd) {
938 			transfer = transfer->link;
939 			if (!transfer)
940 				break;
941 		}
942 	}
943 	return transfer;
944 }
945 
946 
947 status_t
948 EHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
949 {
950 	TRACE("pipe change %d for pipe %p\n", change, pipe);
951 	switch (change) {
952 		case USB_CHANGE_CREATED:
953 		case USB_CHANGE_DESTROYED: {
954 			// ToDo: we should create and keep a single queue head
955 			// for all transfers to/from this pipe
956 			break;
957 		}
958 
959 		case USB_CHANGE_PIPE_POLICY_CHANGED: {
960 			// ToDo: for isochronous pipes we might need to adapt to new
961 			// pipe policy settings here
962 			break;
963 		}
964 	}
965 
966 	return B_OK;
967 }
968 
969 
970 status_t
971 EHCI::AddTo(Stack *stack)
972 {
973 #ifdef TRACE_USB
974 	set_dprintf_enabled(true);
975 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
976 	load_driver_symbols("ehci");
977 #endif
978 #endif
979 
980 	if (!sPCIModule) {
981 		status_t status = get_module(B_PCI_MODULE_NAME,
982 			(module_info **)&sPCIModule);
983 		if (status < B_OK) {
984 			TRACE_MODULE_ERROR("getting pci module failed! 0x%08" B_PRIx32
985 				"\n", status);
986 			return status;
987 		}
988 	}
989 
990 	TRACE_MODULE("searching devices\n");
991 	bool found = false;
992 	pci_info *item = new(std::nothrow) pci_info;
993 	if (!item) {
994 		sPCIModule = NULL;
995 		put_module(B_PCI_MODULE_NAME);
996 		return B_NO_MEMORY;
997 	}
998 
999 	// Try to get the PCI x86 module as well so we can enable possible MSIs.
1000 	if (sPCIx86Module == NULL && get_module(B_PCI_X86_MODULE_NAME,
1001 			(module_info **)&sPCIx86Module) != B_OK) {
1002 		// If it isn't there, that's not critical though.
1003 		TRACE_MODULE_ERROR("failed to get pci x86 module\n");
1004 		sPCIx86Module = NULL;
1005 	}
1006 
1007 	for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
1008 		if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
1009 			&& item->class_api == PCI_usb_ehci) {
1010 			if (item->u.h0.interrupt_line == 0
1011 				|| item->u.h0.interrupt_line == 0xFF) {
1012 				TRACE_MODULE_ERROR("found device with invalid IRQ - "
1013 					"check IRQ assignement\n");
1014 				continue;
1015 			}
1016 
1017 			TRACE_MODULE("found device at IRQ %u\n", item->u.h0.interrupt_line);
1018 			EHCI *bus = new(std::nothrow) EHCI(item, stack);
1019 			if (!bus) {
1020 				delete item;
1021 				sPCIModule = NULL;
1022 				put_module(B_PCI_MODULE_NAME);
1023 				if (sPCIx86Module != NULL) {
1024 					sPCIx86Module = NULL;
1025 					put_module(B_PCI_X86_MODULE_NAME);
1026 				}
1027 				return B_NO_MEMORY;
1028 			}
1029 
1030 			if (bus->InitCheck() < B_OK) {
1031 				TRACE_MODULE_ERROR("bus failed init check\n");
1032 				delete bus;
1033 				continue;
1034 			}
1035 
1036 			// the bus took it away
1037 			item = new(std::nothrow) pci_info;
1038 
1039 			bus->Start();
1040 			stack->AddBusManager(bus);
1041 			found = true;
1042 		}
1043 	}
1044 
1045 	if (!found) {
1046 		TRACE_MODULE_ERROR("no devices found\n");
1047 		delete item;
1048 		sPCIModule = NULL;
1049 		put_module(B_PCI_MODULE_NAME);
1050 		if (sPCIx86Module != NULL) {
1051 			sPCIx86Module = NULL;
1052 			put_module(B_PCI_X86_MODULE_NAME);
1053 		}
1054 		return ENODEV;
1055 	}
1056 
1057 	delete item;
1058 	return B_OK;
1059 }
1060 
1061 
1062 status_t
1063 EHCI::GetPortStatus(uint8 index, usb_port_status *status)
1064 {
1065 	if (index >= fPortCount)
1066 		return B_BAD_INDEX;
1067 
1068 	status->status = status->change = 0;
1069 	uint32 portStatus = ReadOpReg(EHCI_PORTSC + index * sizeof(uint32));
1070 
1071 	// build the status
1072 	if (portStatus & EHCI_PORTSC_CONNSTATUS)
1073 		status->status |= PORT_STATUS_CONNECTION;
1074 	if (portStatus & EHCI_PORTSC_ENABLE)
1075 		status->status |= PORT_STATUS_ENABLE;
1076 	if (portStatus & EHCI_PORTSC_ENABLE)
1077 		status->status |= PORT_STATUS_HIGH_SPEED;
1078 	if (portStatus & EHCI_PORTSC_OCACTIVE)
1079 		status->status |= PORT_STATUS_OVER_CURRENT;
1080 	if (portStatus & EHCI_PORTSC_PORTRESET)
1081 		status->status |= PORT_STATUS_RESET;
1082 	if (portStatus & EHCI_PORTSC_PORTPOWER)
1083 		status->status |= PORT_STATUS_POWER;
1084 	if (portStatus & EHCI_PORTSC_SUSPEND)
1085 		status->status |= PORT_STATUS_SUSPEND;
1086 	if (portStatus & EHCI_PORTSC_DMINUS)
1087 		status->status |= PORT_STATUS_LOW_SPEED;
1088 
1089 	// build the change
1090 	if (portStatus & EHCI_PORTSC_CONNCHANGE)
1091 		status->change |= PORT_STATUS_CONNECTION;
1092 	if (portStatus & EHCI_PORTSC_ENABLECHANGE)
1093 		status->change |= PORT_STATUS_ENABLE;
1094 	if (portStatus & EHCI_PORTSC_OCCHANGE)
1095 		status->change |= PORT_STATUS_OVER_CURRENT;
1096 
1097 	// there are no bits to indicate suspend and reset change
1098 	if (fPortResetChange & (1 << index))
1099 		status->change |= PORT_STATUS_RESET;
1100 	if (fPortSuspendChange & (1 << index))
1101 		status->change |= PORT_STATUS_SUSPEND;
1102 
1103 	return B_OK;
1104 }
1105 
1106 
1107 status_t
1108 EHCI::SetPortFeature(uint8 index, uint16 feature)
1109 {
1110 	if (index >= fPortCount)
1111 		return B_BAD_INDEX;
1112 
1113 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
1114 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1115 
1116 	switch (feature) {
1117 		case PORT_SUSPEND:
1118 			return SuspendPort(index);
1119 
1120 		case PORT_RESET:
1121 			return ResetPort(index);
1122 
1123 		case PORT_POWER:
1124 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTPOWER);
1125 			return B_OK;
1126 	}
1127 
1128 	return B_BAD_VALUE;
1129 }
1130 
1131 
1132 status_t
1133 EHCI::ClearPortFeature(uint8 index, uint16 feature)
1134 {
1135 	if (index >= fPortCount)
1136 		return B_BAD_INDEX;
1137 
1138 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
1139 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1140 
1141 	switch (feature) {
1142 		case PORT_ENABLE:
1143 			WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_ENABLE);
1144 			return B_OK;
1145 
1146 		case PORT_POWER:
1147 			WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTPOWER);
1148 			return B_OK;
1149 
1150 		case C_PORT_CONNECTION:
1151 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_CONNCHANGE);
1152 			return B_OK;
1153 
1154 		case C_PORT_ENABLE:
1155 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_ENABLECHANGE);
1156 			return B_OK;
1157 
1158 		case C_PORT_OVER_CURRENT:
1159 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_OCCHANGE);
1160 			return B_OK;
1161 
1162 		case C_PORT_RESET:
1163 			fPortResetChange &= ~(1 << index);
1164 			return B_OK;
1165 
1166 		case C_PORT_SUSPEND:
1167 			fPortSuspendChange &= ~(1 << index);
1168 			return B_OK;
1169 	}
1170 
1171 	return B_BAD_VALUE;
1172 }
1173 
1174 
1175 status_t
1176 EHCI::ResetPort(uint8 index)
1177 {
1178 	TRACE("reset port %d\n", index);
1179 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
1180 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1181 
1182 	if (portStatus & EHCI_PORTSC_DMINUS) {
1183 		TRACE_ALWAYS("lowspeed device connected, giving up port ownership\n");
1184 		// there is a lowspeed device connected.
1185 		// we give the ownership to a companion controller.
1186 		WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER);
1187 		fPortResetChange |= (1 << index);
1188 		return B_OK;
1189 	}
1190 
1191 	// enable reset signaling
1192 	WriteOpReg(portRegister, (portStatus & ~EHCI_PORTSC_ENABLE)
1193 		| EHCI_PORTSC_PORTRESET);
1194 	snooze(50000);
1195 
1196 	// disable reset signaling
1197 	portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1198 	WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTRESET);
1199 	snooze(2000);
1200 
1201 	portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1202 	if (portStatus & EHCI_PORTSC_PORTRESET) {
1203 		TRACE_ERROR("port reset won't complete\n");
1204 		return B_ERROR;
1205 	}
1206 
1207 	if ((portStatus & EHCI_PORTSC_ENABLE) == 0) {
1208 		TRACE_ALWAYS("fullspeed device connected, giving up port ownership\n");
1209 		// the port was not enabled, this means that no high speed device is
1210 		// attached to this port. we give up ownership to a companion controler
1211 		WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER);
1212 	}
1213 
1214 	fPortResetChange |= (1 << index);
1215 	return B_OK;
1216 }
1217 
1218 
1219 status_t
1220 EHCI::SuspendPort(uint8 index)
1221 {
1222 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
1223 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
1224 	WriteOpReg(portRegister, portStatus | EHCI_PORTSC_SUSPEND);
1225 	fPortSuspendChange |= (1 << index);
1226 	return B_OK;
1227 }
1228 
1229 
1230 status_t
1231 EHCI::ControllerReset()
1232 {
1233 	// halt the controller first
1234 	WriteOpReg(EHCI_USBCMD, 0);
1235 	snooze(10000);
1236 
1237 	// then reset it
1238 	WriteOpReg(EHCI_USBCMD, EHCI_USBCMD_HCRESET);
1239 
1240 	int32 tries = 5;
1241 	while (ReadOpReg(EHCI_USBCMD) & EHCI_USBCMD_HCRESET) {
1242 		snooze(10000);
1243 		if (tries-- < 0)
1244 			return B_ERROR;
1245 	}
1246 
1247 	return B_OK;
1248 }
1249 
1250 
1251 status_t
1252 EHCI::LightReset()
1253 {
1254 	return B_ERROR;
1255 }
1256 
1257 
1258 int32
1259 EHCI::InterruptHandler(void *data)
1260 {
1261 	return ((EHCI *)data)->Interrupt();
1262 }
1263 
1264 
1265 int32
1266 EHCI::Interrupt()
1267 {
1268 	static spinlock lock = B_SPINLOCK_INITIALIZER;
1269 	acquire_spinlock(&lock);
1270 
1271 	// check if any interrupt was generated
1272 	uint32 status = ReadOpReg(EHCI_USBSTS) & EHCI_USBSTS_INTMASK;
1273 	if ((status & fEnabledInterrupts) == 0) {
1274 		if (status != 0) {
1275 			TRACE("discarding not enabled interrupts 0x%08" B_PRIx32 "\n",
1276 				status);
1277 			WriteOpReg(EHCI_USBSTS, status);
1278 		}
1279 
1280 		release_spinlock(&lock);
1281 		return B_UNHANDLED_INTERRUPT;
1282 	}
1283 
1284 	bool asyncAdvance = false;
1285 	bool finishTransfers = false;
1286 	int32 result = B_HANDLED_INTERRUPT;
1287 
1288 	if (status & EHCI_USBSTS_USBINT) {
1289 		TRACE("transfer finished\n");
1290 		result = B_INVOKE_SCHEDULER;
1291 		finishTransfers = true;
1292 	}
1293 
1294 	if (status & EHCI_USBSTS_USBERRINT) {
1295 		TRACE("transfer error\n");
1296 		result = B_INVOKE_SCHEDULER;
1297 		finishTransfers = true;
1298 	}
1299 
1300 	if (status & EHCI_USBSTS_FLROLLOVER)
1301 		TRACE("frame list rollover\n");
1302 
1303 	if (status & EHCI_USBSTS_PORTCHANGE)
1304 		TRACE("port change detected\n");
1305 
1306 	if (status & EHCI_USBSTS_INTONAA) {
1307 		TRACE("interrupt on async advance\n");
1308 		asyncAdvance = true;
1309 		result = B_INVOKE_SCHEDULER;
1310 	}
1311 
1312 	if (status & EHCI_USBSTS_HOSTSYSERR)
1313 		TRACE_ERROR("host system error!\n");
1314 
1315 	WriteOpReg(EHCI_USBSTS, status);
1316 	release_spinlock(&lock);
1317 
1318 	if (asyncAdvance)
1319 		release_sem_etc(fAsyncAdvanceSem, 1, B_DO_NOT_RESCHEDULE);
1320 	if (finishTransfers)
1321 		release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
1322 
1323 	return result;
1324 }
1325 
1326 
1327 int32
1328 EHCI::InterruptPollThread(void *data)
1329 {
1330 	EHCI *ehci = (EHCI *)data;
1331 
1332 	while (!ehci->fStopThreads) {
1333 		// TODO: this could be handled much better by only polling when there
1334 		// are actual transfers going on...
1335 		snooze(1000);
1336 
1337 		cpu_status status = disable_interrupts();
1338 		ehci->Interrupt();
1339 		restore_interrupts(status);
1340 	}
1341 
1342 	return 0;
1343 }
1344 
1345 
1346 status_t
1347 EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead,
1348 	ehci_qtd *dataDescriptor, bool directionIn)
1349 {
1350 	transfer_data *data = new(std::nothrow) transfer_data;
1351 	if (!data)
1352 		return B_NO_MEMORY;
1353 
1354 	status_t result = transfer->InitKernelAccess();
1355 	if (result < B_OK) {
1356 		delete data;
1357 		return result;
1358 	}
1359 
1360 	data->transfer = transfer;
1361 	data->queue_head = queueHead;
1362 	data->data_descriptor = dataDescriptor;
1363 	data->incoming = directionIn;
1364 	data->canceled = false;
1365 	data->link = NULL;
1366 
1367 	if (!Lock()) {
1368 		delete data;
1369 		return B_ERROR;
1370 	}
1371 
1372 	if (fLastTransfer)
1373 		fLastTransfer->link = data;
1374 	else
1375 		fFirstTransfer = data;
1376 
1377 	fLastTransfer = data;
1378 	Unlock();
1379 
1380 	return B_OK;
1381 }
1382 
1383 
1384 status_t
1385 EHCI::AddPendingIsochronousTransfer(Transfer *transfer, ehci_itd **isoRequest,
1386 	uint32 lastIndex, bool directionIn, addr_t bufferPhy, void* bufferLog,
1387 	size_t bufferSize)
1388 {
1389 	if (!transfer || !isoRequest)
1390 		return B_BAD_VALUE;
1391 
1392 	isochronous_transfer_data *data
1393 		= new(std::nothrow) isochronous_transfer_data;
1394 	if (!data)
1395 		return B_NO_MEMORY;
1396 
1397 	status_t result = transfer->InitKernelAccess();
1398 	if (result < B_OK) {
1399 		delete data;
1400 		return result;
1401 	}
1402 
1403 	data->transfer = transfer;
1404 	data->descriptors = isoRequest;
1405 	data->last_to_process = lastIndex;
1406 	data->incoming = directionIn;
1407 	data->is_active = true;
1408 	data->link = NULL;
1409 	data->buffer_phy = bufferPhy;
1410 	data->buffer_log = bufferLog;
1411 	data->buffer_size = bufferSize;
1412 
1413 	// Put in the isochronous transfer list
1414 	if (!LockIsochronous()) {
1415 		delete data;
1416 		return B_ERROR;
1417 	}
1418 
1419 	if (fLastIsochronousTransfer)
1420 		fLastIsochronousTransfer->link = data;
1421 	else if (!fFirstIsochronousTransfer)
1422 		fFirstIsochronousTransfer = data;
1423 
1424 	fLastIsochronousTransfer = data;
1425 	UnlockIsochronous();
1426 	return B_OK;
1427 }
1428 
1429 
1430 status_t
1431 EHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
1432 {
1433 	if ((pipe->Type() & USB_OBJECT_ISO_PIPE) != 0)
1434 		return CancelQueuedIsochronousTransfers(pipe, force);
1435 
1436 	if (!Lock())
1437 		return B_ERROR;
1438 
1439 	struct transfer_entry {
1440 		Transfer *			transfer;
1441 		transfer_entry *	next;
1442 	};
1443 
1444 	transfer_entry *list = NULL;
1445 	transfer_data *current = fFirstTransfer;
1446 	while (current) {
1447 		if (current->transfer && current->transfer->TransferPipe() == pipe) {
1448 			// clear the active bit so the descriptors are canceled
1449 			ehci_qtd *descriptor = current->queue_head->element_log;
1450 			while (descriptor) {
1451 				descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE;
1452 				descriptor = descriptor->next_log;
1453 			}
1454 
1455 			if (!force) {
1456 				// if the transfer is canceled by force, the one causing the
1457 				// cancel is probably not the one who initiated the transfer
1458 				// and the callback is likely not safe anymore
1459 				transfer_entry *entry
1460 					= (transfer_entry *)malloc(sizeof(transfer_entry));
1461 				if (entry != NULL) {
1462 					entry->transfer = current->transfer;
1463 					current->transfer = NULL;
1464 					entry->next = list;
1465 					list = entry;
1466 				}
1467 			}
1468 
1469 			current->canceled = true;
1470 		}
1471 
1472 		current = current->link;
1473 	}
1474 
1475 	Unlock();
1476 
1477 	while (list != NULL) {
1478 		transfer_entry *next = list->next;
1479 		list->transfer->Finished(B_CANCELED, 0);
1480 		delete list->transfer;
1481 		free(list);
1482 		list = next;
1483 	}
1484 
1485 	// wait for any transfers that might have made it before canceling
1486 	while (fProcessingPipe == pipe)
1487 		snooze(1000);
1488 
1489 	// notify the finisher so it can clean up the canceled transfers
1490 	release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
1491 	return B_OK;
1492 }
1493 
1494 
1495 status_t
1496 EHCI::CancelQueuedIsochronousTransfers(Pipe *pipe, bool force)
1497 {
1498 	isochronous_transfer_data *current = fFirstIsochronousTransfer;
1499 
1500 	while (current) {
1501 		if (current->transfer->TransferPipe() == pipe) {
1502 			// TODO implement
1503 
1504 			// TODO: Use the force paramater in order to avoid calling
1505 			// invalid callbacks
1506 			current->is_active = false;
1507 		}
1508 
1509 		current = current->link;
1510 	}
1511 
1512 	TRACE_ERROR("no isochronous transfer found!\n");
1513 	return B_ERROR;
1514 }
1515 
1516 
1517 status_t
1518 EHCI::CancelAllPendingTransfers()
1519 {
1520 	if (!Lock())
1521 		return B_ERROR;
1522 
1523 	transfer_data *transfer = fFirstTransfer;
1524 	while (transfer) {
1525 		transfer->transfer->Finished(B_CANCELED, 0);
1526 		delete transfer->transfer;
1527 
1528 		transfer_data *next = transfer->link;
1529 		delete transfer;
1530 		transfer = next;
1531 	}
1532 
1533 	fFirstTransfer = NULL;
1534 	fLastTransfer = NULL;
1535 	Unlock();
1536 	return B_OK;
1537 }
1538 
1539 
1540 int32
1541 EHCI::FinishThread(void *data)
1542 {
1543 	((EHCI *)data)->FinishTransfers();
1544 	return B_OK;
1545 }
1546 
1547 
1548 void
1549 EHCI::FinishTransfers()
1550 {
1551 	while (!fStopThreads) {
1552 		if (acquire_sem(fFinishTransfersSem) < B_OK)
1553 			continue;
1554 
1555 		// eat up sems that have been released by multiple interrupts
1556 		int32 semCount = 0;
1557 		get_sem_count(fFinishTransfersSem, &semCount);
1558 		if (semCount > 0) {
1559 			acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT,
1560 				0);
1561 		}
1562 
1563 		if (!Lock())
1564 			continue;
1565 
1566 		TRACE("finishing transfers\n");
1567 		transfer_data *lastTransfer = NULL;
1568 		transfer_data *transfer = fFirstTransfer;
1569 		Unlock();
1570 
1571 		while (transfer) {
1572 			bool transferDone = false;
1573 			ehci_qtd *descriptor = transfer->queue_head->element_log;
1574 			status_t callbackStatus = B_OK;
1575 
1576 			while (descriptor) {
1577 				uint32 status = descriptor->token;
1578 				if (status & EHCI_QTD_STATUS_ACTIVE) {
1579 					// still in progress
1580 					TRACE("qtd (0x%08" B_PRIx32 ") still active\n",
1581 						descriptor->this_phy);
1582 					break;
1583 				}
1584 
1585 				if (status & EHCI_QTD_STATUS_ERRMASK) {
1586 					// a transfer error occured
1587 					TRACE_ERROR("qtd (0x%" B_PRIx32 ") error: 0x%08" B_PRIx32
1588 						"\n", descriptor->this_phy, status);
1589 
1590 					uint8 errorCount = status >> EHCI_QTD_ERRCOUNT_SHIFT;
1591 					errorCount &= EHCI_QTD_ERRCOUNT_MASK;
1592 					if (errorCount == 0) {
1593 						// the error counter counted down to zero, report why
1594 						int32 reasons = 0;
1595 						if (status & EHCI_QTD_STATUS_BUFFER) {
1596 							callbackStatus = transfer->incoming
1597 								? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN;
1598 							reasons++;
1599 						}
1600 						if (status & EHCI_QTD_STATUS_TERROR) {
1601 							callbackStatus = B_DEV_CRC_ERROR;
1602 							reasons++;
1603 						}
1604 						if ((transfer->queue_head->endpoint_chars
1605 								& EHCI_QH_CHARS_EPS_HIGH) == 0) {
1606 							// For full-/lowspeed endpoints the unused ping
1607 							// state bit is used as another error bit, it is
1608 							// unspecific however.
1609 							if ((status & EHCI_QTD_STATUS_LS_ERR) != 0) {
1610 								callbackStatus = B_DEV_STALLED;
1611 								reasons++;
1612 							}
1613 						}
1614 
1615 						if (reasons > 1)
1616 							callbackStatus = B_DEV_MULTIPLE_ERRORS;
1617 						else if (reasons == 0) {
1618 							TRACE_ERROR("error counter counted down to zero "
1619 								"but none of the error bits are set\n");
1620 							callbackStatus = B_DEV_STALLED;
1621 						}
1622 					} else if (status & EHCI_QTD_STATUS_BABBLE) {
1623 						// there is a babble condition
1624 						callbackStatus = transfer->incoming
1625 							? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN;
1626 					} else {
1627 						// if the error counter didn't count down to zero
1628 						// and there was no babble, then this halt was caused
1629 						// by a stall handshake
1630 						callbackStatus = B_DEV_STALLED;
1631 					}
1632 
1633 					transferDone = true;
1634 					break;
1635 				}
1636 
1637 				if (descriptor->next_phy & EHCI_ITEM_TERMINATE) {
1638 					// we arrived at the last (stray) descriptor, we're done
1639 					TRACE("qtd (0x%08" B_PRIx32 ") done\n",
1640 						descriptor->this_phy);
1641 					callbackStatus = B_OK;
1642 					transferDone = true;
1643 					break;
1644 				}
1645 
1646 				if (((status >> EHCI_QTD_PID_SHIFT) & EHCI_QTD_PID_MASK)
1647 						== EHCI_QTD_PID_IN
1648 					&& ((status >> EHCI_QTD_BYTES_SHIFT) & EHCI_QTD_BYTES_MASK)
1649 						!=0) {
1650 					// a short packet condition existed on this descriptor
1651 					if ((transfer->transfer->TransferPipe()->Type()
1652 						& USB_OBJECT_CONTROL_PIPE) != 0) {
1653 						// for control pipes, the next descriptor
1654 						// executed is the Status descriptor
1655 						while (!(descriptor->next_phy & EHCI_ITEM_TERMINATE)) {
1656 							descriptor = descriptor->next_log;
1657 						}
1658 						continue;
1659 					}
1660 					// for bulk/interrupt pipes, no other descriptors are
1661 					// executed
1662 					transferDone = true;
1663 					break;
1664 				}
1665 
1666 				descriptor = descriptor->next_log;
1667 			}
1668 
1669 			if (!transferDone) {
1670 				lastTransfer = transfer;
1671 				transfer = transfer->link;
1672 				continue;
1673 			}
1674 
1675 			// remove the transfer from the list first so we are sure
1676 			// it doesn't get canceled while we still process it
1677 			transfer_data *next = transfer->link;
1678 			if (Lock()) {
1679 				if (lastTransfer)
1680 					lastTransfer->link = transfer->link;
1681 
1682 				if (transfer == fFirstTransfer)
1683 					fFirstTransfer = transfer->link;
1684 				if (transfer == fLastTransfer)
1685 					fLastTransfer = lastTransfer;
1686 
1687 				// store the currently processing pipe here so we can wait
1688 				// in cancel if we are processing something on the target pipe
1689 				if (!transfer->canceled)
1690 					fProcessingPipe = transfer->transfer->TransferPipe();
1691 
1692 				transfer->link = NULL;
1693 				Unlock();
1694 			}
1695 
1696 			// if canceled the callback has already been called
1697 			if (!transfer->canceled) {
1698 				size_t actualLength = 0;
1699 
1700 				if (callbackStatus == B_OK) {
1701 					bool nextDataToggle = false;
1702 					if (transfer->data_descriptor && transfer->incoming) {
1703 						// data to read out
1704 						iovec *vector = transfer->transfer->Vector();
1705 						size_t vectorCount = transfer->transfer->VectorCount();
1706 						transfer->transfer->PrepareKernelAccess();
1707 						actualLength = ReadDescriptorChain(
1708 							transfer->data_descriptor,
1709 							vector, vectorCount,
1710 							&nextDataToggle);
1711 					} else if (transfer->data_descriptor) {
1712 						// calculate transfered length
1713 						actualLength = ReadActualLength(
1714 							transfer->data_descriptor, &nextDataToggle);
1715 					}
1716 
1717 					transfer->transfer->TransferPipe()->SetDataToggle(
1718 						nextDataToggle);
1719 
1720 					if (transfer->transfer->IsFragmented()) {
1721 						// this transfer may still have data left
1722 						transfer->transfer->AdvanceByFragment(actualLength);
1723 						if (transfer->transfer->VectorLength() > 0) {
1724 							FreeDescriptorChain(transfer->data_descriptor);
1725 							transfer->transfer->PrepareKernelAccess();
1726 							status_t result = FillQueueWithData(
1727 								transfer->transfer,
1728 								transfer->queue_head,
1729 								&transfer->data_descriptor, NULL);
1730 
1731 							if (result == B_OK && Lock()) {
1732 								// reappend the transfer
1733 								if (fLastTransfer)
1734 									fLastTransfer->link = transfer;
1735 								if (!fFirstTransfer)
1736 									fFirstTransfer = transfer;
1737 
1738 								fLastTransfer = transfer;
1739 								Unlock();
1740 
1741 								transfer = next;
1742 								continue;
1743 							}
1744 						}
1745 
1746 						// the transfer is done, but we already set the
1747 						// actualLength with AdvanceByFragment()
1748 						actualLength = 0;
1749 					}
1750 				}
1751 
1752 				transfer->transfer->Finished(callbackStatus, actualLength);
1753 				fProcessingPipe = NULL;
1754 			}
1755 
1756 			// unlink hardware queue and delete the transfer
1757 			UnlinkQueueHead(transfer->queue_head, &fFreeListHead);
1758 			delete transfer->transfer;
1759 			delete transfer;
1760 			transfer = next;
1761 			release_sem(fCleanupSem);
1762 		}
1763 	}
1764 }
1765 
1766 
1767 int32
1768 EHCI::CleanupThread(void *data)
1769 {
1770 	((EHCI *)data)->Cleanup();
1771 	return B_OK;
1772 }
1773 
1774 
1775 void
1776 EHCI::Cleanup()
1777 {
1778 	ehci_qh *lastFreeListHead = NULL;
1779 
1780 	while (!fStopThreads) {
1781 		if (acquire_sem(fCleanupSem) < B_OK)
1782 			continue;
1783 
1784 		ehci_qh *freeListHead = fFreeListHead;
1785 		if (freeListHead == lastFreeListHead)
1786 			continue;
1787 
1788 		// set the doorbell and wait for the host controller to notify us
1789 		WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_INTONAAD);
1790 		if (acquire_sem(fAsyncAdvanceSem) < B_OK)
1791 			continue;
1792 
1793 		ehci_qh *current = freeListHead;
1794 		while (current != lastFreeListHead) {
1795 			ehci_qh *next = current->next_log;
1796 			FreeQueueHead(current);
1797 			current = next;
1798 		}
1799 
1800 		lastFreeListHead = freeListHead;
1801 	}
1802 }
1803 
1804 
1805 int32
1806 EHCI::FinishIsochronousThread(void *data)
1807 {
1808 	((EHCI *)data)->FinishIsochronousTransfers();
1809 	return B_OK;
1810 }
1811 
1812 
1813 void
1814 EHCI::FinishIsochronousTransfers()
1815 {
1816 	/* This thread stays one position behind the controller and processes every
1817 	* isochronous descriptor. Once it finds the last isochronous descriptor
1818 	* of a transfer, it processes the entire transfer.
1819 	*/
1820 	while (!fStopThreads) {
1821 		// Go to sleep if there are not isochronous transfer to process
1822 		if (acquire_sem(fFinishIsochronousTransfersSem) < B_OK)
1823 			return;
1824 
1825 		bool transferDone = false;
1826 
1827 		uint32 frame = (ReadOpReg(EHCI_FRINDEX) / 8 )
1828 			& (EHCI_FRAMELIST_ENTRIES_COUNT - 1);
1829 		uint32 currentFrame = (frame + EHCI_VFRAMELIST_ENTRIES_COUNT - 5)
1830 			& (EHCI_VFRAMELIST_ENTRIES_COUNT - 1);
1831 		uint32 loop = 0;
1832 
1833 		// Process the frame list until one transfer is processed
1834 		while (!transferDone && loop++ < EHCI_VFRAMELIST_ENTRIES_COUNT) {
1835 			// wait 1ms in order to be sure to be one position behind
1836 			// the controller
1837 			while (currentFrame == (((ReadOpReg(EHCI_FRINDEX) / 8)
1838 				& (EHCI_VFRAMELIST_ENTRIES_COUNT - 1)))) {
1839 				snooze(1000);
1840 			}
1841 
1842 			ehci_itd *itd = fItdEntries[currentFrame];
1843 
1844 			TRACE("FinishIsochronousTransfers itd %p phy 0x%" B_PRIx32
1845 				" prev (%p/0x%" B_PRIx32 ") at frame %" B_PRId32 "\n", itd,
1846 				itd->this_phy, itd->prev, itd->prev != NULL
1847 					? itd->prev->this_phy : 0, currentFrame);
1848 
1849 			if (!LockIsochronous())
1850 				continue;
1851 
1852 			// Process the frame till it has isochronous descriptors in it.
1853 			while (!(itd->next_phy & EHCI_ITEM_TERMINATE) && itd->prev != NULL) {
1854 				TRACE("FinishIsochronousTransfers checking itd %p last_token"
1855 					" %" B_PRId32 "\n", itd, itd->last_token);
1856 				TRACE("FinishIsochronousTransfers tokens 0x%" B_PRIx32 " 0x%"
1857 					B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32
1858 					" 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32 "\n",
1859 					itd->token[0], itd->token[1], itd->token[2], itd->token[3],
1860 					itd->token[4], itd->token[5], itd->token[6], itd->token[7]);
1861 				if (((itd->token[itd->last_token] >> EHCI_ITD_STATUS_SHIFT)
1862 					& EHCI_ITD_STATUS_ACTIVE) == EHCI_ITD_STATUS_ACTIVE) {
1863 					TRACE("FinishIsochronousTransfers unprocessed active itd\n");
1864 				}
1865 				UnlinkITDescriptors(itd, &fItdEntries[currentFrame]);
1866 
1867 				// Process the transfer if we found the last descriptor
1868 				isochronous_transfer_data *transfer
1869 					= FindIsochronousTransfer(itd);
1870 					// Process the descriptors only if it is still active and
1871 					// belongs to an inbound transfer. If the transfer is not
1872 					// active, it means the request has been removed, so simply
1873 					// remove the descriptors.
1874 				if (transfer && transfer->is_active) {
1875 					TRACE("FinishIsochronousTransfers active transfer\n");
1876 					size_t actualLength = 0;
1877 					if (((itd->buffer_phy[1] >> EHCI_ITD_DIR_SHIFT) & 1) != 0) {
1878 						transfer->transfer->PrepareKernelAccess();
1879 						actualLength = ReadIsochronousDescriptorChain(transfer);
1880 					}
1881 
1882 					// Remove the transfer
1883 					if (transfer == fFirstIsochronousTransfer) {
1884 						fFirstIsochronousTransfer = transfer->link;
1885 						if (transfer == fLastIsochronousTransfer)
1886 							fLastIsochronousTransfer = NULL;
1887 					} else {
1888 						isochronous_transfer_data *temp
1889 							= fFirstIsochronousTransfer;
1890 						while (temp != NULL && transfer != temp->link)
1891 							temp = temp->link;
1892 
1893 						if (transfer == fLastIsochronousTransfer)
1894 							fLastIsochronousTransfer = temp;
1895 						if (temp != NULL && temp->link != NULL)
1896 							temp->link = temp->link->link;
1897 					}
1898 					transfer->link = NULL;
1899 
1900 					transfer->transfer->Finished(B_OK, actualLength);
1901 
1902 					itd = itd->prev;
1903 
1904 					for (uint32 i = 0; i <= transfer->last_to_process; i++)
1905 						FreeDescriptor(transfer->descriptors[i]);
1906 
1907 					TRACE("FinishIsochronousTransfers descriptors freed\n");
1908 
1909 					delete [] transfer->descriptors;
1910 					delete transfer->transfer;
1911 					fStack->FreeChunk(transfer->buffer_log,
1912 						(phys_addr_t)transfer->buffer_phy,
1913 						transfer->buffer_size);
1914 					delete transfer;
1915 					transferDone = true;
1916 				} else {
1917 					TRACE("FinishIsochronousTransfers not end of transfer\n");
1918 					itd = itd->prev;
1919 				}
1920 			}
1921 
1922 			UnlockIsochronous();
1923 
1924 			TRACE("FinishIsochronousTransfers next frame\n");
1925 
1926 			// Make sure to reset the frame bandwidth
1927 			fFrameBandwidth[currentFrame] = MAX_AVAILABLE_BANDWIDTH;
1928 			currentFrame = (currentFrame + 1) % EHCI_VFRAMELIST_ENTRIES_COUNT;
1929 		}
1930 	}
1931 }
1932 
1933 
1934 ehci_qh *
1935 EHCI::CreateQueueHead()
1936 {
1937 	ehci_qh *result;
1938 	phys_addr_t physicalAddress;
1939 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
1940 		sizeof(ehci_qh)) < B_OK) {
1941 		TRACE_ERROR("failed to allocate queue head\n");
1942 		return NULL;
1943 	}
1944 
1945 	result->this_phy = (addr_t)physicalAddress | EHCI_ITEM_TYPE_QH;
1946 	result->next_phy = EHCI_ITEM_TERMINATE;
1947 	result->next_log = NULL;
1948 	result->prev_log = NULL;
1949 
1950 	ehci_qtd *descriptor = CreateDescriptor(0, 0);
1951 	if (!descriptor) {
1952 		TRACE_ERROR("failed to allocate initial qtd for queue head\n");
1953 		fStack->FreeChunk(result, physicalAddress, sizeof(ehci_qh));
1954 		return NULL;
1955 	}
1956 
1957 	descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE;
1958 	result->stray_log = descriptor;
1959 	result->element_log = descriptor;
1960 	result->current_qtd_phy = EHCI_ITEM_TERMINATE;
1961 	result->overlay.next_phy = descriptor->this_phy;
1962 	result->overlay.alt_next_phy = EHCI_ITEM_TERMINATE;
1963 	result->overlay.token = 0;
1964 	for (int32 i = 0; i < 5; i++) {
1965 		result->overlay.buffer_phy[i] = 0;
1966 		result->overlay.ext_buffer_phy[i] = 0;
1967 	}
1968 
1969 	return result;
1970 }
1971 
1972 
1973 status_t
1974 EHCI::InitQueueHead(ehci_qh *queueHead, Pipe *pipe)
1975 {
1976 	switch (pipe->Speed()) {
1977 		case USB_SPEED_LOWSPEED:
1978 			queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_LOW;
1979 			break;
1980 		case USB_SPEED_FULLSPEED:
1981 			queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_FULL;
1982 			break;
1983 		case USB_SPEED_HIGHSPEED:
1984 			queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH;
1985 			break;
1986 		default:
1987 			TRACE_ERROR("unknown pipe speed\n");
1988 			return B_ERROR;
1989 	}
1990 
1991 	queueHead->endpoint_chars |= (3 << EHCI_QH_CHARS_RL_SHIFT)
1992 		| (pipe->MaxPacketSize() << EHCI_QH_CHARS_MPL_SHIFT)
1993 		| (pipe->EndpointAddress() << EHCI_QH_CHARS_EPT_SHIFT)
1994 		| (pipe->DeviceAddress() << EHCI_QH_CHARS_DEV_SHIFT)
1995 		| EHCI_QH_CHARS_TOGGLE;
1996 
1997 	queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT);
1998 	if (pipe->Speed() != USB_SPEED_HIGHSPEED) {
1999 		if ((pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0)
2000 			queueHead->endpoint_chars |= EHCI_QH_CHARS_CONTROL;
2001 
2002 		queueHead->endpoint_caps |= (pipe->HubPort() << EHCI_QH_CAPS_PORT_SHIFT)
2003 			| (pipe->HubAddress() << EHCI_QH_CAPS_HUB_SHIFT);
2004 	}
2005 
2006 	return B_OK;
2007 }
2008 
2009 
2010 void
2011 EHCI::FreeQueueHead(ehci_qh *queueHead)
2012 {
2013 	if (!queueHead)
2014 		return;
2015 
2016 	FreeDescriptorChain(queueHead->element_log);
2017 	FreeDescriptor(queueHead->stray_log);
2018 	fStack->FreeChunk(queueHead, (phys_addr_t)queueHead->this_phy,
2019 		sizeof(ehci_qh));
2020 }
2021 
2022 
2023 status_t
2024 EHCI::LinkQueueHead(ehci_qh *queueHead)
2025 {
2026 	if (!Lock())
2027 		return B_ERROR;
2028 
2029 	ehci_qh *prevHead = fAsyncQueueHead->prev_log;
2030 	queueHead->next_phy = fAsyncQueueHead->this_phy;
2031 	queueHead->next_log = fAsyncQueueHead;
2032 	queueHead->prev_log = prevHead;
2033 	fAsyncQueueHead->prev_log = queueHead;
2034 	prevHead->next_log = queueHead;
2035 	prevHead->next_phy = queueHead->this_phy;
2036 
2037 	Unlock();
2038 	return B_OK;
2039 }
2040 
2041 
2042 status_t
2043 EHCI::LinkInterruptQueueHead(ehci_qh *queueHead, Pipe *pipe)
2044 {
2045 	if (!Lock())
2046 		return B_ERROR;
2047 
2048 	uint8 interval = pipe->Interval();
2049 	if (pipe->Speed() == USB_SPEED_HIGHSPEED) {
2050 		// Allow interrupts to be scheduled on each possible micro frame.
2051 		queueHead->endpoint_caps |= (0xff << EHCI_QH_CAPS_ISM_SHIFT);
2052 	} else {
2053 		// As we do not yet support FSTNs to correctly reference low/full
2054 		// speed interrupt transfers, we simply put them into the 1 interval
2055 		// queue. This way we ensure that we reach them on every micro frame
2056 		// and can do the corresponding start/complete split transactions.
2057 		// ToDo: use FSTNs to correctly link non high speed interrupt transfers
2058 		interval = 1;
2059 
2060 		// For now we also force start splits to be in micro frame 0 and
2061 		// complete splits to be in micro frame 2, 3 and 4.
2062 		queueHead->endpoint_caps |= (0x01 << EHCI_QH_CAPS_ISM_SHIFT);
2063 		queueHead->endpoint_caps |= (0x1c << EHCI_QH_CAPS_SCM_SHIFT);
2064 	}
2065 
2066 	// this should not happen
2067 	if (interval < 1)
2068 		interval = 1;
2069 
2070 	// this may happen as intervals can go up to 16; we limit the value to
2071 	// EHCI_INTERRUPT_ENTRIES_COUNT as you cannot support intervals above
2072 	// that with a frame list of just EHCI_VFRAMELIST_ENTRIES_COUNT entries...
2073 	if (interval > EHCI_INTERRUPT_ENTRIES_COUNT)
2074 		interval = EHCI_INTERRUPT_ENTRIES_COUNT;
2075 
2076 	ehci_qh *interruptQueue = &fInterruptEntries[interval - 1].queue_head;
2077 	queueHead->next_phy = interruptQueue->next_phy;
2078 	queueHead->next_log = interruptQueue->next_log;
2079 	queueHead->prev_log = interruptQueue;
2080 	if (interruptQueue->next_log)
2081 		interruptQueue->next_log->prev_log = queueHead;
2082 	interruptQueue->next_log = queueHead;
2083 	interruptQueue->next_phy = queueHead->this_phy;
2084 
2085 	Unlock();
2086 	return B_OK;
2087 }
2088 
2089 
2090 status_t
2091 EHCI::UnlinkQueueHead(ehci_qh *queueHead, ehci_qh **freeListHead)
2092 {
2093 	if (!Lock())
2094 		return B_ERROR;
2095 
2096 	ehci_qh *prevHead = queueHead->prev_log;
2097 	ehci_qh *nextHead = queueHead->next_log;
2098 	if (prevHead) {
2099 		prevHead->next_phy = queueHead->next_phy;
2100 		prevHead->next_log = queueHead->next_log;
2101 	}
2102 
2103 	if (nextHead)
2104 		nextHead->prev_log = queueHead->prev_log;
2105 
2106 	queueHead->next_phy = fAsyncQueueHead->this_phy;
2107 	queueHead->prev_log = NULL;
2108 
2109 	queueHead->next_log = *freeListHead;
2110 	*freeListHead = queueHead;
2111 
2112 	Unlock();
2113 	return B_OK;
2114 }
2115 
2116 
2117 status_t
2118 EHCI::FillQueueWithRequest(Transfer *transfer, ehci_qh *queueHead,
2119 	ehci_qtd **_dataDescriptor, bool *_directionIn)
2120 {
2121 	Pipe *pipe = transfer->TransferPipe();
2122 	usb_request_data *requestData = transfer->RequestData();
2123 	bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0;
2124 
2125 	ehci_qtd *setupDescriptor = CreateDescriptor(sizeof(usb_request_data),
2126 		EHCI_QTD_PID_SETUP);
2127 	ehci_qtd *statusDescriptor = CreateDescriptor(0,
2128 		directionIn ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN);
2129 
2130 	if (!setupDescriptor || !statusDescriptor) {
2131 		TRACE_ERROR("failed to allocate descriptors\n");
2132 		FreeDescriptor(setupDescriptor);
2133 		FreeDescriptor(statusDescriptor);
2134 		return B_NO_MEMORY;
2135 	}
2136 
2137 	iovec vector;
2138 	vector.iov_base = requestData;
2139 	vector.iov_len = sizeof(usb_request_data);
2140 	WriteDescriptorChain(setupDescriptor, &vector, 1);
2141 
2142 	ehci_qtd *strayDescriptor = queueHead->stray_log;
2143 	statusDescriptor->token |= EHCI_QTD_IOC | EHCI_QTD_DATA_TOGGLE;
2144 
2145 	ehci_qtd *dataDescriptor = NULL;
2146 	if (transfer->VectorCount() > 0) {
2147 		ehci_qtd *lastDescriptor = NULL;
2148 		status_t result = CreateDescriptorChain(pipe, &dataDescriptor,
2149 			&lastDescriptor, statusDescriptor, transfer->VectorLength(),
2150 			directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT);
2151 
2152 		if (result < B_OK) {
2153 			FreeDescriptor(setupDescriptor);
2154 			FreeDescriptor(statusDescriptor);
2155 			return result;
2156 		}
2157 
2158 		if (!directionIn) {
2159 			WriteDescriptorChain(dataDescriptor, transfer->Vector(),
2160 				transfer->VectorCount());
2161 		}
2162 
2163 		LinkDescriptors(setupDescriptor, dataDescriptor, strayDescriptor);
2164 		LinkDescriptors(lastDescriptor, statusDescriptor, statusDescriptor);
2165 	} else {
2166 		// no data: link setup and status descriptors directly
2167 		LinkDescriptors(setupDescriptor, statusDescriptor, strayDescriptor);
2168 	}
2169 
2170 	queueHead->element_log = setupDescriptor;
2171 	queueHead->overlay.next_phy = setupDescriptor->this_phy;
2172 	queueHead->overlay.alt_next_phy = EHCI_ITEM_TERMINATE;
2173 
2174 	*_dataDescriptor = dataDescriptor;
2175 	*_directionIn = directionIn;
2176 	return B_OK;
2177 }
2178 
2179 
2180 status_t
2181 EHCI::FillQueueWithData(Transfer *transfer, ehci_qh *queueHead,
2182 	ehci_qtd **_dataDescriptor, bool *_directionIn)
2183 {
2184 	Pipe *pipe = transfer->TransferPipe();
2185 	bool directionIn = (pipe->Direction() == Pipe::In);
2186 
2187 	ehci_qtd *firstDescriptor = NULL;
2188 	ehci_qtd *lastDescriptor = NULL;
2189 	ehci_qtd *strayDescriptor = queueHead->stray_log;
2190 	status_t result = CreateDescriptorChain(pipe, &firstDescriptor,
2191 		&lastDescriptor, strayDescriptor, transfer->VectorLength(),
2192 		directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT);
2193 
2194 	if (result < B_OK)
2195 		return result;
2196 
2197 	lastDescriptor->token |= EHCI_QTD_IOC;
2198 	if (!directionIn) {
2199 		WriteDescriptorChain(firstDescriptor, transfer->Vector(),
2200 			transfer->VectorCount());
2201 	}
2202 
2203 	queueHead->element_log = firstDescriptor;
2204 	queueHead->overlay.next_phy = firstDescriptor->this_phy;
2205 	queueHead->overlay.alt_next_phy = EHCI_ITEM_TERMINATE;
2206 
2207 	*_dataDescriptor = firstDescriptor;
2208 	if (_directionIn)
2209 		*_directionIn = directionIn;
2210 	return B_OK;
2211 }
2212 
2213 
2214 ehci_qtd *
2215 EHCI::CreateDescriptor(size_t bufferSize, uint8 pid)
2216 {
2217 	ehci_qtd *result;
2218 	phys_addr_t physicalAddress;
2219 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
2220 		sizeof(ehci_qtd)) < B_OK) {
2221 		TRACE_ERROR("failed to allocate a qtd\n");
2222 		return NULL;
2223 	}
2224 
2225 	result->this_phy = (addr_t)physicalAddress;
2226 	result->next_phy = EHCI_ITEM_TERMINATE;
2227 	result->next_log = NULL;
2228 	result->alt_next_phy = EHCI_ITEM_TERMINATE;
2229 	result->alt_next_log = NULL;
2230 	result->buffer_size = bufferSize;
2231 	result->token = bufferSize << EHCI_QTD_BYTES_SHIFT;
2232 	result->token |= 3 << EHCI_QTD_ERRCOUNT_SHIFT;
2233 	result->token |= pid << EHCI_QTD_PID_SHIFT;
2234 	result->token |= EHCI_QTD_STATUS_ACTIVE;
2235 	if (bufferSize == 0) {
2236 		result->buffer_log = NULL;
2237 		for (int32 i = 0; i < 5; i++) {
2238 			result->buffer_phy[i] = 0;
2239 			result->ext_buffer_phy[i] = 0;
2240 		}
2241 
2242 		return result;
2243 	}
2244 
2245 	if (fStack->AllocateChunk(&result->buffer_log, &physicalAddress,
2246 		bufferSize) < B_OK) {
2247 		TRACE_ERROR("unable to allocate qtd buffer\n");
2248 		fStack->FreeChunk(result, (phys_addr_t)result->this_phy,
2249 			sizeof(ehci_qtd));
2250 		return NULL;
2251 	}
2252 
2253 	addr_t physicalBase = (addr_t)physicalAddress;
2254 	result->buffer_phy[0] = physicalBase;
2255 	result->ext_buffer_phy[0] = 0;
2256 	for (int32 i = 1; i < 5; i++) {
2257 		physicalBase += B_PAGE_SIZE;
2258 		result->buffer_phy[i] = physicalBase & EHCI_QTD_PAGE_MASK;
2259 		result->ext_buffer_phy[i] = 0;
2260 	}
2261 
2262 	return result;
2263 }
2264 
2265 
2266 status_t
2267 EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **_firstDescriptor,
2268 	ehci_qtd **_lastDescriptor, ehci_qtd *strayDescriptor, size_t bufferSize,
2269 	uint8 pid)
2270 {
2271 	size_t packetSize = B_PAGE_SIZE * 4;
2272 	int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize;
2273 
2274 	bool dataToggle = pipe->DataToggle();
2275 	ehci_qtd *firstDescriptor = NULL;
2276 	ehci_qtd *lastDescriptor = *_firstDescriptor;
2277 	for (int32 i = 0; i < descriptorCount; i++) {
2278 		ehci_qtd *descriptor = CreateDescriptor(min_c(packetSize, bufferSize),
2279 			pid);
2280 
2281 		if (!descriptor) {
2282 			FreeDescriptorChain(firstDescriptor);
2283 			return B_NO_MEMORY;
2284 		}
2285 
2286 		if (dataToggle)
2287 			descriptor->token |= EHCI_QTD_DATA_TOGGLE;
2288 
2289 		if (lastDescriptor)
2290 			LinkDescriptors(lastDescriptor, descriptor, strayDescriptor);
2291 
2292 		bufferSize -= packetSize;
2293 		lastDescriptor = descriptor;
2294 		if (!firstDescriptor)
2295 			firstDescriptor = descriptor;
2296 	}
2297 
2298 	*_firstDescriptor = firstDescriptor;
2299 	*_lastDescriptor = lastDescriptor;
2300 	return B_OK;
2301 }
2302 
2303 
2304 void
2305 EHCI::FreeDescriptor(ehci_qtd *descriptor)
2306 {
2307 	if (!descriptor)
2308 		return;
2309 
2310 	if (descriptor->buffer_log) {
2311 		fStack->FreeChunk(descriptor->buffer_log,
2312 			(phys_addr_t)descriptor->buffer_phy[0], descriptor->buffer_size);
2313 	}
2314 
2315 	fStack->FreeChunk(descriptor, (phys_addr_t)descriptor->this_phy,
2316 		sizeof(ehci_qtd));
2317 }
2318 
2319 
2320 void
2321 EHCI::FreeDescriptorChain(ehci_qtd *topDescriptor)
2322 {
2323 	ehci_qtd *current = topDescriptor;
2324 	ehci_qtd *next = NULL;
2325 
2326 	while (current) {
2327 		next = current->next_log;
2328 		FreeDescriptor(current);
2329 		current = next;
2330 	}
2331 }
2332 
2333 
2334 ehci_itd *
2335 EHCI::CreateItdDescriptor()
2336 {
2337 	ehci_itd *result;
2338 	phys_addr_t physicalAddress;
2339 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
2340 		sizeof(ehci_itd)) < B_OK) {
2341 		TRACE_ERROR("failed to allocate a itd\n");
2342 		return NULL;
2343 	}
2344 
2345 	memset(result, 0, sizeof(ehci_itd));
2346 	result->this_phy = (addr_t)physicalAddress;
2347 	result->next_phy = EHCI_ITEM_TERMINATE;
2348 
2349 	return result;
2350 }
2351 
2352 
2353 ehci_sitd *
2354 EHCI::CreateSitdDescriptor()
2355 {
2356 	ehci_sitd *result;
2357 	phys_addr_t physicalAddress;
2358 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
2359 		sizeof(ehci_sitd)) < B_OK) {
2360 		TRACE_ERROR("failed to allocate a sitd\n");
2361 		return NULL;
2362 	}
2363 
2364 	memset(result, 0, sizeof(ehci_sitd));
2365 	result->this_phy = (addr_t)physicalAddress | EHCI_ITEM_TYPE_SITD;
2366 	result->next_phy = EHCI_ITEM_TERMINATE;
2367 
2368 	return result;
2369 }
2370 
2371 
2372 void
2373 EHCI::FreeDescriptor(ehci_itd *descriptor)
2374 {
2375 	if (!descriptor)
2376 		return;
2377 
2378 	fStack->FreeChunk(descriptor, (phys_addr_t)descriptor->this_phy,
2379 		sizeof(ehci_itd));
2380 }
2381 
2382 
2383 void
2384 EHCI::FreeDescriptor(ehci_sitd *descriptor)
2385 {
2386 	if (!descriptor)
2387 		return;
2388 
2389 	fStack->FreeChunk(descriptor, (phys_addr_t)descriptor->this_phy,
2390 		sizeof(ehci_sitd));
2391 }
2392 
2393 
2394 void
2395 EHCI::LinkDescriptors(ehci_qtd *first, ehci_qtd *last, ehci_qtd *alt)
2396 {
2397 	first->next_phy = last->this_phy;
2398 	first->next_log = last;
2399 
2400 	if (alt) {
2401 		first->alt_next_phy = alt->this_phy;
2402 		first->alt_next_log = alt;
2403 	} else {
2404 		first->alt_next_phy = EHCI_ITEM_TERMINATE;
2405 		first->alt_next_log = NULL;
2406 	}
2407 }
2408 
2409 
2410 void
2411 EHCI::LinkITDescriptors(ehci_itd *itd, ehci_itd **_last)
2412 {
2413 	ehci_itd *last = *_last;
2414 	itd->next_phy = last->next_phy;
2415 	itd->next = NULL;
2416 	itd->prev = last;
2417 	last->next = itd;
2418 	last->next_phy = itd->this_phy;
2419 	*_last = itd;
2420 }
2421 
2422 
2423 void
2424 EHCI::LinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **_last)
2425 {
2426 	ehci_sitd *last = *_last;
2427 	sitd->next_phy = last->next_phy;
2428 	sitd->next = NULL;
2429 	sitd->prev = last;
2430 	last->next = sitd;
2431 	last->next_phy = sitd->this_phy;
2432 	*_last = sitd;
2433 }
2434 
2435 
2436 void
2437 EHCI::UnlinkITDescriptors(ehci_itd *itd, ehci_itd **last)
2438 {
2439 	itd->prev->next_phy = itd->next_phy;
2440 	itd->prev->next = itd->next;
2441 	if (itd->next != NULL)
2442 		itd->next->prev = itd->prev;
2443 	if (itd == *last)
2444 		*last = itd->prev;
2445 }
2446 
2447 
2448 void
2449 EHCI::UnlinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **last)
2450 {
2451 	sitd->prev->next_phy = sitd->next_phy;
2452 	sitd->prev->next = sitd->next;
2453 	if (sitd->next != NULL)
2454 		sitd->next->prev = sitd->prev;
2455 	if (sitd == *last)
2456 		*last = sitd->prev;
2457 }
2458 
2459 
2460 size_t
2461 EHCI::WriteDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
2462 	size_t vectorCount)
2463 {
2464 	ehci_qtd *current = topDescriptor;
2465 	size_t actualLength = 0;
2466 	size_t vectorIndex = 0;
2467 	size_t vectorOffset = 0;
2468 	size_t bufferOffset = 0;
2469 
2470 	while (current) {
2471 		if (!current->buffer_log)
2472 			break;
2473 
2474 		while (true) {
2475 			size_t length = min_c(current->buffer_size - bufferOffset,
2476 				vector[vectorIndex].iov_len - vectorOffset);
2477 
2478 			memcpy((uint8 *)current->buffer_log + bufferOffset,
2479 				(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
2480 
2481 			actualLength += length;
2482 			vectorOffset += length;
2483 			bufferOffset += length;
2484 
2485 			if (vectorOffset >= vector[vectorIndex].iov_len) {
2486 				if (++vectorIndex >= vectorCount) {
2487 					TRACE("wrote descriptor chain (%ld bytes, no more vectors)"
2488 						"\n", actualLength);
2489 					return actualLength;
2490 				}
2491 
2492 				vectorOffset = 0;
2493 			}
2494 
2495 			if (bufferOffset >= current->buffer_size) {
2496 				bufferOffset = 0;
2497 				break;
2498 			}
2499 		}
2500 
2501 		if (current->next_phy & EHCI_ITEM_TERMINATE)
2502 			break;
2503 
2504 		current = current->next_log;
2505 	}
2506 
2507 	TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
2508 	return actualLength;
2509 }
2510 
2511 
2512 size_t
2513 EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
2514 	size_t vectorCount, bool *nextDataToggle)
2515 {
2516 	uint32 dataToggle = 0;
2517 	ehci_qtd *current = topDescriptor;
2518 	size_t actualLength = 0;
2519 	size_t vectorIndex = 0;
2520 	size_t vectorOffset = 0;
2521 	size_t bufferOffset = 0;
2522 
2523 	while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) {
2524 		if (!current->buffer_log)
2525 			break;
2526 
2527 		dataToggle = current->token & EHCI_QTD_DATA_TOGGLE;
2528 		size_t bufferSize = current->buffer_size;
2529 		bufferSize -= (current->token >> EHCI_QTD_BYTES_SHIFT)
2530 			& EHCI_QTD_BYTES_MASK;
2531 
2532 		while (true) {
2533 			size_t length = min_c(bufferSize - bufferOffset,
2534 				vector[vectorIndex].iov_len - vectorOffset);
2535 
2536 			memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
2537 				(uint8 *)current->buffer_log + bufferOffset, length);
2538 
2539 			actualLength += length;
2540 			vectorOffset += length;
2541 			bufferOffset += length;
2542 
2543 			if (vectorOffset >= vector[vectorIndex].iov_len) {
2544 				if (++vectorIndex >= vectorCount) {
2545 					TRACE("read descriptor chain (%ld bytes, no more vectors)"
2546 						"\n", actualLength);
2547 					*nextDataToggle = dataToggle > 0 ? true : false;
2548 					return actualLength;
2549 				}
2550 
2551 				vectorOffset = 0;
2552 			}
2553 
2554 			if (bufferOffset >= bufferSize) {
2555 				bufferOffset = 0;
2556 				break;
2557 			}
2558 		}
2559 
2560 		if (current->next_phy & EHCI_ITEM_TERMINATE)
2561 			break;
2562 
2563 		current = current->next_log;
2564 	}
2565 
2566 	TRACE("read descriptor chain (%ld bytes)\n", actualLength);
2567 	*nextDataToggle = dataToggle > 0 ? true : false;
2568 	return actualLength;
2569 }
2570 
2571 
2572 size_t
2573 EHCI::ReadActualLength(ehci_qtd *topDescriptor, bool *nextDataToggle)
2574 {
2575 	size_t actualLength = 0;
2576 	ehci_qtd *current = topDescriptor;
2577 	uint32 dataToggle = 0;
2578 
2579 	while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) {
2580 		dataToggle = current->token & EHCI_QTD_DATA_TOGGLE;
2581 		size_t length = current->buffer_size;
2582 		length -= (current->token >> EHCI_QTD_BYTES_SHIFT)
2583 			& EHCI_QTD_BYTES_MASK;
2584 		actualLength += length;
2585 
2586 		if (current->next_phy & EHCI_ITEM_TERMINATE)
2587 			break;
2588 
2589 		current = current->next_log;
2590 	}
2591 
2592 	TRACE("read actual length (%ld bytes)\n", actualLength);
2593 	*nextDataToggle = dataToggle > 0 ? true : false;
2594 	return actualLength;
2595 }
2596 
2597 
2598 size_t
2599 EHCI::WriteIsochronousDescriptorChain(isochronous_transfer_data *transfer,
2600 	uint32 packetCount,	iovec *vector)
2601 {
2602 	// TODO implement
2603 	return 0;
2604 }
2605 
2606 
2607 size_t
2608 EHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer)
2609 {
2610 	iovec *vector = transfer->transfer->Vector();
2611 	size_t vectorCount = transfer->transfer->VectorCount();
2612 	size_t vectorOffset = 0;
2613 	size_t vectorIndex = 0;
2614 	usb_isochronous_data *isochronousData
2615 		= transfer->transfer->IsochronousData();
2616 	uint32 packet = 0;
2617 	size_t totalLength = 0;
2618 	size_t bufferOffset = 0;
2619 
2620 	size_t packetSize = transfer->transfer->DataLength();
2621 	packetSize /= isochronousData->packet_count;
2622 
2623 	for (uint32 i = 0; i <= transfer->last_to_process; i++) {
2624 		ehci_itd *itd = transfer->descriptors[i];
2625 		for (uint32 j = 0; j <= itd->last_token
2626 			&& packet < isochronousData->packet_count; j++) {
2627 
2628 			size_t bufferSize = (itd->token[j] >> EHCI_ITD_TLENGTH_SHIFT)
2629 				& EHCI_ITD_TLENGTH_MASK;
2630 			if (((itd->token[j] >> EHCI_ITD_STATUS_SHIFT)
2631 				& EHCI_ITD_STATUS_MASK) != 0) {
2632 				bufferSize = 0;
2633 			}
2634 			isochronousData->packet_descriptors[packet].actual_length
2635 				= bufferSize;
2636 
2637 			if (bufferSize > 0)
2638 				isochronousData->packet_descriptors[packet].status = B_OK;
2639 			else
2640 				isochronousData->packet_descriptors[packet].status = B_ERROR;
2641 
2642 			totalLength += bufferSize;
2643 
2644 			size_t offset = bufferOffset;
2645 			size_t skipSize = packetSize - bufferSize;
2646 			while (bufferSize > 0) {
2647 				size_t length = min_c(bufferSize,
2648 					vector[vectorIndex].iov_len - vectorOffset);
2649 				memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
2650 					(uint8 *)transfer->buffer_log + bufferOffset, length);
2651 				offset += length;
2652 				vectorOffset += length;
2653 				bufferSize -= length;
2654 
2655 				if (vectorOffset >= vector[vectorIndex].iov_len) {
2656 					if (++vectorIndex >= vectorCount) {
2657 						TRACE("read isodescriptor chain (%ld bytes, no more "
2658 							"vectors)\n", totalLength);
2659 						return totalLength;
2660 					}
2661 
2662 					vectorOffset = 0;
2663 				}
2664 			}
2665 
2666 			// skip to next packet offset
2667 			while (skipSize > 0) {
2668 				size_t length = min_c(skipSize,
2669 					vector[vectorIndex].iov_len - vectorOffset);
2670 				vectorOffset += length;
2671 				skipSize -= length;
2672 				if (vectorOffset >= vector[vectorIndex].iov_len) {
2673 					if (++vectorIndex >= vectorCount) {
2674 						TRACE("read isodescriptor chain (%ld bytes, no more "
2675 							"vectors)\n", totalLength);
2676 						return totalLength;
2677 					}
2678 
2679 					vectorOffset = 0;
2680 				}
2681 			}
2682 
2683 			bufferOffset += packetSize;
2684 			if (bufferOffset >= transfer->buffer_size)
2685 				return totalLength;
2686 
2687 			packet++;
2688 		}
2689 	}
2690 
2691 	TRACE("ReadIsochronousDescriptorChain packet count %" B_PRId32 "\n",
2692 		packet);
2693 
2694 	return totalLength;
2695 }
2696 
2697 
2698 bool
2699 EHCI::LockIsochronous()
2700 {
2701 	return (mutex_lock(&fIsochronousLock) == B_OK);
2702 }
2703 
2704 
2705 void
2706 EHCI::UnlockIsochronous()
2707 {
2708 	mutex_unlock(&fIsochronousLock);
2709 }
2710 
2711 
2712 inline void
2713 EHCI::WriteOpReg(uint32 reg, uint32 value)
2714 {
2715 	*(volatile uint32 *)(fOperationalRegisters + reg) = value;
2716 }
2717 
2718 
2719 inline uint32
2720 EHCI::ReadOpReg(uint32 reg)
2721 {
2722 	return *(volatile uint32 *)(fOperationalRegisters + reg);
2723 }
2724 
2725 
2726 inline uint8
2727 EHCI::ReadCapReg8(uint32 reg)
2728 {
2729 	return *(volatile uint8 *)(fCapabilityRegisters + reg);
2730 }
2731 
2732 
2733 inline uint16
2734 EHCI::ReadCapReg16(uint32 reg)
2735 {
2736 	return *(volatile uint16 *)(fCapabilityRegisters + reg);
2737 }
2738 
2739 
2740 inline uint32
2741 EHCI::ReadCapReg32(uint32 reg)
2742 {
2743 	return *(volatile uint32 *)(fCapabilityRegisters + reg);
2744 }
2745