1/*
2 * Copyright 2004-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 *		Niels S. Reedijk
8 *		Salvatore Benedetto <salvatore.benedetto@gmail.com>
9 */
10
11
12#include <stdio.h>
13
14#include <module.h>
15#include <bus/PCI.h>
16#include <USB3.h>
17#include <KernelExport.h>
18
19#include "uhci.h"
20
21
22#define CALLED(x...)	TRACE_MODULE("CALLED %s\n", __PRETTY_FUNCTION__)
23
24#define USB_MODULE_NAME "uhci"
25
26device_manager_info* gDeviceManager;
27static usb_for_controller_interface* gUSB;
28
29
30#define UHCI_PCI_DEVICE_MODULE_NAME "busses/usb/uhci/pci/driver_v1"
31#define UHCI_PCI_USB_BUS_MODULE_NAME "busses/usb/uhci/device_v1"
32
33
34typedef struct {
35	UHCI* uhci;
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} uhci_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	uhci_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	UHCI *uhci = new(std::nothrow) UHCI(&bus->pciinfo, bus->pci, bus->device, stack, node);
65	if (uhci == NULL) {
66		return B_NO_MEMORY;
67	}
68
69	if (uhci->InitCheck() < B_OK) {
70		TRACE_MODULE_ERROR("bus failed init check\n");
71		delete uhci;
72		return B_ERROR;
73	}
74
75	if (uhci->Start() != B_OK) {
76		delete uhci;
77		return B_ERROR;
78	}
79
80	*bus_cookie = uhci;
81
82	return B_OK;
83}
84
85
86static void
87uninit_bus(void* bus_cookie)
88{
89	CALLED();
90	UHCI* uhci = (UHCI*)bus_cookie;
91	delete uhci;
92}
93
94
95static status_t
96register_child_devices(void* cookie)
97{
98	CALLED();
99	uhci_pci_sim_info* bus = (uhci_pci_sim_info*)cookie;
100	device_node* node = bus->driver_node;
101
102	char prettyName[25];
103	sprintf(prettyName, "UHCI 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, UHCI_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	uhci_pci_sim_info* bus = (uhci_pci_sim_info*)calloc(1,
126		sizeof(uhci_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	uhci_pci_sim_info* bus = (uhci_pci_sim_info*)device_cookie;
156	free(bus);
157}
158
159
160static status_t
161register_device(device_node* parent)
162{
163	CALLED();
164	device_attr attrs[] = {
165		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "UHCI PCI"}},
166		{}
167	};
168
169	return gDeviceManager->register_node(parent,
170		UHCI_PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL);
171}
172
173
174static float
175supports_device(device_node* parent)
176{
177	CALLED();
178	const char* bus;
179	uint16 type, subType, api;
180
181	// make sure parent is a UHCI PCI device node
182	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
183		< B_OK) {
184		return -1;
185	}
186
187	if (strcmp(bus, "pci") != 0)
188		return 0.0f;
189
190	if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subType,
191			false) < B_OK
192		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &type,
193			false) < B_OK
194		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_INTERFACE, &api,
195			false) < B_OK) {
196		TRACE_MODULE("Could not find type/subtype/interface attributes\n");
197		return -1;
198	}
199
200	if (type == PCI_serial_bus && subType == PCI_usb && api == PCI_usb_uhci) {
201		pci_device_module_info* pci;
202		pci_device* device;
203		gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
204			(void**)&device);
205		TRACE_MODULE("UHCI Device found!\n");
206
207		return 0.8f;
208	}
209
210	return 0.0f;
211}
212
213
214module_dependency module_dependencies[] = {
215	{ USB_FOR_CONTROLLER_MODULE_NAME, (module_info**)&gUSB },
216	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
217	{}
218};
219
220
221static usb_bus_interface gUHCIPCIDeviceModule = {
222	{
223		{
224			UHCI_PCI_USB_BUS_MODULE_NAME,
225			0,
226			NULL
227		},
228		NULL,  // supports device
229		NULL,  // register device
230		init_bus,
231		uninit_bus,
232		NULL,  // register child devices
233		NULL,  // rescan
234		NULL,  // device removed
235	},
236};
237
238// Root device that binds to the PCI bus. It will register an usb_bus_interface
239// node for each device.
240static driver_module_info sUHCIDevice = {
241	{
242		UHCI_PCI_DEVICE_MODULE_NAME,
243		0,
244		NULL
245	},
246	supports_device,
247	register_device,
248	init_device,
249	uninit_device,
250	register_child_devices,
251	NULL, // rescan
252	NULL, // device removed
253};
254
255module_info* modules[] = {
256	(module_info* )&sUHCIDevice,
257	(module_info* )&gUHCIPCIDeviceModule,
258	NULL
259};
260
261
262//
263// #pragma mark -
264//
265
266
267#ifdef TRACE_USB
268
269void
270print_descriptor_chain(uhci_td *descriptor)
271{
272	while (descriptor) {
273		dprintf("ph: 0x%08" B_PRIx32 "; lp: 0x%08" B_PRIx32 "; vf: %s; q: %s; "
274			"t: %s; st: 0x%08" B_PRIx32 "; to: 0x%08" B_PRIx32 "\n",
275			descriptor->this_phy & 0xffffffff, descriptor->link_phy & 0xfffffff0,
276			descriptor->link_phy & 0x4 ? "y" : "n",
277			descriptor->link_phy & 0x2 ? "qh" : "td",
278			descriptor->link_phy & 0x1 ? "y" : "n",
279			descriptor->status, descriptor->token);
280
281		if (descriptor->link_phy & TD_TERMINATE)
282			break;
283
284		descriptor = (uhci_td *)descriptor->link_log;
285	}
286}
287
288#endif // TRACE_USB
289
290
291//
292// #pragma mark -
293//
294
295
296Queue::Queue(Stack *stack)
297{
298	fStack = stack;
299
300	mutex_init(&fLock, "uhci queue lock");
301
302	phys_addr_t physicalAddress;
303	fStatus = fStack->AllocateChunk((void **)&fQueueHead, &physicalAddress,
304		sizeof(uhci_qh));
305	if (fStatus < B_OK)
306		return;
307
308	fQueueHead->this_phy = (uint32)physicalAddress;
309	fQueueHead->element_phy = QH_TERMINATE;
310
311	fStrayDescriptor = NULL;
312	fQueueTop = NULL;
313}
314
315
316Queue::~Queue()
317{
318	Lock();
319	mutex_destroy(&fLock);
320
321	fStack->FreeChunk(fQueueHead, fQueueHead->this_phy, sizeof(uhci_qh));
322
323	if (fStrayDescriptor)
324		fStack->FreeChunk(fStrayDescriptor, fStrayDescriptor->this_phy,
325			sizeof(uhci_td));
326}
327
328
329status_t
330Queue::InitCheck()
331{
332	return fStatus;
333}
334
335
336bool
337Queue::Lock()
338{
339	return (mutex_lock(&fLock) == B_OK);
340}
341
342
343void
344Queue::Unlock()
345{
346	mutex_unlock(&fLock);
347}
348
349
350status_t
351Queue::LinkTo(Queue *other)
352{
353	if (!other)
354		return B_BAD_VALUE;
355
356	if (!Lock())
357		return B_ERROR;
358
359	fQueueHead->link_phy = other->fQueueHead->this_phy | QH_NEXT_IS_QH;
360	fQueueHead->link_log = other->fQueueHead;
361	Unlock();
362
363	return B_OK;
364}
365
366
367status_t
368Queue::TerminateByStrayDescriptor()
369{
370	// According to the *BSD USB sources, there needs to be a stray transfer
371	// descriptor in order to get some chipset to work nicely (like the PIIX).
372	phys_addr_t physicalAddress;
373	status_t result = fStack->AllocateChunk((void **)&fStrayDescriptor,
374		&physicalAddress, sizeof(uhci_td));
375	if (result < B_OK) {
376		TRACE_ERROR("failed to allocate a stray transfer descriptor\n");
377		return result;
378	}
379
380	fStrayDescriptor->status = 0;
381	fStrayDescriptor->this_phy = (uint32)physicalAddress;
382	fStrayDescriptor->link_phy = TD_TERMINATE;
383	fStrayDescriptor->link_log = NULL;
384	fStrayDescriptor->buffer_phy = 0;
385	fStrayDescriptor->buffer_log = NULL;
386	fStrayDescriptor->buffer_size = 0;
387	fStrayDescriptor->token = TD_TOKEN_NULL_DATA
388		| (0x7f << TD_TOKEN_DEVADDR_SHIFT) | TD_TOKEN_IN;
389
390	if (!Lock()) {
391		fStack->FreeChunk(fStrayDescriptor, fStrayDescriptor->this_phy,
392			sizeof(uhci_td));
393		return B_ERROR;
394	}
395
396	fQueueHead->link_phy = fStrayDescriptor->this_phy;
397	fQueueHead->link_log = fStrayDescriptor;
398	Unlock();
399
400	return B_OK;
401}
402
403
404status_t
405Queue::AppendTransfer(uhci_qh *transfer, bool lock)
406{
407	if (lock && !Lock())
408		return B_ERROR;
409
410	transfer->link_log = NULL;
411	transfer->link_phy = fQueueHead->link_phy;
412
413	if (!fQueueTop) {
414		// the list is empty, make this the first element
415		fQueueTop = transfer;
416		fQueueHead->element_phy = transfer->this_phy | QH_NEXT_IS_QH;
417	} else {
418		// append the transfer queue to the list
419		uhci_qh *element = fQueueTop;
420		while (element->link_log != NULL)
421			element = (uhci_qh *)element->link_log;
422
423		element->link_log = transfer;
424		element->link_phy = transfer->this_phy | QH_NEXT_IS_QH;
425	}
426
427	if (lock)
428		Unlock();
429	return B_OK;
430}
431
432
433status_t
434Queue::RemoveTransfer(uhci_qh *transfer, bool lock)
435{
436	if (lock && !Lock())
437		return B_ERROR;
438
439	if (fQueueTop == transfer) {
440		// this was the top element
441		fQueueTop = (uhci_qh *)transfer->link_log;
442		if (!fQueueTop) {
443			// this was the only element, terminate this queue
444			fQueueHead->element_phy = QH_TERMINATE;
445		} else {
446			// there are elements left, adjust the element pointer
447			fQueueHead->element_phy = transfer->link_phy;
448		}
449
450		if (lock)
451			Unlock();
452		return B_OK;
453	} else {
454		uhci_qh *element = fQueueTop;
455		while (element) {
456			if (element->link_log == transfer) {
457				element->link_log = transfer->link_log;
458				element->link_phy = transfer->link_phy;
459				if (lock)
460					Unlock();
461				return B_OK;
462			}
463
464			element = (uhci_qh *)element->link_log;
465		}
466	}
467
468	if (lock)
469		Unlock();
470	return B_BAD_VALUE;
471}
472
473
474uint32
475Queue::PhysicalAddress()
476{
477	return fQueueHead->this_phy;
478}
479
480
481void
482Queue::PrintToStream()
483{
484#ifdef TRACE_USB
485	TRACE("queue:\n");
486	dprintf("link phy: 0x%08" B_PRIx32 "; link type: %s; terminate: %s\n",
487		fQueueHead->link_phy & 0xfff0,
488		fQueueHead->link_phy & 0x0002 ? "QH" : "TD",
489		fQueueHead->link_phy & 0x0001 ? "yes" : "no");
490	dprintf("elem phy: 0x%08" B_PRIx32 "; elem type: %s; terminate: %s\n",
491		fQueueHead->element_phy & 0xfff0,
492		fQueueHead->element_phy & 0x0002 ? "QH" : "TD",
493		fQueueHead->element_phy & 0x0001 ? "yes" : "no");
494#endif
495}
496
497
498//
499// #pragma mark -
500//
501
502
503UHCI::UHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stack *stack,
504	device_node* node)
505	:	BusManager(stack, node),
506		fPCIInfo(info),
507		fPci(pci),
508		fDevice(device),
509		fStack(stack),
510		fEnabledInterrupts(0),
511		fFrameArea(-1),
512		fFrameList(NULL),
513		fFrameBandwidth(NULL),
514		fFirstIsochronousDescriptor(NULL),
515		fLastIsochronousDescriptor(NULL),
516		fQueueCount(0),
517		fQueues(NULL),
518		fFirstTransfer(NULL),
519		fLastTransfer(NULL),
520		fFinishTransfersSem(-1),
521		fFinishThread(-1),
522		fStopThreads(false),
523		fProcessingPipe(NULL),
524		fFreeList(NULL),
525		fCleanupThread(-1),
526		fCleanupSem(-1),
527		fCleanupCount(0),
528		fFirstIsochronousTransfer(NULL),
529		fLastIsochronousTransfer(NULL),
530		fFinishIsochronousTransfersSem(-1),
531		fFinishIsochronousThread(-1),
532		fRootHub(NULL),
533		fRootHubAddress(0),
534		fPortResetChange(0),
535		fIRQ(0),
536		fUseMSI(false)
537{
538	// Create a lock for the isochronous transfer list
539	mutex_init(&fIsochronousLock, "UHCI isochronous lock");
540
541	if (!fInitOK) {
542		TRACE_ERROR("bus manager failed to init\n");
543		return;
544	}
545
546	TRACE("constructing new UHCI host controller driver\n");
547	fInitOK = false;
548
549	fRegisterBase = fPci->read_pci_config(fDevice, PCI_memory_base, 4);
550	fRegisterBase &= PCI_address_io_mask;
551	TRACE("iospace offset: 0x%08" B_PRIx32 "\n", fRegisterBase);
552
553	if (fRegisterBase == 0) {
554		fRegisterBase = fPCIInfo->u.h0.base_registers[0];
555		TRACE_ALWAYS("register base: 0x%08" B_PRIx32 "\n", fRegisterBase);
556	}
557
558	// enable pci address access
559	uint16 command = PCI_command_io | PCI_command_master | PCI_command_memory;
560	command |= fPci->read_pci_config(fDevice, PCI_command, 2);
561
562	fPci->write_pci_config(fDevice, PCI_command, 2, command);
563
564	// disable interrupts
565	WriteReg16(UHCI_USBINTR, 0);
566
567	// make sure we gain control of the UHCI controller instead of the BIOS
568	fPci->write_pci_config(fDevice, PCI_LEGSUP, 2, PCI_LEGSUP_USBPIRQDEN
569		| PCI_LEGSUP_CLEAR_SMI);
570
571	// do a global and host reset
572	GlobalReset();
573	if (ControllerReset() < B_OK) {
574		TRACE_ERROR("host failed to reset\n");
575		return;
576	}
577
578	// Setup the frame list
579	phys_addr_t physicalAddress;
580	fFrameArea = fStack->AllocateArea((void **)&fFrameList, &physicalAddress,
581		4096, "USB UHCI framelist");
582
583	if (fFrameArea < B_OK) {
584		TRACE_ERROR("unable to create an area for the frame pointer list\n");
585		return;
586	}
587
588	// Set base pointer and reset frame number
589	WriteReg32(UHCI_FRBASEADD, (uint32)physicalAddress);
590	WriteReg16(UHCI_FRNUM, 0);
591
592	// Set the max packet size for bandwidth reclamation to 64 bytes
593	WriteReg16(UHCI_USBCMD, ReadReg16(UHCI_USBCMD) | UHCI_USBCMD_MAXP);
594
595	// we will create four queues:
596	// 0: interrupt transfers
597	// 1: low speed control transfers
598	// 2: full speed control transfers
599	// 3: bulk transfers
600	// 4: debug queue
601	// TODO: 4: bandwidth reclamation queue
602	fQueueCount = 5;
603	fQueues = new(std::nothrow) Queue *[fQueueCount];
604	if (!fQueues) {
605		delete_area(fFrameArea);
606		return;
607	}
608
609	for (int32 i = 0; i < fQueueCount; i++) {
610		fQueues[i] = new(std::nothrow) Queue(fStack);
611		if (!fQueues[i] || fQueues[i]->InitCheck() < B_OK) {
612			TRACE_ERROR("cannot create queues\n");
613			delete_area(fFrameArea);
614			return;
615		}
616
617		if (i > 0)
618			fQueues[i - 1]->LinkTo(fQueues[i]);
619	}
620
621	// Make sure the last queue terminates
622	fQueues[fQueueCount - 1]->TerminateByStrayDescriptor();
623
624	// Create the array that will keep bandwidth information
625	fFrameBandwidth = new(std::nothrow) uint16[NUMBER_OF_FRAMES];
626
627	// Create lists for managing isochronous transfer descriptors
628	fFirstIsochronousDescriptor = new(std::nothrow) uhci_td *[NUMBER_OF_FRAMES];
629	if (!fFirstIsochronousDescriptor) {
630		TRACE_ERROR("faild to allocate memory for first isochronous descriptor\n");
631		return;
632	}
633
634	fLastIsochronousDescriptor = new(std::nothrow) uhci_td *[NUMBER_OF_FRAMES];
635	if (!fLastIsochronousDescriptor) {
636		TRACE_ERROR("failed to allocate memory for last isochronous descriptor\n");
637		delete [] fFirstIsochronousDescriptor;
638		return;
639	}
640
641	for (int32 i = 0; i < NUMBER_OF_FRAMES; i++) {
642		fFrameList[i] =	fQueues[UHCI_INTERRUPT_QUEUE]->PhysicalAddress()
643			| FRAMELIST_NEXT_IS_QH;
644		fFrameBandwidth[i] = MAX_AVAILABLE_BANDWIDTH;
645		fFirstIsochronousDescriptor[i] = NULL;
646		fLastIsochronousDescriptor[i] = NULL;
647	}
648
649	// Create semaphore the finisher and cleanup threads will wait for
650	fFinishTransfersSem = create_sem(0, "UHCI Finish Transfers");
651	if (fFinishTransfersSem < B_OK) {
652		TRACE_ERROR("failed to create finisher semaphore\n");
653		return;
654	}
655
656	fCleanupSem = create_sem(0, "UHCI Cleanup");
657	if (fCleanupSem < B_OK) {
658		TRACE_ERROR("failed to create cleanup semaphore\n");
659		return;
660	}
661
662	// Create the finisher service and cleanup threads
663	fFinishThread = spawn_kernel_thread(FinishThread,
664		"uhci finish thread", B_URGENT_DISPLAY_PRIORITY, (void *)this);
665	resume_thread(fFinishThread);
666
667	fCleanupThread = spawn_kernel_thread(CleanupThread,
668		"uhci cleanup thread", B_NORMAL_PRIORITY, (void *)this);
669	resume_thread(fCleanupThread);
670
671	// Create semaphore the isochronous finisher thread will wait for
672	fFinishIsochronousTransfersSem = create_sem(0,
673		"UHCI Isochronous Finish Transfers");
674	if (fFinishIsochronousTransfersSem < B_OK) {
675		TRACE_ERROR("failed to create isochronous finisher semaphore\n");
676		return;
677	}
678
679	// Create the isochronous finisher service thread
680	fFinishIsochronousThread = spawn_kernel_thread(FinishIsochronousThread,
681		"uhci isochronous finish thread", B_URGENT_DISPLAY_PRIORITY,
682		(void *)this);
683	resume_thread(fFinishIsochronousThread);
684
685	// Find the right interrupt vector, using MSIs if available.
686	fIRQ = fPCIInfo->u.h0.interrupt_line;
687		if (fIRQ == 0xFF)
688			fIRQ = 0;
689
690	if (fPci->get_msi_count(fDevice) >= 1) {
691		uint32 msiVector = 0;
692		if (fPci->configure_msi(fDevice, 1, &msiVector) == B_OK
693			&& fPci->enable_msi(fDevice) == B_OK) {
694			TRACE_ALWAYS("using message signaled interrupts\n");
695			fIRQ = msiVector;
696			fUseMSI = true;
697		}
698	}
699
700	if (fIRQ == 0) {
701		TRACE_MODULE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n",
702			fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function);
703		return;
704	}
705
706	// Install the interrupt handler
707	TRACE("installing interrupt handler\n");
708	install_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this, 0);
709
710	// Enable interrupts
711	fEnabledInterrupts = UHCI_USBSTS_USBINT | UHCI_USBSTS_ERRINT
712		| UHCI_USBSTS_HOSTERR | UHCI_USBSTS_HCPRERR | UHCI_USBSTS_HCHALT;
713	WriteReg16(UHCI_USBINTR, UHCI_USBINTR_CRC | UHCI_USBINTR_IOC
714		| UHCI_USBINTR_SHORT);
715
716	TRACE("UHCI host controller driver constructed\n");
717	fInitOK = true;
718}
719
720
721UHCI::~UHCI()
722{
723	int32 result = 0;
724	fStopThreads = true;
725	delete_sem(fFinishTransfersSem);
726	delete_sem(fCleanupSem);
727	delete_sem(fFinishIsochronousTransfersSem);
728	wait_for_thread(fFinishThread, &result);
729	wait_for_thread(fCleanupThread, &result);
730	wait_for_thread(fFinishIsochronousThread, &result);
731
732	remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this);
733
734	LockIsochronous();
735	isochronous_transfer_data *isoTransfer = fFirstIsochronousTransfer;
736	while (isoTransfer) {
737		isochronous_transfer_data *next = isoTransfer->link;
738		delete isoTransfer;
739		isoTransfer = next;
740	}
741	mutex_destroy(&fIsochronousLock);
742
743	Lock();
744	transfer_data *transfer = fFirstTransfer;
745	while (transfer) {
746		transfer->transfer->Finished(B_CANCELED, 0);
747		delete transfer->transfer;
748
749		transfer_data *next = transfer->link;
750		delete transfer;
751		transfer = next;
752	}
753
754	for (int32 i = 0; i < fQueueCount; i++)
755		delete fQueues[i];
756
757	delete [] fQueues;
758	delete [] fFrameBandwidth;
759	delete [] fFirstIsochronousDescriptor;
760	delete [] fLastIsochronousDescriptor;
761	delete fRootHub;
762	delete_area(fFrameArea);
763
764	if (fUseMSI) {
765		fPci->disable_msi(fDevice);
766		fPci->unconfigure_msi(fDevice);
767	}
768
769	Unlock();
770}
771
772
773status_t
774UHCI::Start()
775{
776	// Start the host controller, then start the Busmanager
777	TRACE("starting UHCI BusManager\n");
778	TRACE("usbcmd reg 0x%04x, usbsts reg 0x%04x\n",
779		ReadReg16(UHCI_USBCMD), ReadReg16(UHCI_USBSTS));
780
781	// Set the run bit in the command register
782	WriteReg16(UHCI_USBCMD, ReadReg16(UHCI_USBCMD) | UHCI_USBCMD_RS);
783
784	bool running = false;
785	for (int32 i = 0; i < 10; i++) {
786		uint16 status = ReadReg16(UHCI_USBSTS);
787		TRACE("current loop %" B_PRId32 ", status 0x%04x\n", i, status);
788
789		if (status & UHCI_USBSTS_HCHALT)
790			snooze(10000);
791		else {
792			running = true;
793			break;
794		}
795	}
796
797	if (!running) {
798		TRACE_ERROR("controller won't start running\n");
799		return B_ERROR;
800	}
801
802	fRootHubAddress = AllocateAddress();
803	fRootHub = new(std::nothrow) UHCIRootHub(RootObject(), fRootHubAddress);
804	if (!fRootHub) {
805		TRACE_ERROR("no memory to allocate root hub\n");
806		return B_NO_MEMORY;
807	}
808
809	if (fRootHub->InitCheck() < B_OK) {
810		TRACE_ERROR("root hub failed init check\n");
811		delete fRootHub;
812		return B_ERROR;
813	}
814
815	SetRootHub(fRootHub);
816
817	fRootHub->RegisterNode(Node());
818
819	TRACE("controller is started. status: %u curframe: %u\n",
820		ReadReg16(UHCI_USBSTS), ReadReg16(UHCI_FRNUM));
821	TRACE_ALWAYS("successfully started the controller\n");
822	return BusManager::Start();
823}
824
825
826status_t
827UHCI::SubmitTransfer(Transfer *transfer)
828{
829	// Short circuit the root hub
830	Pipe *pipe = transfer->TransferPipe();
831	if (pipe->DeviceAddress() == fRootHubAddress)
832		return fRootHub->ProcessTransfer(this, transfer);
833
834	TRACE("submit transfer called for device %d\n", pipe->DeviceAddress());
835	if (pipe->Type() & USB_OBJECT_CONTROL_PIPE)
836		return SubmitRequest(transfer);
837
838	// Process isochronous transfers
839#if 0
840	if (pipe->Type() & USB_OBJECT_ISO_PIPE)
841		return SubmitIsochronous(transfer);
842#else
843	// At present, isochronous transfers cause busylooping, and do not seem to work.
844	if (pipe->Type() & USB_OBJECT_ISO_PIPE)
845		return B_NOT_SUPPORTED;
846#endif
847
848	uhci_td *firstDescriptor = NULL;
849	uhci_qh *transferQueue = NULL;
850	status_t result = CreateFilledTransfer(transfer, &firstDescriptor,
851		&transferQueue);
852	if (result < B_OK)
853		return result;
854
855	Queue *queue = NULL;
856	if (pipe->Type() & USB_OBJECT_INTERRUPT_PIPE)
857		queue = fQueues[UHCI_INTERRUPT_QUEUE];
858	else
859		queue = fQueues[UHCI_BULK_QUEUE];
860
861	bool directionIn = (pipe->Direction() == Pipe::In);
862	result = AddPendingTransfer(transfer, queue, transferQueue,
863		firstDescriptor, firstDescriptor, directionIn);
864	if (result < B_OK) {
865		TRACE_ERROR("failed to add pending transfer\n");
866		FreeDescriptorChain(firstDescriptor);
867		FreeTransferQueue(transferQueue);
868		return result;
869	}
870
871	queue->AppendTransfer(transferQueue);
872	return B_OK;
873}
874
875
876status_t
877UHCI::StartDebugTransfer(Transfer *transfer)
878{
879	if ((transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) != 0)
880		return B_UNSUPPORTED;
881
882	static transfer_data transferData;
883	transferData.first_descriptor = NULL;
884	transferData.transfer_queue = NULL;
885	status_t result = CreateFilledTransfer(transfer,
886		&transferData.first_descriptor, &transferData.transfer_queue);
887	if (result < B_OK)
888		return result;
889
890	fQueues[UHCI_DEBUG_QUEUE]->AppendTransfer(transferData.transfer_queue,
891		false);
892
893	// we abuse the callback cookie to hold our transfer data
894	transfer->SetCallback(NULL, &transferData);
895	return B_OK;
896}
897
898
899status_t
900UHCI::CheckDebugTransfer(Transfer *transfer)
901{
902	bool transferOK = false;
903	bool transferError = false;
904	transfer_data *transferData = (transfer_data *)transfer->CallbackCookie();
905	uhci_td *descriptor = transferData->first_descriptor;
906
907	while (descriptor) {
908		uint32 status = descriptor->status;
909		if (status & TD_STATUS_ACTIVE)
910			break;
911
912		if (status & TD_ERROR_MASK) {
913			transferError = true;
914			break;
915		}
916
917		if ((descriptor->link_phy & TD_TERMINATE)
918			|| uhci_td_actual_length(descriptor)
919				< uhci_td_maximum_length(descriptor)) {
920			transferOK = true;
921			break;
922		}
923
924		descriptor = (uhci_td *)descriptor->link_log;
925	}
926
927	if (!transferOK && !transferError) {
928		spin(200);
929		return B_DEV_PENDING;
930	}
931
932	if (transferOK) {
933		uint8 lastDataToggle = 0;
934		if (transfer->TransferPipe()->Direction() == Pipe::In) {
935			// data to read out
936			generic_io_vec *vector = transfer->Vector();
937			size_t vectorCount = transfer->VectorCount();
938
939			ReadDescriptorChain(transferData->first_descriptor,
940				vector, vectorCount, transfer->IsPhysical(), &lastDataToggle);
941		} else {
942			// read the actual length that was sent
943			ReadActualLength(transferData->first_descriptor, &lastDataToggle);
944		}
945
946		transfer->TransferPipe()->SetDataToggle(lastDataToggle == 0);
947	}
948
949	fQueues[UHCI_DEBUG_QUEUE]->RemoveTransfer(transferData->transfer_queue,
950		false);
951	FreeDescriptorChain(transferData->first_descriptor);
952	FreeTransferQueue(transferData->transfer_queue);
953	return transferOK ? B_OK : B_IO_ERROR;
954}
955
956
957void
958UHCI::CancelDebugTransfer(Transfer *transfer)
959{
960	transfer_data *transferData = (transfer_data *)transfer->CallbackCookie();
961
962	// clear the active bit so the descriptors are canceled
963	uhci_td *descriptor = transferData->first_descriptor;
964	while (descriptor) {
965		descriptor->status &= ~TD_STATUS_ACTIVE;
966		descriptor = (uhci_td *)descriptor->link_log;
967	}
968
969	transfer->Finished(B_CANCELED, 0);
970
971	// dequeue and free resources
972	fQueues[UHCI_DEBUG_QUEUE]->RemoveTransfer(transferData->transfer_queue,
973		false);
974	FreeDescriptorChain(transferData->first_descriptor);
975	FreeTransferQueue(transferData->transfer_queue);
976	// TODO: [bonefish] The Free*() calls cause "PMA: provided address resulted
977	// in invalid index" to be printed, so apparently something is not right.
978	// Though I have not clue what. This is the same cleanup code as in
979	// CheckDebugTransfer() that should undo the CreateFilledTransfer() from
980	// StartDebugTransfer().
981}
982
983
984status_t
985UHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
986{
987	if (pipe->Type() & USB_OBJECT_ISO_PIPE)
988		return CancelQueuedIsochronousTransfers(pipe, force);
989
990	if (!Lock())
991		return B_ERROR;
992
993	struct transfer_entry {
994		Transfer *			transfer;
995		transfer_entry *	next;
996	};
997
998	transfer_entry *list = NULL;
999	transfer_data *current = fFirstTransfer;
1000	while (current) {
1001		if (current->transfer && current->transfer->TransferPipe() == pipe) {
1002			// clear the active bit so the descriptors are canceled
1003			uhci_td *descriptor = current->first_descriptor;
1004			while (descriptor) {
1005				descriptor->status &= ~TD_STATUS_ACTIVE;
1006				descriptor = (uhci_td *)descriptor->link_log;
1007			}
1008
1009			if (!force) {
1010				// if the transfer is canceled by force, the one causing the
1011				// cancel is probably not the one who initiated the transfer
1012				// and the callback is likely not safe anymore
1013				transfer_entry *entry
1014					= (transfer_entry *)malloc(sizeof(transfer_entry));
1015				if (entry != NULL) {
1016					entry->transfer = current->transfer;
1017					current->transfer = NULL;
1018					entry->next = list;
1019					list = entry;
1020				}
1021			}
1022
1023			current->canceled = true;
1024		}
1025		current = current->link;
1026	}
1027
1028	Unlock();
1029
1030	while (list != NULL) {
1031		transfer_entry *next = list->next;
1032		list->transfer->Finished(B_CANCELED, 0);
1033		delete list->transfer;
1034		free(list);
1035		list = next;
1036	}
1037
1038	// wait for any transfers that might have made it before canceling
1039	while (fProcessingPipe == pipe)
1040		snooze(1000);
1041
1042	// notify the finisher so it can clean up the canceled transfers
1043	release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
1044	return B_OK;
1045}
1046
1047
1048status_t
1049UHCI::CancelQueuedIsochronousTransfers(Pipe *pipe, bool force)
1050{
1051	isochronous_transfer_data *current = fFirstIsochronousTransfer;
1052
1053	while (current) {
1054		if (current->transfer->TransferPipe() == pipe) {
1055			int32 packetCount
1056				= current->transfer->IsochronousData()->packet_count;
1057			// Set the active bit off on every descriptor in order to prevent
1058			// the controller from processing them. Then set off the is_active
1059			// field of the transfer in order to make the finisher thread skip
1060			// the transfer. The FinishIsochronousThread will do the rest.
1061			for (int32 i = 0; i < packetCount; i++)
1062				current->descriptors[i]->status &= ~TD_STATUS_ACTIVE;
1063
1064			// TODO: Use the force paramater in order to avoid calling
1065			// invalid callbacks
1066			current->is_active = false;
1067		}
1068
1069		current = current->link;
1070	}
1071
1072	TRACE_ERROR("no isochronous transfer found!\n");
1073	return B_ERROR;
1074}
1075
1076
1077status_t
1078UHCI::SubmitRequest(Transfer *transfer)
1079{
1080	Pipe *pipe = transfer->TransferPipe();
1081	usb_request_data *requestData = transfer->RequestData();
1082	bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0;
1083
1084	uhci_td *setupDescriptor = CreateDescriptor(pipe, TD_TOKEN_SETUP,
1085		sizeof(usb_request_data));
1086
1087	uhci_td *statusDescriptor = CreateDescriptor(pipe,
1088		directionIn ? TD_TOKEN_OUT : TD_TOKEN_IN, 0);
1089
1090	if (!setupDescriptor || !statusDescriptor) {
1091		TRACE_ERROR("failed to allocate descriptors\n");
1092		FreeDescriptor(setupDescriptor);
1093		FreeDescriptor(statusDescriptor);
1094		return B_NO_MEMORY;
1095	}
1096
1097	generic_io_vec vector;
1098	vector.base = (generic_addr_t)requestData;
1099	vector.length = sizeof(usb_request_data);
1100	WriteDescriptorChain(setupDescriptor, &vector, 1, false);
1101
1102	statusDescriptor->status |= TD_CONTROL_IOC;
1103	statusDescriptor->token |= TD_TOKEN_DATA1;
1104	statusDescriptor->link_phy = TD_TERMINATE;
1105	statusDescriptor->link_log = NULL;
1106
1107	uhci_td *dataDescriptor = NULL;
1108	if (transfer->VectorCount() > 0) {
1109		uhci_td *lastDescriptor = NULL;
1110		status_t result = CreateDescriptorChain(pipe, &dataDescriptor,
1111			&lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT,
1112			transfer->FragmentLength());
1113
1114		if (result < B_OK) {
1115			FreeDescriptor(setupDescriptor);
1116			FreeDescriptor(statusDescriptor);
1117			return result;
1118		}
1119
1120		if (!directionIn) {
1121			WriteDescriptorChain(dataDescriptor, transfer->Vector(),
1122				transfer->VectorCount(), transfer->IsPhysical());
1123		}
1124
1125		LinkDescriptors(setupDescriptor, dataDescriptor);
1126		LinkDescriptors(lastDescriptor, statusDescriptor);
1127	} else {
1128		// Link transfer and status descriptors directly
1129		LinkDescriptors(setupDescriptor, statusDescriptor);
1130	}
1131
1132	Queue *queue = NULL;
1133	if (pipe->Speed() == USB_SPEED_LOWSPEED)
1134		queue = fQueues[UHCI_LOW_SPEED_CONTROL_QUEUE];
1135	else
1136		queue = fQueues[UHCI_FULL_SPEED_CONTROL_QUEUE];
1137
1138	uhci_qh *transferQueue = CreateTransferQueue(setupDescriptor);
1139	status_t result = AddPendingTransfer(transfer, queue, transferQueue,
1140		setupDescriptor, dataDescriptor, directionIn);
1141	if (result < B_OK) {
1142		TRACE_ERROR("failed to add pending transfer\n");
1143		FreeDescriptorChain(setupDescriptor);
1144		FreeTransferQueue(transferQueue);
1145		return result;
1146	}
1147
1148	queue->AppendTransfer(transferQueue);
1149	return B_OK;
1150}
1151
1152
1153status_t
1154UHCI::AddPendingTransfer(Transfer *transfer, Queue *queue,
1155	uhci_qh *transferQueue, uhci_td *firstDescriptor, uhci_td *dataDescriptor,
1156	bool directionIn)
1157{
1158	if (!transfer || !queue || !transferQueue || !firstDescriptor)
1159		return B_BAD_VALUE;
1160
1161	transfer_data *data = new(std::nothrow) transfer_data;
1162	if (!data)
1163		return B_NO_MEMORY;
1164
1165	status_t result = transfer->InitKernelAccess();
1166	if (result < B_OK) {
1167		delete data;
1168		return result;
1169	}
1170
1171	data->transfer = transfer;
1172	data->queue = queue;
1173	data->transfer_queue = transferQueue;
1174	data->first_descriptor = firstDescriptor;
1175	data->data_descriptor = dataDescriptor;
1176	data->incoming = directionIn;
1177	data->canceled = false;
1178	data->link = NULL;
1179
1180	if (!Lock()) {
1181		delete data;
1182		return B_ERROR;
1183	}
1184
1185	// We do not support queuing other transfers in tandem with a fragmented one.
1186	transfer_data *it = fFirstTransfer;
1187	while (it) {
1188		if (it->transfer && it->transfer->TransferPipe() == transfer->TransferPipe()
1189				&& it->transfer->IsFragmented()) {
1190			TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n");
1191
1192			Unlock();
1193			delete data;
1194			return B_DEV_RESOURCE_CONFLICT;
1195		}
1196
1197		it = it->link;
1198	}
1199
1200	if (fLastTransfer)
1201		fLastTransfer->link = data;
1202	if (!fFirstTransfer)
1203		fFirstTransfer = data;
1204
1205	fLastTransfer = data;
1206	Unlock();
1207	return B_OK;
1208}
1209
1210
1211status_t
1212UHCI::AddPendingIsochronousTransfer(Transfer *transfer, uhci_td **isoRequest,
1213	bool directionIn)
1214{
1215	if (!transfer || !isoRequest)
1216		return B_BAD_VALUE;
1217
1218	isochronous_transfer_data *data
1219		= new(std::nothrow) isochronous_transfer_data;
1220	if (!data)
1221		return B_NO_MEMORY;
1222
1223	status_t result = transfer->InitKernelAccess();
1224	if (result < B_OK) {
1225		delete data;
1226		return result;
1227	}
1228
1229	data->transfer = transfer;
1230	data->descriptors = isoRequest;
1231	data->last_to_process = transfer->IsochronousData()->packet_count - 1;
1232	data->incoming = directionIn;
1233	data->is_active = true;
1234	data->link = NULL;
1235
1236	// Put in the isochronous transfer list
1237	if (!LockIsochronous()) {
1238		delete data;
1239		return B_ERROR;
1240	}
1241
1242	if (fLastIsochronousTransfer)
1243		fLastIsochronousTransfer->link = data;
1244	if (!fFirstIsochronousTransfer)
1245		fFirstIsochronousTransfer = data;
1246
1247	fLastIsochronousTransfer = data;
1248	UnlockIsochronous();
1249	return B_OK;
1250}
1251
1252
1253status_t
1254UHCI::SubmitIsochronous(Transfer *transfer)
1255{
1256	Pipe *pipe = transfer->TransferPipe();
1257	bool directionIn = (pipe->Direction() == Pipe::In);
1258	usb_isochronous_data *isochronousData = transfer->IsochronousData();
1259	size_t packetSize = transfer->DataLength();
1260	size_t restSize = packetSize % isochronousData->packet_count;
1261	packetSize /= isochronousData->packet_count;
1262	uint16 currentFrame;
1263
1264	if (packetSize > pipe->MaxPacketSize()) {
1265		TRACE_ERROR("isochronous packetSize is bigger than pipe MaxPacketSize\n");
1266		return B_BAD_VALUE;
1267	}
1268
1269	// Ignore the fact that the last descriptor might need less bandwidth.
1270	// The overhead is not worthy.
1271	uint16 bandwidth = transfer->Bandwidth() / isochronousData->packet_count;
1272
1273	TRACE("isochronous transfer descriptor bandwidth %d\n", bandwidth);
1274
1275	// The following holds the list of transfer descriptor of the
1276	// isochronous request. It is used to quickly remove all the isochronous
1277	// descriptors from the frame list, as descriptors are not link to each
1278	// other in a queue like for every other transfer.
1279	uhci_td **isoRequest
1280		= new(std::nothrow) uhci_td *[isochronousData->packet_count];
1281	if (isoRequest == NULL) {
1282		TRACE("failed to create isoRequest array!\n");
1283		return B_NO_MEMORY;
1284	}
1285
1286	// Create the list of transfer descriptors
1287	for (uint32 i = 0; i < (isochronousData->packet_count - 1); i++) {
1288		isoRequest[i] = CreateDescriptor(pipe,
1289			directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, packetSize);
1290		// If we ran out of memory, clean up and return
1291		if (isoRequest[i] == NULL) {
1292			for (uint32 j = 0; j < i; j++)
1293				FreeDescriptor(isoRequest[j]);
1294			delete [] isoRequest;
1295			return B_NO_MEMORY;
1296		}
1297		// Make sure data toggle is set to zero
1298		isoRequest[i]->token &= ~TD_TOKEN_DATA1;
1299	}
1300
1301	// Create the last transfer descriptor which should be of smaller size
1302	// and set the IOC bit
1303	isoRequest[isochronousData->packet_count - 1] = CreateDescriptor(pipe,
1304		directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT,
1305		(restSize) ? restSize : packetSize);
1306	// If we are that unlucky...
1307	if (!isoRequest[isochronousData->packet_count - 1]) {
1308		for (uint32 i = 0; i < (isochronousData->packet_count - 2); i++)
1309			FreeDescriptor(isoRequest[i]);
1310		delete [] isoRequest;
1311		return B_NO_MEMORY;
1312	}
1313	isoRequest[isochronousData->packet_count - 1]->token &= ~TD_TOKEN_DATA1;
1314
1315	// If direction is out set every descriptor data
1316	if (!directionIn) {
1317		generic_io_vec *vector = transfer->Vector();
1318		WriteIsochronousDescriptorChain(isoRequest,
1319			isochronousData->packet_count, vector);
1320	}
1321
1322	TRACE("isochronous submitted size=%ld bytes, TDs=%" B_PRId32 ", "
1323		"packetSize=%ld, restSize=%ld\n", transfer->DataLength(),
1324		isochronousData->packet_count, packetSize, restSize);
1325
1326	// Find the entry where to start inserting the first Isochronous descriptor
1327	if (isochronousData->flags & USB_ISO_ASAP ||
1328		isochronousData->starting_frame_number == NULL) {
1329		// find the first available frame with enough bandwidth.
1330		// This should always be the case, as defining the starting frame
1331		// number in the driver makes no sense for many reason, one of which
1332		// is that frame numbers value are host controller specific, and the
1333		// driver does not know which host controller is running.
1334		currentFrame = ReadReg16(UHCI_FRNUM);
1335
1336		// Make sure that:
1337		// 1. We are at least 5ms ahead the controller
1338		// 2. We stay in the range 0-1023
1339		// 3. There is enough bandwidth in the first entry
1340		currentFrame = (currentFrame + 5) % NUMBER_OF_FRAMES;
1341	} else {
1342		// Find out if the frame number specified has enough bandwidth,
1343		// otherwise find the first next available frame with enough bandwidth
1344		currentFrame = *isochronousData->starting_frame_number;
1345	}
1346
1347	// Find the first entry with enough bandwidth
1348	// TODO: should we also check the bandwidth of the following packet_count frames?
1349	uint16 startSeekingFromFrame = currentFrame;
1350	while (fFrameBandwidth[currentFrame] < bandwidth) {
1351		currentFrame = (currentFrame + 1) % NUMBER_OF_FRAMES;
1352		if (currentFrame == startSeekingFromFrame) {
1353			TRACE_ERROR("not enough bandwidth to queue the isochronous request");
1354			for (uint32 i = 0; i < isochronousData->packet_count; i++)
1355				FreeDescriptor(isoRequest[i]);
1356			delete [] isoRequest;
1357		return B_ERROR;
1358		}
1359	}
1360
1361	if (isochronousData->starting_frame_number)
1362		*isochronousData->starting_frame_number = currentFrame;
1363
1364	// Add transfer to the list
1365	status_t result = AddPendingIsochronousTransfer(transfer, isoRequest,
1366		directionIn);
1367	if (result < B_OK) {
1368		TRACE_ERROR("failed to add pending isochronous transfer\n");
1369		for (uint32 i = 0; i < isochronousData->packet_count; i++)
1370			FreeDescriptor(isoRequest[i]);
1371		delete [] isoRequest;
1372		return result;
1373	}
1374
1375	TRACE("appended isochronous transfer by starting at frame number %d\n",
1376		currentFrame);
1377
1378	// Insert the Transfer Descriptor by starting at
1379	// the starting_frame_number entry
1380	// TODO: We don't consider bInterval, and assume it's 1!
1381	for (uint32 i = 0; i < isochronousData->packet_count; i++) {
1382		result = LinkIsochronousDescriptor(isoRequest[i], currentFrame);
1383		if (result < B_OK) {
1384			TRACE_ERROR("failed to add pending isochronous transfer\n");
1385			for (uint32 i = 0; i < isochronousData->packet_count; i++)
1386				FreeDescriptor(isoRequest[i]);
1387			delete [] isoRequest;
1388			return result;
1389		}
1390
1391		fFrameBandwidth[currentFrame] -= bandwidth;
1392		currentFrame = (currentFrame + 1) % NUMBER_OF_FRAMES;
1393	}
1394
1395	// Wake up the isochronous finisher thread
1396	release_sem_etc(fFinishIsochronousTransfersSem, 1, B_DO_NOT_RESCHEDULE);
1397
1398	return B_OK;
1399}
1400
1401
1402isochronous_transfer_data *
1403UHCI::FindIsochronousTransfer(uhci_td *descriptor)
1404{
1405	// Simply check every last descriptor of the isochronous transfer list
1406	if (LockIsochronous()) {
1407		isochronous_transfer_data *transfer = fFirstIsochronousTransfer;
1408		if (transfer) {
1409			while (transfer->descriptors[transfer->last_to_process]
1410				!= descriptor) {
1411				transfer = transfer->link;
1412				if (!transfer)
1413					break;
1414			}
1415		}
1416		UnlockIsochronous();
1417		return transfer;
1418	}
1419	return NULL;
1420}
1421
1422
1423status_t
1424UHCI::LinkIsochronousDescriptor(uhci_td *descriptor, uint16 frame)
1425{
1426	// The transfer descriptor is appended to the last
1427	// existing isochronous transfer descriptor (if any)
1428	// in that frame.
1429	if (LockIsochronous()) {
1430		if (!fFirstIsochronousDescriptor[frame]) {
1431			// Insert the transfer descriptor in the first position
1432			fFrameList[frame] = descriptor->this_phy & ~FRAMELIST_NEXT_IS_QH;
1433			fFirstIsochronousDescriptor[frame] = descriptor;
1434			fLastIsochronousDescriptor[frame] = descriptor;
1435		} else {
1436			// Append to the last transfer descriptor
1437			fLastIsochronousDescriptor[frame]->link_log = descriptor;
1438			fLastIsochronousDescriptor[frame]->link_phy
1439				= descriptor->this_phy & ~TD_NEXT_IS_QH;
1440			fLastIsochronousDescriptor[frame] = descriptor;
1441		}
1442
1443		descriptor->link_phy
1444			= fQueues[UHCI_INTERRUPT_QUEUE]->PhysicalAddress() | TD_NEXT_IS_QH;
1445		UnlockIsochronous();
1446		return B_OK;
1447	}
1448	return B_ERROR;
1449}
1450
1451
1452uhci_td *
1453UHCI::UnlinkIsochronousDescriptor(uint16 frame)
1454{
1455	// We always unlink from the top
1456	if (LockIsochronous()) {
1457		uhci_td *descriptor = fFirstIsochronousDescriptor[frame];
1458		if (descriptor) {
1459			// The descriptor will be freed later.
1460			fFrameList[frame] = descriptor->link_phy;
1461			if (descriptor->link_log) {
1462				fFirstIsochronousDescriptor[frame]
1463					= (uhci_td *)descriptor->link_log;
1464			} else {
1465				fFirstIsochronousDescriptor[frame] = NULL;
1466				fLastIsochronousDescriptor[frame] = NULL;
1467			}
1468		}
1469		UnlockIsochronous();
1470		return descriptor;
1471	}
1472	return NULL;
1473}
1474
1475
1476int32
1477UHCI::FinishThread(void *data)
1478{
1479	((UHCI *)data)->FinishTransfers();
1480	return B_OK;
1481}
1482
1483
1484void
1485UHCI::FinishTransfers()
1486{
1487	while (!fStopThreads) {
1488		if (acquire_sem(fFinishTransfersSem) < B_OK)
1489			continue;
1490
1491		// eat up sems that have been released by multiple interrupts
1492		int32 semCount = 0;
1493		get_sem_count(fFinishTransfersSem, &semCount);
1494		if (semCount > 0)
1495			acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
1496
1497		if (!Lock())
1498			continue;
1499
1500		TRACE("finishing transfers (first transfer: 0x%08lx; last"
1501			" transfer: 0x%08lx)\n", (addr_t)fFirstTransfer,
1502			(addr_t)fLastTransfer);
1503		transfer_data *lastTransfer = NULL;
1504		transfer_data *transfer = fFirstTransfer;
1505		Unlock();
1506
1507		while (transfer) {
1508			bool transferDone = false;
1509			uhci_td *descriptor = transfer->first_descriptor;
1510			status_t callbackStatus = B_OK;
1511
1512			while (descriptor) {
1513				uint32 status = descriptor->status;
1514				if (status & TD_STATUS_ACTIVE) {
1515					// still in progress
1516					TRACE("td (0x%08" B_PRIx32 ") still active\n",
1517						descriptor->this_phy);
1518					break;
1519				}
1520
1521				if (status & TD_ERROR_MASK) {
1522					// an error occured
1523					TRACE_ERROR("td (0x%08" B_PRIx32 ") error: status: 0x%08"
1524						B_PRIx32 "; token: 0x%08" B_PRIx32 ";\n",
1525						descriptor->this_phy, status, descriptor->token);
1526
1527					uint8 errorCount = status >> TD_ERROR_COUNT_SHIFT;
1528					errorCount &= TD_ERROR_COUNT_MASK;
1529					if (errorCount == 0) {
1530						// the error counter counted down to zero, report why
1531						int32 reasons = 0;
1532						if (status & TD_STATUS_ERROR_BUFFER) {
1533							callbackStatus = transfer->incoming ? B_DEV_WRITE_ERROR : B_DEV_READ_ERROR;
1534							reasons++;
1535						}
1536						if (status & TD_STATUS_ERROR_TIMEOUT) {
1537							callbackStatus = transfer->incoming ? B_DEV_CRC_ERROR : B_TIMED_OUT;
1538							reasons++;
1539						}
1540						if (status & TD_STATUS_ERROR_NAK) {
1541							callbackStatus = B_DEV_UNEXPECTED_PID;
1542							reasons++;
1543						}
1544						if (status & TD_STATUS_ERROR_BITSTUFF) {
1545							callbackStatus = B_DEV_CRC_ERROR;
1546							reasons++;
1547						}
1548
1549						if (reasons > 1)
1550							callbackStatus = B_DEV_MULTIPLE_ERRORS;
1551					} else if (status & TD_STATUS_ERROR_BABBLE) {
1552						// there is a babble condition
1553						callbackStatus = transfer->incoming ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN;
1554					} else {
1555						// if the error counter didn't count down to zero
1556						// and there was no babble, then this halt was caused
1557						// by a stall handshake
1558						callbackStatus = B_DEV_STALLED;
1559					}
1560
1561					transferDone = true;
1562					break;
1563				}
1564
1565				if ((descriptor->link_phy & TD_TERMINATE)
1566					|| ((descriptor->status & TD_CONTROL_SPD) != 0
1567						&& uhci_td_actual_length(descriptor)
1568							< uhci_td_maximum_length(descriptor))) {
1569					// all descriptors are done, or we have a short packet
1570					TRACE("td (0x%08" B_PRIx32 ") ok\n", descriptor->this_phy);
1571					callbackStatus = B_OK;
1572					transferDone = true;
1573					break;
1574				}
1575
1576				descriptor = (uhci_td *)descriptor->link_log;
1577			}
1578
1579			if (!transferDone) {
1580				lastTransfer = transfer;
1581				transfer = transfer->link;
1582				continue;
1583			}
1584
1585			// remove the transfer from the list first so we are sure
1586			// it doesn't get canceled while we still process it
1587			transfer_data *next = transfer->link;
1588			if (Lock()) {
1589				if (lastTransfer)
1590					lastTransfer->link = transfer->link;
1591
1592				if (transfer == fFirstTransfer)
1593					fFirstTransfer = transfer->link;
1594				if (transfer == fLastTransfer)
1595					fLastTransfer = lastTransfer;
1596
1597				// store the currently processing pipe here so we can wait
1598				// in cancel if we are processing something on the target pipe
1599				if (!transfer->canceled)
1600					fProcessingPipe = transfer->transfer->TransferPipe();
1601
1602				transfer->link = NULL;
1603				Unlock();
1604			}
1605
1606			// if canceled the callback has already been called
1607			if (!transfer->canceled) {
1608				size_t actualLength = 0;
1609				if (callbackStatus == B_OK) {
1610					uint8 lastDataToggle = 0;
1611					if (transfer->data_descriptor && transfer->incoming) {
1612						// data to read out
1613						generic_io_vec *vector = transfer->transfer->Vector();
1614						size_t vectorCount = transfer->transfer->VectorCount();
1615
1616						transfer->transfer->PrepareKernelAccess();
1617						actualLength = ReadDescriptorChain(
1618							transfer->data_descriptor,
1619							vector, vectorCount, transfer->transfer->IsPhysical(),
1620							&lastDataToggle);
1621					} else if (transfer->data_descriptor) {
1622						// read the actual length that was sent
1623						actualLength = ReadActualLength(
1624							transfer->data_descriptor, &lastDataToggle);
1625					}
1626
1627					transfer->transfer->TransferPipe()->SetDataToggle(lastDataToggle == 0);
1628
1629					if (transfer->transfer->IsFragmented()) {
1630						// this transfer may still have data left
1631						TRACE("advancing fragmented transfer\n");
1632						transfer->transfer->AdvanceByFragment(actualLength);
1633						if (transfer->transfer->FragmentLength() > 0) {
1634							TRACE("still %ld bytes left on transfer\n",
1635								transfer->transfer->FragmentLength());
1636
1637							Transfer *resubmit = transfer->transfer;
1638
1639							// free the used descriptors
1640							transfer->queue->RemoveTransfer(
1641								transfer->transfer_queue);
1642							AddToFreeList(transfer);
1643
1644							// resubmit the advanced transfer so the rest
1645							// of the buffers are transmitted over the bus
1646							resubmit->PrepareKernelAccess();
1647							if (SubmitTransfer(resubmit) != B_OK)
1648								resubmit->Finished(B_ERROR, 0);
1649
1650							transfer = next;
1651							continue;
1652						}
1653
1654						// the transfer is done, but we already set the
1655						// actualLength with AdvanceByFragment()
1656						actualLength = 0;
1657					}
1658				}
1659
1660				transfer->transfer->Finished(callbackStatus, actualLength);
1661				fProcessingPipe = NULL;
1662			}
1663
1664			// remove and free the hardware queue and its descriptors
1665			transfer->queue->RemoveTransfer(transfer->transfer_queue);
1666			delete transfer->transfer;
1667			AddToFreeList(transfer);
1668			transfer = next;
1669		}
1670	}
1671}
1672
1673
1674void
1675UHCI::AddToFreeList(transfer_data *transfer)
1676{
1677	transfer->free_after_frame = ReadReg16(UHCI_FRNUM);
1678	if (!Lock())
1679		return;
1680
1681	transfer->link = fFreeList;
1682	fFreeList = transfer;
1683	Unlock();
1684
1685	if (atomic_add(&fCleanupCount, 1) == 0)
1686		release_sem(fCleanupSem);
1687}
1688
1689
1690int32
1691UHCI::CleanupThread(void *data)
1692{
1693	((UHCI *)data)->Cleanup();
1694	return B_OK;
1695}
1696
1697
1698void
1699UHCI::Cleanup()
1700{
1701	while (!fStopThreads) {
1702		if (acquire_sem(fCleanupSem) != B_OK)
1703			continue;
1704
1705		bigtime_t nextTime = system_time() + 1000;
1706		while (atomic_get(&fCleanupCount) != 0) {
1707			// wait for the frame to pass
1708			snooze_until(nextTime, B_SYSTEM_TIMEBASE);
1709			nextTime += 1000;
1710
1711			if (!Lock())
1712				continue;
1713
1714			// find the first entry we may free
1715			transfer_data **link = &fFreeList;
1716			transfer_data *transfer = fFreeList;
1717			uint16 frameNumber = ReadReg16(UHCI_FRNUM);
1718			while (transfer) {
1719				if (transfer->free_after_frame != frameNumber) {
1720					*link = NULL;
1721					break;
1722				}
1723
1724				link = &transfer->link;
1725				transfer = transfer->link;
1726			}
1727
1728			Unlock();
1729
1730			// the transfers below this one are all freeable
1731			while (transfer) {
1732				transfer_data *next = transfer->link;
1733				FreeDescriptorChain(transfer->first_descriptor);
1734				FreeTransferQueue(transfer->transfer_queue);
1735				delete transfer;
1736				atomic_add(&fCleanupCount, -1);
1737				transfer = next;
1738			}
1739		}
1740	}
1741}
1742
1743
1744int32
1745UHCI::FinishIsochronousThread(void *data)
1746{
1747       ((UHCI *)data)->FinishIsochronousTransfers();
1748       return B_OK;
1749}
1750
1751
1752void
1753UHCI::FinishIsochronousTransfers()
1754{
1755	/* This thread stays one position behind the controller and processes every
1756	 * isochronous descriptor. Once it finds the last isochronous descriptor
1757	 * of a transfer, it processes the entire transfer.
1758	 */
1759
1760	while (!fStopThreads) {
1761		// Go to sleep if there are not isochronous transfer to process
1762		if (acquire_sem(fFinishIsochronousTransfersSem) < B_OK)
1763			return;
1764
1765		bool transferDone = false;
1766		uint16 currentFrame = ReadReg16(UHCI_FRNUM);
1767
1768		// Process the frame list until one transfer is processed
1769		while (!transferDone) {
1770			// wait 1ms in order to be sure to be one position behind
1771			// the controller
1772			if (currentFrame == ReadReg16(UHCI_FRNUM))
1773				snooze(1000);
1774
1775			// Process the frame till it has isochronous descriptors in it.
1776			while (!(fFrameList[currentFrame] & FRAMELIST_NEXT_IS_QH)) {
1777				uhci_td *current = UnlinkIsochronousDescriptor(currentFrame);
1778
1779				// Process the transfer if we found the last descriptor
1780				isochronous_transfer_data *transfer
1781					= FindIsochronousTransfer(current);
1782					// Process the descriptors only if it is still active and
1783					// belongs to an inbound transfer. If the transfer is not
1784					// active, it means the request has been removed, so simply
1785					// remove the descriptors.
1786				if (transfer && transfer->is_active) {
1787					if (current->token & TD_TOKEN_IN) {
1788						generic_io_vec *vector = transfer->transfer->Vector();
1789						transfer->transfer->PrepareKernelAccess();
1790						ReadIsochronousDescriptorChain(transfer, vector);
1791					}
1792
1793					// Remove the transfer
1794					if (LockIsochronous()) {
1795						if (transfer == fFirstIsochronousTransfer) {
1796							fFirstIsochronousTransfer = transfer->link;
1797							if (transfer == fLastIsochronousTransfer)
1798								fLastIsochronousTransfer = NULL;
1799						} else {
1800							isochronous_transfer_data *temp
1801								= fFirstIsochronousTransfer;
1802							while (transfer != temp->link)
1803								temp = temp->link;
1804
1805							if (transfer == fLastIsochronousTransfer)
1806								fLastIsochronousTransfer = temp;
1807							temp->link = temp->link->link;
1808						}
1809						UnlockIsochronous();
1810					}
1811
1812					transfer->transfer->Finished(B_OK, 0);
1813
1814					uint32 packetCount =
1815						transfer->transfer->IsochronousData()->packet_count;
1816					for (uint32 i = 0; i < packetCount; i++)
1817						FreeDescriptor(transfer->descriptors[i]);
1818
1819					delete [] transfer->descriptors;
1820					delete transfer->transfer;
1821					delete transfer;
1822					transferDone = true;
1823				}
1824			}
1825
1826			// Make sure to reset the frame bandwidth
1827			fFrameBandwidth[currentFrame] = MAX_AVAILABLE_BANDWIDTH;
1828			currentFrame = (currentFrame + 1) % NUMBER_OF_FRAMES;
1829		}
1830	}
1831}
1832
1833
1834void
1835UHCI::GlobalReset()
1836{
1837	uint8 sofValue = ReadReg8(UHCI_SOFMOD);
1838
1839	WriteReg16(UHCI_USBCMD, UHCI_USBCMD_GRESET);
1840	snooze(100000);
1841	WriteReg16(UHCI_USBCMD, 0);
1842	snooze(10000);
1843
1844	WriteReg8(UHCI_SOFMOD, sofValue);
1845}
1846
1847
1848status_t
1849UHCI::ControllerReset()
1850{
1851	WriteReg16(UHCI_USBCMD, UHCI_USBCMD_HCRESET);
1852
1853	int32 tries = 5;
1854	while (ReadReg16(UHCI_USBCMD) & UHCI_USBCMD_HCRESET) {
1855		snooze(10000);
1856		if (tries-- < 0)
1857			return B_ERROR;
1858	}
1859
1860	return B_OK;
1861}
1862
1863
1864status_t
1865UHCI::GetPortStatus(uint8 index, usb_port_status *status)
1866{
1867	if (index > 1)
1868		return B_BAD_INDEX;
1869
1870	status->status = status->change = 0;
1871	uint16 portStatus = ReadReg16(UHCI_PORTSC1 + index * 2);
1872
1873	// build the status
1874	if (portStatus & UHCI_PORTSC_CURSTAT)
1875		status->status |= PORT_STATUS_CONNECTION;
1876	if (portStatus & UHCI_PORTSC_ENABLED)
1877		status->status |= PORT_STATUS_ENABLE;
1878	if (portStatus & UHCI_PORTSC_RESET)
1879		status->status |= PORT_STATUS_RESET;
1880	if (portStatus & UHCI_PORTSC_LOWSPEED)
1881		status->status |= PORT_STATUS_LOW_SPEED;
1882
1883	// build the change
1884	if (portStatus & UHCI_PORTSC_STATCHA)
1885		status->change |= PORT_STATUS_CONNECTION;
1886	if (portStatus & UHCI_PORTSC_ENABCHA)
1887		status->change |= PORT_STATUS_ENABLE;
1888
1889	// ToDo: work out suspended/resume
1890
1891	// there are no bits to indicate reset change
1892	if (fPortResetChange & (1 << index))
1893		status->change |= PORT_STATUS_RESET;
1894
1895	// the port is automagically powered on
1896	status->status |= PORT_STATUS_POWER;
1897	return B_OK;
1898}
1899
1900
1901status_t
1902UHCI::SetPortFeature(uint8 index, uint16 feature)
1903{
1904	if (index > 1)
1905		return B_BAD_INDEX;
1906
1907	switch (feature) {
1908		case PORT_RESET:
1909			return ResetPort(index);
1910
1911		case PORT_POWER:
1912			// the ports are automatically powered
1913			return B_OK;
1914	}
1915
1916	return B_BAD_VALUE;
1917}
1918
1919
1920status_t
1921UHCI::ClearPortFeature(uint8 index, uint16 feature)
1922{
1923	if (index > 1)
1924		return B_BAD_INDEX;
1925
1926	uint32 portRegister = UHCI_PORTSC1 + index * 2;
1927	uint16 portStatus = ReadReg16(portRegister) & UHCI_PORTSC_DATAMASK;
1928
1929	switch (feature) {
1930		case C_PORT_RESET:
1931			fPortResetChange &= ~(1 << index);
1932			return B_OK;
1933
1934		case C_PORT_CONNECTION:
1935			WriteReg16(portRegister, portStatus | UHCI_PORTSC_STATCHA);
1936			return B_OK;
1937
1938		case C_PORT_ENABLE:
1939			WriteReg16(portRegister, portStatus | UHCI_PORTSC_ENABCHA);
1940			return B_OK;
1941	}
1942
1943	return B_BAD_VALUE;
1944}
1945
1946
1947status_t
1948UHCI::ResetPort(uint8 index)
1949{
1950	if (index > 1)
1951		return B_BAD_INDEX;
1952
1953	TRACE("reset port %d\n", index);
1954
1955	uint32 port = UHCI_PORTSC1 + index * 2;
1956	uint16 status = ReadReg16(port);
1957	status &= UHCI_PORTSC_DATAMASK;
1958	WriteReg16(port, status | UHCI_PORTSC_RESET);
1959	snooze(250000);
1960
1961	status = ReadReg16(port);
1962	status &= UHCI_PORTSC_DATAMASK;
1963	WriteReg16(port, status & ~UHCI_PORTSC_RESET);
1964	snooze(1000);
1965
1966	for (int32 i = 10; i > 0; i--) {
1967		// try to enable the port
1968		status = ReadReg16(port);
1969		status &= UHCI_PORTSC_DATAMASK;
1970		WriteReg16(port, status | UHCI_PORTSC_ENABLED);
1971		snooze(50000);
1972
1973		status = ReadReg16(port);
1974
1975		if ((status & UHCI_PORTSC_CURSTAT) == 0) {
1976			// no device connected. since we waited long enough we can assume
1977			// that the port was reset and no device is connected.
1978			break;
1979		}
1980
1981		if (status & (UHCI_PORTSC_STATCHA | UHCI_PORTSC_ENABCHA)) {
1982			// port enabled changed or connection status were set.
1983			// acknowledge either / both and wait again.
1984			status &= UHCI_PORTSC_DATAMASK;
1985			WriteReg16(port, status | UHCI_PORTSC_STATCHA | UHCI_PORTSC_ENABCHA);
1986			continue;
1987		}
1988
1989		if (status & UHCI_PORTSC_ENABLED) {
1990			// the port is enabled
1991			break;
1992		}
1993	}
1994
1995	fPortResetChange |= (1 << index);
1996	TRACE("port was reset: 0x%04x\n", ReadReg16(port));
1997	return B_OK;
1998}
1999
2000
2001int32
2002UHCI::InterruptHandler(void *data)
2003{
2004	return ((UHCI *)data)->Interrupt();
2005}
2006
2007
2008int32
2009UHCI::Interrupt()
2010{
2011	static spinlock lock = B_SPINLOCK_INITIALIZER;
2012	acquire_spinlock(&lock);
2013
2014	// Check if we really had an interrupt
2015	uint16 status = ReadReg16(UHCI_USBSTS);
2016	if ((status & fEnabledInterrupts) == 0) {
2017		if (status != 0) {
2018			TRACE("discarding not enabled interrupts 0x%08x\n", status);
2019			WriteReg16(UHCI_USBSTS, status);
2020		}
2021
2022		release_spinlock(&lock);
2023		return B_UNHANDLED_INTERRUPT;
2024	}
2025
2026	uint16 acknowledge = 0;
2027	bool finishTransfers = false;
2028	int32 result = B_HANDLED_INTERRUPT;
2029
2030	if (status & UHCI_USBSTS_USBINT) {
2031		TRACE_MODULE("transfer finished\n");
2032		acknowledge |= UHCI_USBSTS_USBINT;
2033		result = B_INVOKE_SCHEDULER;
2034		finishTransfers = true;
2035	}
2036
2037	if (status & UHCI_USBSTS_ERRINT) {
2038		TRACE_MODULE("transfer error\n");
2039		acknowledge |= UHCI_USBSTS_ERRINT;
2040		result = B_INVOKE_SCHEDULER;
2041		finishTransfers = true;
2042	}
2043
2044	if (status & UHCI_USBSTS_RESDET) {
2045		TRACE_MODULE("resume detected\n");
2046		acknowledge |= UHCI_USBSTS_RESDET;
2047	}
2048
2049	if (status & UHCI_USBSTS_HOSTERR) {
2050		TRACE_MODULE_ERROR("host system error\n");
2051		acknowledge |= UHCI_USBSTS_HOSTERR;
2052	}
2053
2054	if (status & UHCI_USBSTS_HCPRERR) {
2055		TRACE_MODULE_ERROR("process error\n");
2056		acknowledge |= UHCI_USBSTS_HCPRERR;
2057	}
2058
2059	if (status & UHCI_USBSTS_HCHALT) {
2060		TRACE_MODULE_ERROR("host controller halted\n");
2061		// at least disable interrupts so we do not flood the system
2062		WriteReg16(UHCI_USBINTR, 0);
2063		fEnabledInterrupts = 0;
2064		// ToDo: cancel all transfers and reset the host controller
2065		// acknowledge not needed
2066	}
2067
2068	if (acknowledge)
2069		WriteReg16(UHCI_USBSTS, acknowledge);
2070
2071	release_spinlock(&lock);
2072
2073	if (finishTransfers)
2074		release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
2075
2076	return result;
2077}
2078
2079
2080status_t
2081UHCI::CreateFilledTransfer(Transfer *transfer, uhci_td **_firstDescriptor,
2082	uhci_qh **_transferQueue)
2083{
2084	Pipe *pipe = transfer->TransferPipe();
2085	bool directionIn = (pipe->Direction() == Pipe::In);
2086
2087	uhci_td *firstDescriptor = NULL;
2088	uhci_td *lastDescriptor = NULL;
2089	status_t result = CreateDescriptorChain(pipe, &firstDescriptor,
2090		&lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT,
2091		transfer->FragmentLength());
2092
2093	if (result < B_OK)
2094		return result;
2095	if (!firstDescriptor || !lastDescriptor)
2096		return B_NO_MEMORY;
2097
2098	lastDescriptor->status |= TD_CONTROL_IOC;
2099	lastDescriptor->link_phy = TD_TERMINATE;
2100	lastDescriptor->link_log = NULL;
2101
2102	if (!directionIn) {
2103		WriteDescriptorChain(firstDescriptor, transfer->Vector(),
2104			transfer->VectorCount(), transfer->IsPhysical());
2105	}
2106
2107	uhci_qh *transferQueue = CreateTransferQueue(firstDescriptor);
2108	if (!transferQueue) {
2109		FreeDescriptorChain(firstDescriptor);
2110		return B_NO_MEMORY;
2111	}
2112
2113	*_firstDescriptor = firstDescriptor;
2114	*_transferQueue = transferQueue;
2115	return B_OK;
2116}
2117
2118
2119uhci_qh *
2120UHCI::CreateTransferQueue(uhci_td *descriptor)
2121{
2122	uhci_qh *queueHead;
2123	phys_addr_t physicalAddress;
2124	if (fStack->AllocateChunk((void **)&queueHead, &physicalAddress,
2125		sizeof(uhci_qh)) < B_OK)
2126		return NULL;
2127
2128	queueHead->this_phy = (uint32)physicalAddress;
2129	queueHead->element_phy = descriptor->this_phy;
2130	return queueHead;
2131}
2132
2133
2134void
2135UHCI::FreeTransferQueue(uhci_qh *queueHead)
2136{
2137	if (!queueHead)
2138		return;
2139
2140	fStack->FreeChunk(queueHead, queueHead->this_phy, sizeof(uhci_qh));
2141}
2142
2143
2144uhci_td *
2145UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, size_t bufferSize)
2146{
2147	uhci_td *result;
2148	phys_addr_t physicalAddress;
2149
2150	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
2151		sizeof(uhci_td)) < B_OK) {
2152		TRACE_ERROR("failed to allocate a transfer descriptor\n");
2153		return NULL;
2154	}
2155
2156	result->this_phy = (uint32)physicalAddress;
2157	result->status = TD_STATUS_ACTIVE;
2158	if (pipe->Type() & USB_OBJECT_ISO_PIPE)
2159		result->status |= TD_CONTROL_ISOCHRONOUS;
2160	else {
2161		result->status |= TD_CONTROL_3_ERRORS;
2162		if (direction == TD_TOKEN_IN)
2163			result->status |= TD_CONTROL_SPD;
2164	}
2165	if (pipe->Speed() == USB_SPEED_LOWSPEED)
2166		result->status |= TD_CONTROL_LOWSPEED;
2167
2168	result->buffer_size = bufferSize;
2169	if (bufferSize == 0)
2170		result->token = TD_TOKEN_NULL_DATA;
2171	else
2172		result->token = (bufferSize - 1) << TD_TOKEN_MAXLEN_SHIFT;
2173
2174	result->token |= (pipe->EndpointAddress() << TD_TOKEN_ENDPTADDR_SHIFT)
2175		| (pipe->DeviceAddress() << 8) | direction;
2176
2177	result->link_phy = 0;
2178	result->link_log = NULL;
2179	if (bufferSize <= 0) {
2180		result->buffer_log = NULL;
2181		result->buffer_phy = 0;
2182		return result;
2183	}
2184
2185	if (fStack->AllocateChunk(&result->buffer_log, &physicalAddress,
2186		bufferSize) < B_OK) {
2187		TRACE_ERROR("unable to allocate space for the buffer\n");
2188		fStack->FreeChunk(result, result->this_phy, sizeof(uhci_td));
2189		return NULL;
2190	}
2191	result->buffer_phy = physicalAddress;
2192
2193	return result;
2194}
2195
2196
2197status_t
2198UHCI::CreateDescriptorChain(Pipe *pipe, uhci_td **_firstDescriptor,
2199	uhci_td **_lastDescriptor, uint8 direction, size_t bufferSize)
2200{
2201	size_t packetSize = pipe->MaxPacketSize();
2202	int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize;
2203	if (descriptorCount == 0)
2204		descriptorCount = 1;
2205
2206	bool dataToggle = pipe->DataToggle();
2207	uhci_td *firstDescriptor = NULL;
2208	uhci_td *lastDescriptor = *_firstDescriptor;
2209	for (int32 i = 0; i < descriptorCount; i++) {
2210		uhci_td *descriptor = CreateDescriptor(pipe, direction,
2211			min_c(packetSize, bufferSize));
2212
2213		if (!descriptor) {
2214			FreeDescriptorChain(firstDescriptor);
2215			return B_NO_MEMORY;
2216		}
2217
2218		if (dataToggle)
2219			descriptor->token |= TD_TOKEN_DATA1;
2220
2221		// link to previous
2222		if (lastDescriptor)
2223			LinkDescriptors(lastDescriptor, descriptor);
2224
2225		dataToggle = !dataToggle;
2226		bufferSize -= packetSize;
2227		lastDescriptor = descriptor;
2228		if (!firstDescriptor)
2229			firstDescriptor = descriptor;
2230	}
2231
2232	*_firstDescriptor = firstDescriptor;
2233	*_lastDescriptor = lastDescriptor;
2234	return B_OK;
2235}
2236
2237
2238void
2239UHCI::FreeDescriptor(uhci_td *descriptor)
2240{
2241	if (!descriptor)
2242		return;
2243
2244	if (descriptor->buffer_log) {
2245		fStack->FreeChunk(descriptor->buffer_log,
2246			descriptor->buffer_phy, descriptor->buffer_size);
2247	}
2248
2249	fStack->FreeChunk(descriptor, descriptor->this_phy, sizeof(uhci_td));
2250}
2251
2252
2253void
2254UHCI::FreeDescriptorChain(uhci_td *topDescriptor)
2255{
2256	uhci_td *current = topDescriptor;
2257	uhci_td *next = NULL;
2258
2259	while (current) {
2260		next = (uhci_td *)current->link_log;
2261		FreeDescriptor(current);
2262		current = next;
2263	}
2264}
2265
2266
2267void
2268UHCI::LinkDescriptors(uhci_td *first, uhci_td *second)
2269{
2270	first->link_phy = second->this_phy | TD_DEPTH_FIRST;
2271	first->link_log = second;
2272}
2273
2274
2275size_t
2276UHCI::WriteDescriptorChain(uhci_td *topDescriptor, generic_io_vec *vector,
2277	size_t vectorCount, bool physical)
2278{
2279	uhci_td *current = topDescriptor;
2280	size_t actualLength = 0;
2281	size_t vectorIndex = 0;
2282	size_t vectorOffset = 0;
2283	size_t bufferOffset = 0;
2284
2285	while (current) {
2286		if (!current->buffer_log)
2287			break;
2288
2289		while (true) {
2290			size_t length = min_c(current->buffer_size - bufferOffset,
2291				vector[vectorIndex].length - vectorOffset);
2292
2293			TRACE("copying %ld bytes to bufferOffset %ld from"
2294				" vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
2295				vectorOffset, vectorIndex, vectorCount);
2296			status_t status = generic_memcpy(
2297				(generic_addr_t)current->buffer_log + bufferOffset, false,
2298				vector[vectorIndex].base + vectorOffset, physical, length);
2299			ASSERT(status == B_OK);
2300
2301			actualLength += length;
2302			vectorOffset += length;
2303			bufferOffset += length;
2304
2305			if (vectorOffset >= vector[vectorIndex].length) {
2306				if (++vectorIndex >= vectorCount) {
2307					TRACE("wrote descriptor chain (%ld bytes, no more vectors)\n",
2308						actualLength);
2309					return actualLength;
2310				}
2311
2312				vectorOffset = 0;
2313			}
2314
2315			if (bufferOffset >= current->buffer_size) {
2316				bufferOffset = 0;
2317				break;
2318			}
2319		}
2320
2321		if (current->link_phy & TD_TERMINATE)
2322			break;
2323
2324		current = (uhci_td *)current->link_log;
2325	}
2326
2327	TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
2328	return actualLength;
2329}
2330
2331
2332size_t
2333UHCI::ReadDescriptorChain(uhci_td *topDescriptor, generic_io_vec *vector,
2334	size_t vectorCount, bool physical, uint8 *lastDataToggle)
2335{
2336	uint8 dataToggle = 0;
2337	uhci_td *current = topDescriptor;
2338	size_t actualLength = 0;
2339	size_t vectorIndex = 0;
2340	size_t vectorOffset = 0;
2341	size_t bufferOffset = 0;
2342
2343	while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
2344		if (!current->buffer_log)
2345			break;
2346
2347		dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01;
2348		size_t bufferSize = uhci_td_actual_length(current);
2349
2350		while (true) {
2351			size_t length = min_c(bufferSize - bufferOffset,
2352				vector[vectorIndex].length - vectorOffset);
2353
2354			TRACE("copying %ld bytes to vectorOffset %ld from"
2355				" bufferOffset %ld at index %ld of %ld\n", length, vectorOffset,
2356				bufferOffset, vectorIndex, vectorCount);
2357			status_t status = generic_memcpy(
2358				vector[vectorIndex].base + vectorOffset, physical,
2359				(generic_addr_t)current->buffer_log + bufferOffset, false, length);
2360			ASSERT(status == B_OK);
2361
2362			actualLength += length;
2363			vectorOffset += length;
2364			bufferOffset += length;
2365
2366			if (vectorOffset >= vector[vectorIndex].length) {
2367				if (++vectorIndex >= vectorCount) {
2368					TRACE("read descriptor chain (%ld bytes, no more vectors)\n",
2369						actualLength);
2370					if (lastDataToggle)
2371						*lastDataToggle = dataToggle;
2372					return actualLength;
2373				}
2374
2375				vectorOffset = 0;
2376			}
2377
2378			if (bufferOffset >= bufferSize) {
2379				bufferOffset = 0;
2380				break;
2381			}
2382		}
2383
2384		if (current->link_phy & TD_TERMINATE)
2385			break;
2386
2387		current = (uhci_td *)current->link_log;
2388	}
2389
2390	if (lastDataToggle)
2391		*lastDataToggle = dataToggle;
2392
2393	TRACE("read descriptor chain (%ld bytes)\n", actualLength);
2394	return actualLength;
2395}
2396
2397
2398size_t
2399UHCI::ReadActualLength(uhci_td *topDescriptor, uint8 *lastDataToggle)
2400{
2401	size_t actualLength = 0;
2402	uhci_td *current = topDescriptor;
2403	uint8 dataToggle = 0;
2404
2405	while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
2406		actualLength += uhci_td_actual_length(current);
2407		dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01;
2408
2409		if (current->link_phy & TD_TERMINATE)
2410			break;
2411
2412		current = (uhci_td *)current->link_log;
2413	}
2414
2415	if (lastDataToggle)
2416		*lastDataToggle = dataToggle;
2417
2418	TRACE("read actual length (%ld bytes)\n", actualLength);
2419	return actualLength;
2420}
2421
2422
2423void
2424UHCI::WriteIsochronousDescriptorChain(uhci_td **isoRequest, uint32 packetCount,
2425	generic_io_vec *vector)
2426{
2427	size_t vectorOffset = 0;
2428	for (uint32 i = 0; i < packetCount; i++) {
2429		size_t bufferSize = isoRequest[i]->buffer_size;
2430		memcpy((uint8 *)isoRequest[i]->buffer_log,
2431			(uint8 *)vector->base + vectorOffset, bufferSize);
2432		vectorOffset += bufferSize;
2433	}
2434}
2435
2436
2437void
2438UHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer,
2439	generic_io_vec *vector)
2440{
2441	size_t vectorOffset = 0;
2442	usb_isochronous_data *isochronousData
2443		= transfer->transfer->IsochronousData();
2444
2445	for (uint32 i = 0; i < isochronousData->packet_count; i++) {
2446		uhci_td *current = transfer->descriptors[i];
2447
2448		size_t bufferSize = current->buffer_size;
2449		size_t actualLength = uhci_td_actual_length(current);
2450
2451		isochronousData->packet_descriptors[i].actual_length = actualLength;
2452
2453		if (actualLength > 0)
2454			isochronousData->packet_descriptors[i].status = B_OK;
2455		else {
2456			isochronousData->packet_descriptors[i].status = B_ERROR;
2457			vectorOffset += bufferSize;
2458			continue;
2459		}
2460		memcpy((uint8 *)vector->base + vectorOffset,
2461			(uint8 *)current->buffer_log, bufferSize);
2462
2463		vectorOffset += bufferSize;
2464	}
2465}
2466
2467
2468bool
2469UHCI::LockIsochronous()
2470{
2471	return (mutex_lock(&fIsochronousLock) == B_OK);
2472}
2473
2474
2475void
2476UHCI::UnlockIsochronous()
2477{
2478	mutex_unlock(&fIsochronousLock);
2479}
2480
2481
2482inline void
2483UHCI::WriteReg8(uint32 reg, uint8 value)
2484{
2485	fPci->write_io_8(fDevice, fRegisterBase + reg, value);
2486}
2487
2488
2489inline void
2490UHCI::WriteReg16(uint32 reg, uint16 value)
2491{
2492	fPci->write_io_16(fDevice, fRegisterBase + reg, value);
2493}
2494
2495
2496inline void
2497UHCI::WriteReg32(uint32 reg, uint32 value)
2498{
2499	fPci->write_io_32(fDevice, fRegisterBase + reg, value);
2500}
2501
2502
2503inline uint8
2504UHCI::ReadReg8(uint32 reg)
2505{
2506	return fPci->read_io_8(fDevice, fRegisterBase + reg);
2507}
2508
2509
2510inline uint16
2511UHCI::ReadReg16(uint32 reg)
2512{
2513	return fPci->read_io_16(fDevice, fRegisterBase + reg);
2514}
2515
2516
2517inline uint32
2518UHCI::ReadReg32(uint32 reg)
2519{
2520	return fPci->read_io_32(fDevice, fRegisterBase + reg);
2521}
2522