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