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