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