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