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