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