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