xref: /haiku/src/add-ons/kernel/busses/usb/uhci.cpp (revision f5821a1aee77d3b9a979b42c68a79e50b5ebaefe)
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 
20 pci_module_info *UHCI::sPCIModule = NULL;
21 
22 static int32 sDebuggerCommandAdded = 0;
23 
24 
25 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
26 
27 
28 class DebugTransfer : public Transfer {
29 public:
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 */
48 static int
49 debug_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 
103 static int32
104 uhci_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 
121 usb_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 
132 module_info *modules[] = {
133 	(module_info *)&uhci_module,
134 	NULL
135 };
136 
137 
138 //
139 // #pragma mark -
140 //
141 
142 
143 #ifdef TRACE_USB
144 
145 void
146 print_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 
172 Queue::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 
192 Queue::~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 
205 status_t
206 Queue::InitCheck()
207 {
208 	return fStatus;
209 }
210 
211 
212 bool
213 Queue::Lock()
214 {
215 	return (mutex_lock(&fLock) == B_OK);
216 }
217 
218 
219 void
220 Queue::Unlock()
221 {
222 	mutex_unlock(&fLock);
223 }
224 
225 
226 status_t
227 Queue::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 
243 status_t
244 Queue::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 
280 status_t
281 Queue::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 
309 status_t
310 Queue::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 
350 uint32
351 Queue::PhysicalAddress()
352 {
353 	return fQueueHead->this_phy;
354 }
355 
356 
357 void
358 Queue::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 
379 UHCI::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 
584 UHCI::~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 
637 status_t
638 UHCI::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 
688 status_t
689 UHCI::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 
732 status_t
733 UHCI::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 
748 status_t
749 UHCI::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 
806 void
807 UHCI::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 
830 status_t
831 UHCI::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 
894 status_t
895 UHCI::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 
923 status_t
924 UHCI::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 
999 status_t
1000 UHCI::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 
1042 status_t
1043 UHCI::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 
1084 status_t
1085 UHCI::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 
1239 isochronous_transfer_data *
1240 UHCI::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 
1260 status_t
1261 UHCI::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 
1289 uhci_td *
1290 UHCI::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 
1313 int32
1314 UHCI::FinishThread(void *data)
1315 {
1316 	((UHCI *)data)->FinishTransfers();
1317 	return B_OK;
1318 }
1319 
1320 
1321 void
1322 UHCI::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 
1511 void
1512 UHCI::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 
1527 int32
1528 UHCI::CleanupThread(void *data)
1529 {
1530 	((UHCI *)data)->Cleanup();
1531 	return B_OK;
1532 }
1533 
1534 
1535 void
1536 UHCI::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 
1581 int32
1582 UHCI::FinishIsochronousThread(void *data)
1583 {
1584        ((UHCI *)data)->FinishIsochronousTransfers();
1585        return B_OK;
1586 }
1587 
1588 
1589 void
1590 UHCI::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 
1671 void
1672 UHCI::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 
1685 status_t
1686 UHCI::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 
1701 status_t
1702 UHCI::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 
1738 status_t
1739 UHCI::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 
1757 status_t
1758 UHCI::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 
1784 status_t
1785 UHCI::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 
1838 int32
1839 UHCI::InterruptHandler(void *data)
1840 {
1841 	return ((UHCI *)data)->Interrupt();
1842 }
1843 
1844 
1845 int32
1846 UHCI::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 
1917 status_t
1918 UHCI::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 
1995 status_t
1996 UHCI::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 
2034 uhci_qh *
2035 UHCI::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 
2049 void
2050 UHCI::FreeTransferQueue(uhci_qh *queueHead)
2051 {
2052 	if (!queueHead)
2053 		return;
2054 
2055 	fStack->FreeChunk(queueHead, queueHead->this_phy, sizeof(uhci_qh));
2056 }
2057 
2058 
2059 uhci_td *
2060 UHCI::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 
2113 status_t
2114 UHCI::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 
2154 void
2155 UHCI::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 
2169 void
2170 UHCI::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 
2183 void
2184 UHCI::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 
2191 size_t
2192 UHCI::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 
2246 size_t
2247 UHCI::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 
2310 size_t
2311 UHCI::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 
2335 void
2336 UHCI::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 
2349 void
2350 UHCI::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 
2380 bool
2381 UHCI::LockIsochronous()
2382 {
2383 	return (mutex_lock(&fIsochronousLock) == B_OK);
2384 }
2385 
2386 
2387 void
2388 UHCI::UnlockIsochronous()
2389 {
2390 	mutex_unlock(&fIsochronousLock);
2391 }
2392 
2393 
2394 inline void
2395 UHCI::WriteReg8(uint32 reg, uint8 value)
2396 {
2397 	sPCIModule->write_io_8(fRegisterBase + reg, value);
2398 }
2399 
2400 
2401 inline void
2402 UHCI::WriteReg16(uint32 reg, uint16 value)
2403 {
2404 	sPCIModule->write_io_16(fRegisterBase + reg, value);
2405 }
2406 
2407 
2408 inline void
2409 UHCI::WriteReg32(uint32 reg, uint32 value)
2410 {
2411 	sPCIModule->write_io_32(fRegisterBase + reg, value);
2412 }
2413 
2414 
2415 inline uint8
2416 UHCI::ReadReg8(uint32 reg)
2417 {
2418 	return sPCIModule->read_io_8(fRegisterBase + reg);
2419 }
2420 
2421 
2422 inline uint16
2423 UHCI::ReadReg16(uint32 reg)
2424 {
2425 	return sPCIModule->read_io_16(fRegisterBase + reg);
2426 }
2427 
2428 
2429 inline uint32
2430 UHCI::ReadReg32(uint32 reg)
2431 {
2432 	return sPCIModule->read_io_32(fRegisterBase + reg);
2433 }
2434