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