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