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