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