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