xref: /haiku/src/add-ons/kernel/busses/usb/ehci.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
1 /*
2  * Copyright 2006-2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  */
8 
9 #include <module.h>
10 #include <PCI.h>
11 #include <USB3.h>
12 #include <KernelExport.h>
13 
14 #include "ehci.h"
15 
16 #define USB_MODULE_NAME	"ehci"
17 
18 pci_module_info *EHCI::sPCIModule = NULL;
19 
20 
21 static int32
22 ehci_std_ops(int32 op, ...)
23 {
24 	switch (op) {
25 		case B_MODULE_INIT:
26 			TRACE_MODULE("ehci init module\n");
27 			return B_OK;
28 		case B_MODULE_UNINIT:
29 			TRACE_MODULE("ehci uninit module\n");
30 			return B_OK;
31 	}
32 
33 	return EINVAL;
34 }
35 
36 
37 usb_host_controller_info ehci_module = {
38 	{
39 		"busses/usb/ehci",
40 		0,
41 		ehci_std_ops
42 	},
43 	NULL,
44 	EHCI::AddTo
45 };
46 
47 
48 module_info *modules[] = {
49 	(module_info *)&ehci_module,
50 	NULL
51 };
52 
53 
54 //
55 // #pragma mark -
56 //
57 
58 
59 #ifdef TRACE_USB
60 
61 void
62 print_descriptor_chain(ehci_qtd *descriptor)
63 {
64 	while (descriptor) {
65 		dprintf(" %08lx n%08lx a%08lx t%08lx %08lx %08lx %08lx %08lx %08lx s%ld\n",
66 			descriptor->this_phy, descriptor->next_phy,
67 			descriptor->alt_next_phy, descriptor->token,
68 			descriptor->buffer_phy[0], descriptor->buffer_phy[1],
69 			descriptor->buffer_phy[2], descriptor->buffer_phy[3],
70 			descriptor->buffer_phy[4], descriptor->buffer_size);
71 
72 		if (descriptor->next_phy & EHCI_QTD_TERMINATE)
73 			break;
74 
75 		descriptor = (ehci_qtd *)descriptor->next_log;
76 	}
77 }
78 
79 void
80 print_queue(ehci_qh *queueHead)
81 {
82 	dprintf("queue:    t%08lx n%08lx ch%08lx ca%08lx cu%08lx\n",
83 		queueHead->this_phy, queueHead->next_phy, queueHead->endpoint_chars,
84 		queueHead->endpoint_caps, queueHead->current_qtd_phy);
85 	dprintf("overlay:  n%08lx a%08lx t%08lx %08lx %08lx %08lx %08lx %08lx\n",
86 		queueHead->overlay.next_phy, queueHead->overlay.alt_next_phy,
87 		queueHead->overlay.token, queueHead->overlay.buffer_phy[0],
88 		queueHead->overlay.buffer_phy[1], queueHead->overlay.buffer_phy[2],
89 		queueHead->overlay.buffer_phy[3], queueHead->overlay.buffer_phy[4]);
90 	print_descriptor_chain((ehci_qtd *)queueHead->element_log);
91 }
92 
93 #endif // TRACE_USB
94 
95 
96 //
97 // #pragma mark -
98 //
99 
100 
101 EHCI::EHCI(pci_info *info, Stack *stack)
102 	:	BusManager(stack),
103 		fCapabilityRegisters(NULL),
104 		fOperationalRegisters(NULL),
105 		fRegisterArea(-1),
106 		fPCIInfo(info),
107 		fStack(stack),
108 		fEnabledInterrupts(0),
109 		fPeriodicFrameListArea(-1),
110 		fPeriodicFrameList(NULL),
111 		fInterruptEntries(NULL),
112 		fAsyncQueueHead(NULL),
113 		fAsyncAdvanceSem(-1),
114 		fFirstTransfer(NULL),
115 		fLastTransfer(NULL),
116 		fFinishTransfersSem(-1),
117 		fFinishThread(-1),
118 		fCleanupSem(-1),
119 		fCleanupThread(-1),
120 		fStopThreads(false),
121 		fFreeListHead(NULL),
122 		fProcessingPipe(NULL),
123 		fRootHub(NULL),
124 		fRootHubAddress(0),
125 		fPortCount(0),
126 		fPortResetChange(0),
127 		fPortSuspendChange(0)
128 {
129 	if (BusManager::InitCheck() < B_OK) {
130 		TRACE_ERROR("bus manager failed to init\n");
131 		return;
132 	}
133 
134 	TRACE("constructing new EHCI host controller driver\n");
135 	fInitOK = false;
136 
137 	// enable busmaster and memory mapped access
138 	uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
139 		fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
140 	command &= ~PCI_command_io;
141 	command |= PCI_command_master | PCI_command_memory;
142 
143 	sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
144 		fPCIInfo->function, PCI_command, 2, command);
145 
146 	// map the registers
147 	uint32 offset = fPCIInfo->u.h0.base_registers[0] & (B_PAGE_SIZE - 1);
148 	addr_t physicalAddress = fPCIInfo->u.h0.base_registers[0] - offset;
149 	size_t mapSize = (fPCIInfo->u.h0.base_register_sizes[0] + offset
150 		+ B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
151 
152 	TRACE("map physical memory 0x%08lx (base: 0x%08lx; offset: %lx); size: %ld\n",
153 		fPCIInfo->u.h0.base_registers[0], physicalAddress, offset,
154 		fPCIInfo->u.h0.base_register_sizes[0]);
155 
156 	fRegisterArea = map_physical_memory("EHCI memory mapped registers",
157 		(void *)physicalAddress, mapSize, B_ANY_KERNEL_BLOCK_ADDRESS,
158 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA,
159 		(void **)&fCapabilityRegisters);
160 	if (fRegisterArea < B_OK) {
161 		TRACE("failed to map register memory\n");
162 		return;
163 	}
164 
165 	fCapabilityRegisters += offset;
166 	fOperationalRegisters = fCapabilityRegisters + ReadCapReg8(EHCI_CAPLENGTH);
167 	TRACE("mapped capability registers: 0x%08lx\n", (uint32)fCapabilityRegisters);
168 	TRACE("mapped operational registers: 0x%08lx\n", (uint32)fOperationalRegisters);
169 
170 	TRACE("structural parameters: 0x%08lx\n", ReadCapReg32(EHCI_HCSPARAMS));
171 	TRACE("capability parameters: 0x%08lx\n", ReadCapReg32(EHCI_HCCPARAMS));
172 
173 	// read port count from capability register
174 	fPortCount = ReadCapReg32(EHCI_HCSPARAMS) & 0x0f;
175 
176 	uint32 extendedCapPointer = ReadCapReg32(EHCI_HCCPARAMS) >> EHCI_ECP_SHIFT;
177 	extendedCapPointer &= EHCI_ECP_MASK;
178 	if (extendedCapPointer > 0) {
179 		TRACE("extended capabilities register at %ld\n", extendedCapPointer);
180 
181 		uint32 legacySupport = sPCIModule->read_pci_config(fPCIInfo->bus,
182 			fPCIInfo->device, fPCIInfo->function, extendedCapPointer, 4);
183 		if ((legacySupport & EHCI_LEGSUP_CAPID_MASK) == EHCI_LEGSUP_CAPID) {
184 			if (legacySupport & EHCI_LEGSUP_BIOSOWNED)
185 				TRACE_ALWAYS("the host controller is bios owned\n");
186 
187 			TRACE_ALWAYS("claiming ownership of the host controller\n");
188 			sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
189 				fPCIInfo->function, extendedCapPointer + 3, 1, 1);
190 
191 			for (int32 i = 0; i < 20; i++) {
192 				legacySupport = sPCIModule->read_pci_config(fPCIInfo->bus,
193 					fPCIInfo->device, fPCIInfo->function, extendedCapPointer, 4);
194 
195 				if (legacySupport & EHCI_LEGSUP_BIOSOWNED) {
196 					TRACE_ALWAYS("controller is still bios owned, waiting\n");
197 					snooze(50000);
198 				} else
199 					break;
200 			}
201 
202 			if (legacySupport & EHCI_LEGSUP_BIOSOWNED) {
203 				TRACE_ERROR("bios won't give up control over the host controller (ignoring)\n");
204 			} else if (legacySupport & EHCI_LEGSUP_OSOWNED) {
205 				TRACE_ALWAYS("successfully took ownership of the host controller\n");
206 			}
207 
208 			// Force off the BIOS owned flag, and clear all SMIs. Some BIOSes
209 			// do indicate a successful handover but do not remove their SMIs
210 			// and then freeze the system when interrupts are generated.
211 			sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
212 				fPCIInfo->function, extendedCapPointer + 2, 1, 0);
213 			sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
214 				fPCIInfo->function, extendedCapPointer + 4, 4, 0);
215 		} else {
216 			TRACE("extended capability is not a legacy support register\n");
217 		}
218 	} else {
219 		TRACE("no extended capabilities register\n");
220 	}
221 
222 	// disable interrupts
223 	WriteOpReg(EHCI_USBINTR, 0);
224 
225 	// reset the host controller
226 	if (ControllerReset() < B_OK) {
227 		TRACE_ERROR("host controller failed to reset\n");
228 		return;
229 	}
230 
231 	// reset the segment register
232 	WriteOpReg(EHCI_CTRDSSEGMENT, 0);
233 
234 	// create semaphores the finisher thread will wait for
235 	fAsyncAdvanceSem = create_sem(0, "EHCI Async Advance");
236 	fFinishTransfersSem = create_sem(0, "EHCI Finish Transfers");
237 	fCleanupSem = create_sem(0, "EHCI Cleanup");
238 	if (fFinishTransfersSem < B_OK || fAsyncAdvanceSem < B_OK
239 		|| fCleanupSem < B_OK) {
240 		TRACE_ERROR("failed to create semaphores\n");
241 		return;
242 	}
243 
244 	// create finisher service thread
245 	fFinishThread = spawn_kernel_thread(FinishThread, "ehci finish thread",
246 		B_NORMAL_PRIORITY, (void *)this);
247 	resume_thread(fFinishThread);
248 
249 	// create cleanup service thread
250 	fCleanupThread = spawn_kernel_thread(CleanupThread, "ehci cleanup thread",
251 		B_NORMAL_PRIORITY, (void *)this);
252 	resume_thread(fCleanupThread);
253 
254 	// install the interrupt handler and enable interrupts
255 	install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
256 		InterruptHandler, (void *)this, 0);
257 	fEnabledInterrupts = EHCI_USBINTR_HOSTSYSERR | EHCI_USBINTR_USBERRINT
258 		| EHCI_USBINTR_USBINT | EHCI_USBINTR_INTONAA;
259 	WriteOpReg(EHCI_USBINTR, fEnabledInterrupts);
260 
261 	// allocate the periodic frame list
262 	fPeriodicFrameListArea = fStack->AllocateArea((void **)&fPeriodicFrameList,
263 		(void **)&physicalAddress, B_PAGE_SIZE * 2, "USB EHCI Periodic Framelist");
264 	if (fPeriodicFrameListArea < B_OK) {
265 		TRACE_ERROR("unable to allocate periodic framelist\n");
266 		return;
267 	}
268 
269 	// set the periodic frame list base on the controller
270 	WriteOpReg(EHCI_PERIODICLISTBASE, (uint32)physicalAddress);
271 
272 	// create the interrupt entries to support different polling intervals
273 	TRACE("creating interrupt entries\n");
274 	addr_t physicalBase = physicalAddress + B_PAGE_SIZE;
275 	uint8 *logicalBase = (uint8 *)fPeriodicFrameList + B_PAGE_SIZE;
276 	memset(logicalBase, 0, B_PAGE_SIZE);
277 
278 	fInterruptEntries = (interrupt_entry *)logicalBase;
279 	for (int32 i = 0; i < 11; i++) {
280 		ehci_qh *queueHead = &fInterruptEntries[i].queue_head;
281 		queueHead->this_phy = physicalBase;
282 		queueHead->current_qtd_phy = EHCI_QTD_TERMINATE;
283 		queueHead->overlay.next_phy = EHCI_QTD_TERMINATE;
284 		queueHead->overlay.alt_next_phy = EHCI_QTD_TERMINATE;
285 		queueHead->overlay.token = EHCI_QTD_STATUS_HALTED;
286 
287 		// set dummy endpoint information
288 		queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH
289 			| (3 << EHCI_QH_CHARS_RL_SHIFT) | (64 << EHCI_QH_CHARS_MPL_SHIFT)
290 			| EHCI_QH_CHARS_TOGGLE;
291 		queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT)
292 			| (0xff << EHCI_QH_CAPS_ISM_SHIFT);
293 
294 		physicalBase += sizeof(interrupt_entry);
295 	}
296 
297 	// build flat interrupt tree
298 	TRACE("build up interrupt links\n");
299 	uint32 interval = 1024;
300 	uint32 intervalIndex = 10;
301 	while (interval > 1) {
302 		uint32 insertIndex = interval / 2;
303 		while (insertIndex < 1024) {
304 			uint32 entry = fInterruptEntries[intervalIndex].queue_head.this_phy;
305 			fPeriodicFrameList[insertIndex] = entry | EHCI_PFRAMELIST_QH;
306 			insertIndex += interval;
307 		}
308 
309 		intervalIndex--;
310 		interval /= 2;
311 	}
312 
313 	// setup the empty slot in the list and linking of all -> first
314 	ehci_qh *firstLogical = &fInterruptEntries[0].queue_head;
315 	uint32 firstPhysical = firstLogical->this_phy | EHCI_QH_TYPE_QH;
316 	fPeriodicFrameList[0] = firstPhysical;
317 	for (int32 i = 1; i < 11; i++) {
318 		fInterruptEntries[i].queue_head.next_phy = firstPhysical;
319 		fInterruptEntries[i].queue_head.next_log = firstLogical;
320 		fInterruptEntries[i].queue_head.prev_log = NULL;
321 	}
322 
323 	// terminate the first entry
324 	firstLogical->next_phy = EHCI_QH_TERMINATE;
325 	firstLogical->next_log = NULL;
326 	firstLogical->prev_log = NULL;
327 
328 	// allocate a queue head that will always stay in the async frame list
329 	fAsyncQueueHead = CreateQueueHead();
330 	if (!fAsyncQueueHead) {
331 		TRACE_ERROR("unable to allocate stray async queue head\n");
332 		return;
333 	}
334 
335 	fAsyncQueueHead->next_phy = fAsyncQueueHead->this_phy | EHCI_QH_TYPE_QH;
336 	fAsyncQueueHead->next_log = fAsyncQueueHead;
337 	fAsyncQueueHead->prev_log = fAsyncQueueHead;
338 	fAsyncQueueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH | EHCI_QH_CHARS_RECHEAD;
339 	fAsyncQueueHead->endpoint_caps = 1 << EHCI_QH_CAPS_MULT_SHIFT;
340 	fAsyncQueueHead->current_qtd_phy = EHCI_QTD_TERMINATE;
341 	fAsyncQueueHead->overlay.next_phy = EHCI_QTD_TERMINATE;
342 
343 	WriteOpReg(EHCI_ASYNCLISTADDR, (uint32)fAsyncQueueHead->this_phy
344 		| EHCI_QH_TYPE_QH);
345 	TRACE("set the async list addr to 0x%08lx\n", ReadOpReg(EHCI_ASYNCLISTADDR));
346 
347 	fInitOK = true;
348 	TRACE("EHCI host controller driver constructed\n");
349 }
350 
351 
352 EHCI::~EHCI()
353 {
354 	TRACE("tear down EHCI host controller driver\n");
355 
356 	WriteOpReg(EHCI_USBCMD, 0);
357 	WriteOpReg(EHCI_CONFIGFLAG, 0);
358 	CancelAllPendingTransfers();
359 
360 	int32 result = 0;
361 	fStopThreads = true;
362 	delete_sem(fAsyncAdvanceSem);
363 	delete_sem(fFinishTransfersSem);
364 	wait_for_thread(fFinishThread, &result);
365 	wait_for_thread(fCleanupThread, &result);
366 
367 	delete fRootHub;
368 	delete_area(fPeriodicFrameListArea);
369 	delete_area(fRegisterArea);
370 	put_module(B_PCI_MODULE_NAME);
371 }
372 
373 
374 status_t
375 EHCI::Start()
376 {
377 	TRACE("starting EHCI host controller\n");
378 	TRACE("usbcmd: 0x%08lx; usbsts: 0x%08lx\n", ReadOpReg(EHCI_USBCMD), ReadOpReg(EHCI_USBSTS));
379 
380 	uint32 frameListSize = (ReadOpReg(EHCI_USBCMD) >> EHCI_USBCMD_FLS_SHIFT)
381 		& EHCI_USBCMD_FLS_MASK;
382 	WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_RUNSTOP
383 		| EHCI_USBCMD_ASENABLE | EHCI_USBCMD_PSENABLE
384 		| (frameListSize << EHCI_USBCMD_FLS_SHIFT)
385 		| (1 << EHCI_USBCMD_ITC_SHIFT));
386 
387 	bool running = false;
388 	for (int32 i = 0; i < 10; i++) {
389 		uint32 status = ReadOpReg(EHCI_USBSTS);
390 		TRACE("try %ld: status 0x%08lx\n", i, status);
391 
392 		if (status & EHCI_USBSTS_HCHALTED) {
393 			snooze(10000);
394 		} else {
395 			running = true;
396 			break;
397 		}
398 	}
399 
400 	if (!running) {
401 		TRACE("host controller didn't start\n");
402 		return B_ERROR;
403 	}
404 
405 	// route all ports to us
406 	WriteOpReg(EHCI_CONFIGFLAG, EHCI_CONFIGFLAG_FLAG);
407 	snooze(10000);
408 
409 	fRootHubAddress = AllocateAddress();
410 	fRootHub = new(std::nothrow) EHCIRootHub(RootObject(), fRootHubAddress);
411 	if (!fRootHub) {
412 		TRACE_ERROR("no memory to allocate root hub\n");
413 		return B_NO_MEMORY;
414 	}
415 
416 	if (fRootHub->InitCheck() < B_OK) {
417 		TRACE_ERROR("root hub failed init check\n");
418 		return fRootHub->InitCheck();
419 	}
420 
421 	SetRootHub(fRootHub);
422 	TRACE_ALWAYS("successfully started the controller\n");
423 	return BusManager::Start();
424 }
425 
426 
427 status_t
428 EHCI::SubmitTransfer(Transfer *transfer)
429 {
430 	// short circuit the root hub
431 	if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
432 		return fRootHub->ProcessTransfer(this, transfer);
433 
434 	Pipe *pipe = transfer->TransferPipe();
435 	if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
436 		// ToDo: implement isochronous transfers...
437 		return B_ERROR;
438 	}
439 
440 	ehci_qh *queueHead = CreateQueueHead();
441 	if (!queueHead) {
442 		TRACE_ERROR("failed to allocate queue head\n");
443 		return B_NO_MEMORY;
444 	}
445 
446 	status_t result = InitQueueHead(queueHead, pipe);
447 	if (result < B_OK) {
448 		TRACE_ERROR("failed to init queue head\n");
449 		FreeQueueHead(queueHead);
450 		return result;
451 	}
452 
453 	bool directionIn;
454 	ehci_qtd *dataDescriptor;
455 	if (pipe->Type() & USB_OBJECT_CONTROL_PIPE) {
456 		result = FillQueueWithRequest(transfer, queueHead, &dataDescriptor,
457 			&directionIn);
458 	} else {
459 		result = FillQueueWithData(transfer, queueHead, &dataDescriptor,
460 			&directionIn);
461 	}
462 
463 	if (result < B_OK) {
464 		TRACE_ERROR("failed to fill transfer queue with data\n");
465 		FreeQueueHead(queueHead);
466 		return result;
467 	}
468 
469 	result = AddPendingTransfer(transfer, queueHead, dataDescriptor, directionIn);
470 	if (result < B_OK) {
471 		TRACE_ERROR("failed to add pending transfer\n");
472 		FreeQueueHead(queueHead);
473 		return result;
474 	}
475 
476 #ifdef TRACE_USB
477 	TRACE("linking queue\n");
478 	print_queue(queueHead);
479 #endif
480 
481 	if (pipe->Type() & USB_OBJECT_INTERRUPT_PIPE)
482 		result = LinkInterruptQueueHead(queueHead, pipe);
483 	else
484 		result = LinkQueueHead(queueHead);
485 
486 	if (result < B_OK) {
487 		TRACE_ERROR("failed to link queue head\n");
488 		FreeQueueHead(queueHead);
489 		return result;
490 	}
491 
492 	return B_OK;
493 }
494 
495 
496 status_t
497 EHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
498 {
499 	TRACE("pipe change %d for pipe %p\n", change, pipe);
500 	switch (change) {
501 		case USB_CHANGE_CREATED:
502 		case USB_CHANGE_DESTROYED: {
503 			// ToDo: we should create and keep a single queue head
504 			// for all transfers to/from this pipe
505 			break;
506 		}
507 
508 		case USB_CHANGE_PIPE_POLICY_CHANGED: {
509 			// ToDo: for isochronous pipes we might need to adapt to new
510 			// pipe policy settings here
511 			break;
512 		}
513 	}
514 
515 	return B_OK;
516 }
517 
518 
519 status_t
520 EHCI::AddTo(Stack *stack)
521 {
522 #ifdef TRACE_USB
523 	set_dprintf_enabled(true);
524 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
525 	load_driver_symbols("ehci");
526 #endif
527 #endif
528 
529 	if (!sPCIModule) {
530 		status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
531 		if (status < B_OK) {
532 			TRACE_MODULE_ERROR("getting pci module failed! 0x%08lx\n", status);
533 			return status;
534 		}
535 	}
536 
537 	TRACE_MODULE("searching devices\n");
538 	bool found = false;
539 	pci_info *item = new(std::nothrow) pci_info;
540 	if (!item) {
541 		sPCIModule = NULL;
542 		put_module(B_PCI_MODULE_NAME);
543 		return B_NO_MEMORY;
544 	}
545 
546 	for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
547 		if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
548 			&& item->class_api == PCI_usb_ehci) {
549 			if (item->u.h0.interrupt_line == 0
550 				|| item->u.h0.interrupt_line == 0xFF) {
551 				TRACE_MODULE_ERROR("found device with invalid IRQ - check IRQ assignement\n");
552 				continue;
553 			}
554 
555 			TRACE_MODULE("found device at IRQ %u\n", item->u.h0.interrupt_line);
556 			EHCI *bus = new(std::nothrow) EHCI(item, stack);
557 			if (!bus) {
558 				delete item;
559 				sPCIModule = NULL;
560 				put_module(B_PCI_MODULE_NAME);
561 				return B_NO_MEMORY;
562 			}
563 
564 			if (bus->InitCheck() < B_OK) {
565 				TRACE_MODULE_ERROR("bus failed init check\n");
566 				delete bus;
567 				continue;
568 			}
569 
570 			// the bus took it away
571 			item = new(std::nothrow) pci_info;
572 
573 			bus->Start();
574 			stack->AddBusManager(bus);
575 			found = true;
576 		}
577 	}
578 
579 	if (!found) {
580 		TRACE_MODULE_ERROR("no devices found\n");
581 		delete item;
582 		sPCIModule = NULL;
583 		put_module(B_PCI_MODULE_NAME);
584 		return ENODEV;
585 	}
586 
587 	delete item;
588 	return B_OK;
589 }
590 
591 
592 status_t
593 EHCI::GetPortStatus(uint8 index, usb_port_status *status)
594 {
595 	if (index >= fPortCount)
596 		return B_BAD_INDEX;
597 
598 	status->status = status->change = 0;
599 	uint32 portStatus = ReadOpReg(EHCI_PORTSC + index * sizeof(uint32));
600 
601 	// build the status
602 	if (portStatus & EHCI_PORTSC_CONNSTATUS)
603 		status->status |= PORT_STATUS_CONNECTION;
604 	if (portStatus & EHCI_PORTSC_ENABLE)
605 		status->status |= PORT_STATUS_ENABLE;
606 	if (portStatus & EHCI_PORTSC_ENABLE)
607 		status->status |= PORT_STATUS_HIGH_SPEED;
608 	if (portStatus & EHCI_PORTSC_OCACTIVE)
609 		status->status |= PORT_STATUS_OVER_CURRENT;
610 	if (portStatus & EHCI_PORTSC_PORTRESET)
611 		status->status |= PORT_STATUS_RESET;
612 	if (portStatus & EHCI_PORTSC_PORTPOWER)
613 		status->status |= PORT_STATUS_POWER;
614 	if (portStatus & EHCI_PORTSC_SUSPEND)
615 		status->status |= PORT_STATUS_SUSPEND;
616 	if (portStatus & EHCI_PORTSC_DMINUS)
617 		status->status |= PORT_STATUS_LOW_SPEED;
618 
619 	// build the change
620 	if (portStatus & EHCI_PORTSC_CONNCHANGE)
621 		status->change |= PORT_STATUS_CONNECTION;
622 	if (portStatus & EHCI_PORTSC_ENABLECHANGE)
623 		status->change |= PORT_STATUS_ENABLE;
624 	if (portStatus & EHCI_PORTSC_OCCHANGE)
625 		status->change |= PORT_STATUS_OVER_CURRENT;
626 
627 	// there are no bits to indicate suspend and reset change
628 	if (fPortResetChange & (1 << index))
629 		status->change |= PORT_STATUS_RESET;
630 	if (fPortSuspendChange & (1 << index))
631 		status->change |= PORT_STATUS_SUSPEND;
632 
633 	return B_OK;
634 }
635 
636 
637 status_t
638 EHCI::SetPortFeature(uint8 index, uint16 feature)
639 {
640 	if (index >= fPortCount)
641 		return B_BAD_INDEX;
642 
643 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
644 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
645 
646 	switch (feature) {
647 		case PORT_SUSPEND:
648 			return SuspendPort(index);
649 
650 		case PORT_RESET:
651 			return ResetPort(index);
652 
653 		case PORT_POWER:
654 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTPOWER);
655 			return B_OK;
656 	}
657 
658 	return B_BAD_VALUE;
659 }
660 
661 
662 status_t
663 EHCI::ClearPortFeature(uint8 index, uint16 feature)
664 {
665 	if (index >= fPortCount)
666 		return B_BAD_INDEX;
667 
668 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
669 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
670 
671 	switch (feature) {
672 		case PORT_ENABLE:
673 			WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_ENABLE);
674 			return B_OK;
675 
676 		case PORT_POWER:
677 			WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTPOWER);
678 			return B_OK;
679 
680 		case C_PORT_CONNECTION:
681 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_CONNCHANGE);
682 			return B_OK;
683 
684 		case C_PORT_ENABLE:
685 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_ENABLECHANGE);
686 			return B_OK;
687 
688 		case C_PORT_OVER_CURRENT:
689 			WriteOpReg(portRegister, portStatus | EHCI_PORTSC_OCCHANGE);
690 			return B_OK;
691 
692 		case C_PORT_RESET:
693 			fPortResetChange &= ~(1 << index);
694 			return B_OK;
695 
696 		case C_PORT_SUSPEND:
697 			fPortSuspendChange &= ~(1 << index);
698 			return B_OK;
699 	}
700 
701 	return B_BAD_VALUE;
702 }
703 
704 
705 status_t
706 EHCI::ResetPort(uint8 index)
707 {
708 	TRACE("reset port %d\n", index);
709 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
710 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
711 
712 	if (portStatus & EHCI_PORTSC_DMINUS) {
713 		TRACE_ALWAYS("lowspeed device connected, giving up port ownership\n");
714 		// there is a lowspeed device connected.
715 		// we give the ownership to a companion controller.
716 		WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER);
717 		fPortResetChange |= (1 << index);
718 		return B_OK;
719 	}
720 
721 	// enable reset signaling
722 	WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTRESET);
723 	snooze(250000);
724 
725 	// disable reset signaling
726 	portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
727 	WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTRESET);
728 	snooze(2000);
729 
730 	portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
731 	if (portStatus & EHCI_PORTSC_PORTRESET) {
732 		TRACE_ERROR("port reset won't complete\n");
733 		return B_ERROR;
734 	}
735 
736 	if ((portStatus & EHCI_PORTSC_ENABLE) == 0) {
737 		TRACE_ALWAYS("fullspeed device connected, giving up port ownership\n");
738 		// the port was not enabled, this means that no high speed device is
739 		// attached to this port. we give up ownership to a companion controler
740 		WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER);
741 	}
742 
743 	fPortResetChange |= (1 << index);
744 	return B_OK;
745 }
746 
747 
748 status_t
749 EHCI::SuspendPort(uint8 index)
750 {
751 	uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32);
752 	uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK;
753 	WriteOpReg(portRegister, portStatus | EHCI_PORTSC_SUSPEND);
754 	fPortSuspendChange |= (1 << index);
755 	return B_OK;
756 }
757 
758 
759 status_t
760 EHCI::ControllerReset()
761 {
762 	// halt the controller first
763 	WriteOpReg(EHCI_USBCMD, 0);
764 	snooze(10000);
765 
766 	// then reset it
767 	WriteOpReg(EHCI_USBCMD, EHCI_USBCMD_HCRESET);
768 
769 	int32 tries = 5;
770 	while (ReadOpReg(EHCI_USBCMD) & EHCI_USBCMD_HCRESET) {
771 		snooze(10000);
772 		if (tries-- < 0)
773 			return B_ERROR;
774 	}
775 
776 	return B_OK;
777 }
778 
779 
780 status_t
781 EHCI::LightReset()
782 {
783 	return B_ERROR;
784 }
785 
786 
787 int32
788 EHCI::InterruptHandler(void *data)
789 {
790 	return ((EHCI *)data)->Interrupt();
791 }
792 
793 
794 int32
795 EHCI::Interrupt()
796 {
797 	static spinlock lock = B_SPINLOCK_INITIALIZER;
798 	acquire_spinlock(&lock);
799 
800 	// check if any interrupt was generated
801 	uint32 status = ReadOpReg(EHCI_USBSTS) & EHCI_USBSTS_INTMASK;
802 	if ((status & fEnabledInterrupts) == 0) {
803 		if (status != 0) {
804 			TRACE("discarding not enabled interrupts 0x%08lx\n", status);
805 			WriteOpReg(EHCI_USBSTS, status);
806 		}
807 
808 		release_spinlock(&lock);
809 		return B_UNHANDLED_INTERRUPT;
810 	}
811 
812 	bool asyncAdvance = false;
813 	bool finishTransfers = false;
814 	int32 result = B_HANDLED_INTERRUPT;
815 
816 	if (status & EHCI_USBSTS_USBINT) {
817 		TRACE("transfer finished\n");
818 		result = B_INVOKE_SCHEDULER;
819 		finishTransfers = true;
820 	}
821 
822 	if (status & EHCI_USBSTS_USBERRINT) {
823 		TRACE("transfer error\n");
824 		result = B_INVOKE_SCHEDULER;
825 		finishTransfers = true;
826 	}
827 
828 	if (status & EHCI_USBSTS_FLROLLOVER)
829 		TRACE("frame list rollover\n");
830 
831 	if (status & EHCI_USBSTS_PORTCHANGE)
832 		TRACE("port change detected\n");
833 
834 	if (status & EHCI_USBSTS_INTONAA) {
835 		TRACE("interrupt on async advance\n");
836 		asyncAdvance = true;
837 		result = B_INVOKE_SCHEDULER;
838 	}
839 
840 	if (status & EHCI_USBSTS_HOSTSYSERR)
841 		TRACE_ERROR("host system error!\n");
842 
843 	WriteOpReg(EHCI_USBSTS, status);
844 	release_spinlock(&lock);
845 
846 	if (asyncAdvance)
847 		release_sem_etc(fAsyncAdvanceSem, 1, B_DO_NOT_RESCHEDULE);
848 	if (finishTransfers)
849 		release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
850 
851 	return result;
852 }
853 
854 
855 status_t
856 EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead,
857 	ehci_qtd *dataDescriptor, bool directionIn)
858 {
859 	transfer_data *data = new(std::nothrow) transfer_data;
860 	if (!data)
861 		return B_NO_MEMORY;
862 
863 	status_t result = transfer->InitKernelAccess();
864 	if (result < B_OK) {
865 		delete data;
866 		return result;
867 	}
868 
869 	data->transfer = transfer;
870 	data->queue_head = queueHead;
871 	data->data_descriptor = dataDescriptor;
872 	data->incoming = directionIn;
873 	data->canceled = false;
874 	data->link = NULL;
875 
876 	if (!Lock()) {
877 		delete data;
878 		return B_ERROR;
879 	}
880 
881 	if (fLastTransfer)
882 		fLastTransfer->link = data;
883 	else
884 		fFirstTransfer = data;
885 
886 	fLastTransfer = data;
887 	Unlock();
888 
889 	return B_OK;
890 }
891 
892 
893 status_t
894 EHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
895 {
896 	if (!Lock())
897 		return B_ERROR;
898 
899 	struct transfer_entry {
900 		Transfer *			transfer;
901 		transfer_entry *	next;
902 	};
903 
904 	transfer_entry *list = NULL;
905 	transfer_data *current = fFirstTransfer;
906 	while (current) {
907 		if (current->transfer && current->transfer->TransferPipe() == pipe) {
908 			// clear the active bit so the descriptors are canceled
909 			ehci_qtd *descriptor = (ehci_qtd *)current->queue_head->element_log;
910 			while (descriptor) {
911 				descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE;
912 				descriptor = (ehci_qtd *)descriptor->next_log;
913 			}
914 
915 			if (!force) {
916 				// if the transfer is canceled by force, the one causing the
917 				// cancel is probably not the one who initiated the transfer
918 				// and the callback is likely not safe anymore
919 				transfer_entry *entry
920 					= (transfer_entry *)malloc(sizeof(transfer_entry));
921 				if (entry != NULL) {
922 					entry->transfer = current->transfer;
923 					current->transfer = NULL;
924 					entry->next = list;
925 					list = entry;
926 				}
927 			}
928 
929 			current->canceled = true;
930 		}
931 
932 		current = current->link;
933 	}
934 
935 	Unlock();
936 
937 	while (list != NULL) {
938 		transfer_entry *next = list->next;
939 		list->transfer->Finished(B_CANCELED, 0);
940 		delete list->transfer;
941 		free(list);
942 		list = next;
943 	}
944 
945 	// wait for any transfers that might have made it before canceling
946 	while (fProcessingPipe == pipe)
947 		snooze(1000);
948 
949 	// notify the finisher so it can clean up the canceled transfers
950 	release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
951 	return B_OK;
952 }
953 
954 
955 status_t
956 EHCI::CancelAllPendingTransfers()
957 {
958 	if (!Lock())
959 		return B_ERROR;
960 
961 	transfer_data *transfer = fFirstTransfer;
962 	while (transfer) {
963 		transfer->transfer->Finished(B_CANCELED, 0);
964 		delete transfer->transfer;
965 
966 		transfer_data *next = transfer->link;
967 		delete transfer;
968 		transfer = next;
969 	}
970 
971 	fFirstTransfer = NULL;
972 	fLastTransfer = NULL;
973 	Unlock();
974 	return B_OK;
975 }
976 
977 
978 int32
979 EHCI::FinishThread(void *data)
980 {
981 	((EHCI *)data)->FinishTransfers();
982 	return B_OK;
983 }
984 
985 
986 void
987 EHCI::FinishTransfers()
988 {
989 	while (!fStopThreads) {
990 		if (acquire_sem(fFinishTransfersSem) < B_OK)
991 			continue;
992 
993 		// eat up sems that have been released by multiple interrupts
994 		int32 semCount = 0;
995 		get_sem_count(fFinishTransfersSem, &semCount);
996 		if (semCount > 0)
997 			acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
998 
999 		if (!Lock())
1000 			continue;
1001 
1002 		TRACE("finishing transfers\n");
1003 		transfer_data *lastTransfer = NULL;
1004 		transfer_data *transfer = fFirstTransfer;
1005 		Unlock();
1006 
1007 		while (transfer) {
1008 			bool transferDone = false;
1009 			ehci_qtd *descriptor = (ehci_qtd *)transfer->queue_head->element_log;
1010 			status_t callbackStatus = B_OK;
1011 
1012 			while (descriptor) {
1013 				uint32 status = descriptor->token;
1014 				if (status & EHCI_QTD_STATUS_ACTIVE) {
1015 					// still in progress
1016 					TRACE("qtd (0x%08lx) still active\n", descriptor->this_phy);
1017 					break;
1018 				}
1019 
1020 				if (status & EHCI_QTD_STATUS_ERRMASK) {
1021 					// a transfer error occured
1022 					TRACE_ERROR("qtd (0x%08lx) error: 0x%08lx\n", descriptor->this_phy, status);
1023 
1024 					uint8 errorCount = status >> EHCI_QTD_ERRCOUNT_SHIFT;
1025 					errorCount &= EHCI_QTD_ERRCOUNT_MASK;
1026 					if (errorCount == 0) {
1027 						// the error counter counted down to zero, report why
1028 						int32 reasons = 0;
1029 						if (status & EHCI_QTD_STATUS_BUFFER) {
1030 							callbackStatus = transfer->incoming ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN;
1031 							reasons++;
1032 						}
1033 						if (status & EHCI_QTD_STATUS_TERROR) {
1034 							callbackStatus = B_DEV_CRC_ERROR;
1035 							reasons++;
1036 						}
1037 
1038 						if (reasons > 1)
1039 							callbackStatus = B_DEV_MULTIPLE_ERRORS;
1040 					} else if (status & EHCI_QTD_STATUS_BABBLE) {
1041 						// there is a babble condition
1042 						callbackStatus = transfer->incoming ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN;
1043 					} else {
1044 						// if the error counter didn't count down to zero
1045 						// and there was no babble, then this halt was caused
1046 						// by a stall handshake
1047 						callbackStatus = B_DEV_STALLED;
1048 					}
1049 
1050 					transferDone = true;
1051 					break;
1052 				}
1053 
1054 				if (descriptor->next_phy & EHCI_QTD_TERMINATE) {
1055 					// we arrived at the last (stray) descriptor, we're done
1056 					TRACE("qtd (0x%08lx) done\n", descriptor->this_phy);
1057 					callbackStatus = B_OK;
1058 					transferDone = true;
1059 					break;
1060 				}
1061 
1062 				descriptor = (ehci_qtd *)descriptor->next_log;
1063 			}
1064 
1065 			if (!transferDone) {
1066 				lastTransfer = transfer;
1067 				transfer = transfer->link;
1068 				continue;
1069 			}
1070 
1071 			// remove the transfer from the list first so we are sure
1072 			// it doesn't get canceled while we still process it
1073 			transfer_data *next = transfer->link;
1074 			if (Lock()) {
1075 				if (lastTransfer)
1076 					lastTransfer->link = transfer->link;
1077 
1078 				if (transfer == fFirstTransfer)
1079 					fFirstTransfer = transfer->link;
1080 				if (transfer == fLastTransfer)
1081 					fLastTransfer = lastTransfer;
1082 
1083 				// store the currently processing pipe here so we can wait
1084 				// in cancel if we are processing something on the target pipe
1085 				if (!transfer->canceled)
1086 					fProcessingPipe = transfer->transfer->TransferPipe();
1087 
1088 				transfer->link = NULL;
1089 				Unlock();
1090 			}
1091 
1092 			// if canceled the callback has already been called
1093 			if (!transfer->canceled) {
1094 				size_t actualLength = 0;
1095 
1096 				if (callbackStatus == B_OK) {
1097 					bool nextDataToggle = false;
1098 					if (transfer->data_descriptor && transfer->incoming) {
1099 						// data to read out
1100 						iovec *vector = transfer->transfer->Vector();
1101 						size_t vectorCount = transfer->transfer->VectorCount();
1102 						transfer->transfer->PrepareKernelAccess();
1103 						actualLength = ReadDescriptorChain(
1104 							transfer->data_descriptor,
1105 							vector, vectorCount,
1106 							&nextDataToggle);
1107 					} else if (transfer->data_descriptor) {
1108 						// calculate transfered length
1109 						actualLength = ReadActualLength(
1110 							transfer->data_descriptor, &nextDataToggle);
1111 					}
1112 
1113 					transfer->transfer->TransferPipe()->SetDataToggle(nextDataToggle);
1114 
1115 					if (transfer->transfer->IsFragmented()) {
1116 						// this transfer may still have data left
1117 						transfer->transfer->AdvanceByFragment(actualLength);
1118 						if (transfer->transfer->VectorLength() > 0) {
1119 							FreeDescriptorChain(transfer->data_descriptor);
1120 							transfer->transfer->PrepareKernelAccess();
1121 							status_t result = FillQueueWithData(
1122 								transfer->transfer,
1123 								transfer->queue_head,
1124 								&transfer->data_descriptor, NULL);
1125 
1126 							if (result == B_OK && Lock()) {
1127 								// reappend the transfer
1128 								if (fLastTransfer)
1129 									fLastTransfer->link = transfer;
1130 								if (!fFirstTransfer)
1131 									fFirstTransfer = transfer;
1132 
1133 								fLastTransfer = transfer;
1134 								Unlock();
1135 
1136 								transfer = next;
1137 								continue;
1138 							}
1139 						}
1140 
1141 						// the transfer is done, but we already set the
1142 						// actualLength with AdvanceByFragment()
1143 						actualLength = 0;
1144 					}
1145 				}
1146 
1147 				transfer->transfer->Finished(callbackStatus, actualLength);
1148 				fProcessingPipe = NULL;
1149 			}
1150 
1151 			// unlink hardware queue and delete the transfer
1152 			UnlinkQueueHead(transfer->queue_head, &fFreeListHead);
1153 			delete transfer->transfer;
1154 			delete transfer;
1155 			transfer = next;
1156 			release_sem(fCleanupSem);
1157 		}
1158 	}
1159 }
1160 
1161 
1162 int32
1163 EHCI::CleanupThread(void *data)
1164 {
1165 	((EHCI *)data)->Cleanup();
1166 	return B_OK;
1167 }
1168 
1169 
1170 void
1171 EHCI::Cleanup()
1172 {
1173 	ehci_qh *lastFreeListHead = NULL;
1174 
1175 	while (!fStopThreads) {
1176 		if (acquire_sem(fCleanupSem) < B_OK)
1177 			continue;
1178 
1179 		ehci_qh *freeListHead = fFreeListHead;
1180 		if (freeListHead == lastFreeListHead)
1181 			continue;
1182 
1183 		// set the doorbell and wait for the host controller to notify us
1184 		WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_INTONAAD);
1185 		if (acquire_sem(fAsyncAdvanceSem) < B_OK)
1186 			continue;
1187 
1188 		ehci_qh *current = freeListHead;
1189 		while (current != lastFreeListHead) {
1190 			ehci_qh *next = (ehci_qh *)current->next_log;
1191 			FreeQueueHead(current);
1192 			current = next;
1193 		}
1194 
1195 		lastFreeListHead = freeListHead;
1196 	}
1197 }
1198 
1199 
1200 ehci_qh *
1201 EHCI::CreateQueueHead()
1202 {
1203 	ehci_qh *result;
1204 	void *physicalAddress;
1205 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
1206 		sizeof(ehci_qh)) < B_OK) {
1207 		TRACE_ERROR("failed to allocate queue head\n");
1208 		return NULL;
1209 	}
1210 
1211 	result->this_phy = (addr_t)physicalAddress;
1212 	result->next_phy = EHCI_QH_TERMINATE;
1213 	result->next_log = NULL;
1214 	result->prev_log = NULL;
1215 
1216 	ehci_qtd *descriptor = CreateDescriptor(0, 0);
1217 	if (!descriptor) {
1218 		TRACE_ERROR("failed to allocate initial qtd for queue head\n");
1219 		fStack->FreeChunk(result, (void *)result->this_phy, sizeof(ehci_qh));
1220 		return NULL;
1221 	}
1222 
1223 	descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE;
1224 	result->stray_log = descriptor;
1225 	result->element_log = descriptor;
1226 	result->current_qtd_phy = EHCI_QTD_TERMINATE;
1227 	result->overlay.next_phy = descriptor->this_phy;
1228 	result->overlay.alt_next_phy = EHCI_QTD_TERMINATE;
1229 	result->overlay.token = 0;
1230 	for (int32 i = 0; i < 5; i++) {
1231 		result->overlay.buffer_phy[i] = 0;
1232 		result->overlay.ext_buffer_phy[i] = 0;
1233 	}
1234 
1235 	return result;
1236 }
1237 
1238 
1239 status_t
1240 EHCI::InitQueueHead(ehci_qh *queueHead, Pipe *pipe)
1241 {
1242 	switch (pipe->Speed()) {
1243 		case USB_SPEED_LOWSPEED:
1244 			queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_LOW;
1245 			break;
1246 		case USB_SPEED_FULLSPEED:
1247 			queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_FULL;
1248 			break;
1249 		case USB_SPEED_HIGHSPEED:
1250 			queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH;
1251 			break;
1252 		default:
1253 			TRACE_ERROR("unknown pipe speed\n");
1254 			return B_ERROR;
1255 	}
1256 
1257 	queueHead->endpoint_chars |= (3 << EHCI_QH_CHARS_RL_SHIFT)
1258 		| (pipe->MaxPacketSize() << EHCI_QH_CHARS_MPL_SHIFT)
1259 		| (pipe->EndpointAddress() << EHCI_QH_CHARS_EPT_SHIFT)
1260 		| (pipe->DeviceAddress() << EHCI_QH_CHARS_DEV_SHIFT)
1261 		| EHCI_QH_CHARS_TOGGLE;
1262 
1263 	queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT);
1264 	if (pipe->Speed() != USB_SPEED_HIGHSPEED) {
1265 		if (pipe->Type() & USB_OBJECT_CONTROL_PIPE)
1266 			queueHead->endpoint_chars |= EHCI_QH_CHARS_CONTROL;
1267 
1268 		queueHead->endpoint_caps |= (pipe->HubPort() << EHCI_QH_CAPS_PORT_SHIFT)
1269 			| (pipe->HubAddress() << EHCI_QH_CAPS_HUB_SHIFT);
1270 	}
1271 
1272 	return B_OK;
1273 }
1274 
1275 
1276 void
1277 EHCI::FreeQueueHead(ehci_qh *queueHead)
1278 {
1279 	if (!queueHead)
1280 		return;
1281 
1282 	FreeDescriptorChain((ehci_qtd *)queueHead->element_log);
1283 	FreeDescriptor((ehci_qtd *)queueHead->stray_log);
1284 	fStack->FreeChunk(queueHead, (void *)queueHead->this_phy, sizeof(ehci_qh));
1285 }
1286 
1287 
1288 status_t
1289 EHCI::LinkQueueHead(ehci_qh *queueHead)
1290 {
1291 	if (!Lock())
1292 		return B_ERROR;
1293 
1294 	ehci_qh *prevHead = (ehci_qh *)fAsyncQueueHead->prev_log;
1295 	queueHead->next_phy = fAsyncQueueHead->this_phy | EHCI_QH_TYPE_QH;
1296 	queueHead->next_log = fAsyncQueueHead;
1297 	queueHead->prev_log = prevHead;
1298 	fAsyncQueueHead->prev_log = queueHead;
1299 	prevHead->next_log = queueHead;
1300 	prevHead->next_phy = queueHead->this_phy | EHCI_QH_TYPE_QH;
1301 
1302 	Unlock();
1303 	return B_OK;
1304 }
1305 
1306 
1307 status_t
1308 EHCI::LinkInterruptQueueHead(ehci_qh *queueHead, Pipe *pipe)
1309 {
1310 	if (!Lock())
1311 		return B_ERROR;
1312 
1313 	uint8 interval = pipe->Interval();
1314 	if (pipe->Speed() == USB_SPEED_HIGHSPEED) {
1315 		// Allow interrupts to be scheduled on each possible micro frame.
1316 		queueHead->endpoint_caps |= (0xff << EHCI_QH_CAPS_ISM_SHIFT);
1317 	} else {
1318 		// As we do not yet support FSTNs to correctly reference low/full
1319 		// speed interrupt transfers, we simply put them into the 1 interval
1320 		// queue. This way we ensure that we reach them on every micro frame
1321 		// and can do the corresponding start/complete split transactions.
1322 		// ToDo: use FSTNs to correctly link non high speed interrupt transfers
1323 		interval = 1;
1324 
1325 		// For now we also force start splits to be in micro frame 0 and
1326 		// complete splits to be in micro frame 2, 3 and 4.
1327 		queueHead->endpoint_caps |= (0x01 << EHCI_QH_CAPS_ISM_SHIFT);
1328 		queueHead->endpoint_caps |= (0x1c << EHCI_QH_CAPS_SCM_SHIFT);
1329 	}
1330 
1331 	// this should not happen
1332 	if (interval < 1)
1333 		interval = 1;
1334 
1335 	// this may happen as intervals can go up to 16; we limit the value to
1336 	// 11 as you cannot support intervals above that with a frame list of
1337 	// just 1024 entries...
1338 	if (interval > 11)
1339 		interval = 11;
1340 
1341 	ehci_qh *interruptQueue = &fInterruptEntries[interval - 1].queue_head;
1342 	queueHead->next_phy = interruptQueue->next_phy;
1343 	queueHead->next_log = interruptQueue->next_log;
1344 	queueHead->prev_log = interruptQueue;
1345 	if (interruptQueue->next_log)
1346 		((ehci_qh *)interruptQueue->next_log)->prev_log = queueHead;
1347 	interruptQueue->next_log = queueHead;
1348 	interruptQueue->next_phy = queueHead->this_phy | EHCI_QH_TYPE_QH;
1349 
1350 	Unlock();
1351 	return B_OK;
1352 }
1353 
1354 
1355 status_t
1356 EHCI::UnlinkQueueHead(ehci_qh *queueHead, ehci_qh **freeListHead)
1357 {
1358 	if (!Lock())
1359 		return B_ERROR;
1360 
1361 	ehci_qh *prevHead = (ehci_qh *)queueHead->prev_log;
1362 	ehci_qh *nextHead = (ehci_qh *)queueHead->next_log;
1363 	if (prevHead) {
1364 		prevHead->next_phy = queueHead->next_phy | EHCI_QH_TYPE_QH;
1365 		prevHead->next_log = queueHead->next_log;
1366 	}
1367 
1368 	if (nextHead)
1369 		nextHead->prev_log = queueHead->prev_log;
1370 
1371 	queueHead->next_phy = fAsyncQueueHead->this_phy | EHCI_QH_TYPE_QH;
1372 	queueHead->prev_log = NULL;
1373 
1374 	queueHead->next_log = *freeListHead;
1375 	*freeListHead = queueHead;
1376 
1377 	Unlock();
1378 	return B_OK;
1379 }
1380 
1381 
1382 status_t
1383 EHCI::FillQueueWithRequest(Transfer *transfer, ehci_qh *queueHead,
1384 	ehci_qtd **_dataDescriptor, bool *_directionIn)
1385 {
1386 	Pipe *pipe = transfer->TransferPipe();
1387 	usb_request_data *requestData = transfer->RequestData();
1388 	bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0;
1389 
1390 	ehci_qtd *setupDescriptor = CreateDescriptor(sizeof(usb_request_data),
1391 		EHCI_QTD_PID_SETUP);
1392 	ehci_qtd *statusDescriptor = CreateDescriptor(0,
1393 		directionIn ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN);
1394 
1395 	if (!setupDescriptor || !statusDescriptor) {
1396 		TRACE_ERROR("failed to allocate descriptors\n");
1397 		FreeDescriptor(setupDescriptor);
1398 		FreeDescriptor(statusDescriptor);
1399 		return B_NO_MEMORY;
1400 	}
1401 
1402 	iovec vector;
1403 	vector.iov_base = requestData;
1404 	vector.iov_len = sizeof(usb_request_data);
1405 	WriteDescriptorChain(setupDescriptor, &vector, 1);
1406 
1407 	ehci_qtd *strayDescriptor = (ehci_qtd *)queueHead->stray_log;
1408 	statusDescriptor->token |= EHCI_QTD_IOC | EHCI_QTD_DATA_TOGGLE;
1409 
1410 	ehci_qtd *dataDescriptor = NULL;
1411 	if (transfer->VectorCount() > 0) {
1412 		ehci_qtd *lastDescriptor = NULL;
1413 		status_t result = CreateDescriptorChain(pipe, &dataDescriptor,
1414 			&lastDescriptor, strayDescriptor, transfer->VectorLength(),
1415 			directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT);
1416 
1417 		if (result < B_OK) {
1418 			FreeDescriptor(setupDescriptor);
1419 			FreeDescriptor(statusDescriptor);
1420 			return result;
1421 		}
1422 
1423 		if (!directionIn) {
1424 			WriteDescriptorChain(dataDescriptor, transfer->Vector(),
1425 				transfer->VectorCount());
1426 		}
1427 
1428 		LinkDescriptors(setupDescriptor, dataDescriptor, strayDescriptor);
1429 		LinkDescriptors(lastDescriptor, statusDescriptor, strayDescriptor);
1430 	} else {
1431 		// no data: link setup and status descriptors directly
1432 		LinkDescriptors(setupDescriptor, statusDescriptor, strayDescriptor);
1433 	}
1434 
1435 	queueHead->element_log = setupDescriptor;
1436 	queueHead->overlay.next_phy = setupDescriptor->this_phy;
1437 	queueHead->overlay.alt_next_phy = EHCI_QTD_TERMINATE;
1438 
1439 	*_dataDescriptor = dataDescriptor;
1440 	*_directionIn = directionIn;
1441 	return B_OK;
1442 }
1443 
1444 
1445 status_t
1446 EHCI::FillQueueWithData(Transfer *transfer, ehci_qh *queueHead,
1447 	ehci_qtd **_dataDescriptor, bool *_directionIn)
1448 {
1449 	Pipe *pipe = transfer->TransferPipe();
1450 	bool directionIn = (pipe->Direction() == Pipe::In);
1451 
1452 	ehci_qtd *firstDescriptor = NULL;
1453 	ehci_qtd *lastDescriptor = NULL;
1454 	ehci_qtd *strayDescriptor = (ehci_qtd *)queueHead->stray_log;
1455 	status_t result = CreateDescriptorChain(pipe, &firstDescriptor,
1456 		&lastDescriptor, strayDescriptor, transfer->VectorLength(),
1457 		directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT);
1458 
1459 	if (result < B_OK)
1460 		return result;
1461 
1462 	lastDescriptor->token |= EHCI_QTD_IOC;
1463 	if (!directionIn) {
1464 		WriteDescriptorChain(firstDescriptor, transfer->Vector(),
1465 			transfer->VectorCount());
1466 	}
1467 
1468 	queueHead->element_log = firstDescriptor;
1469 	queueHead->overlay.next_phy = firstDescriptor->this_phy;
1470 	queueHead->overlay.alt_next_phy = EHCI_QTD_TERMINATE;
1471 
1472 	*_dataDescriptor = firstDescriptor;
1473 	if (_directionIn)
1474 		*_directionIn = directionIn;
1475 	return B_OK;
1476 }
1477 
1478 
1479 ehci_qtd *
1480 EHCI::CreateDescriptor(size_t bufferSize, uint8 pid)
1481 {
1482 	ehci_qtd *result;
1483 	void *physicalAddress;
1484 	if (fStack->AllocateChunk((void **)&result, &physicalAddress,
1485 		sizeof(ehci_qtd)) < B_OK) {
1486 		TRACE_ERROR("failed to allocate a qtd\n");
1487 		return NULL;
1488 	}
1489 
1490 	result->this_phy = (addr_t)physicalAddress;
1491 	result->next_phy = EHCI_QTD_TERMINATE;
1492 	result->next_log = NULL;
1493 	result->alt_next_phy = EHCI_QTD_TERMINATE;
1494 	result->alt_next_log = NULL;
1495 	result->buffer_size = bufferSize;
1496 	result->token = bufferSize << EHCI_QTD_BYTES_SHIFT;
1497 	result->token |= 3 << EHCI_QTD_ERRCOUNT_SHIFT;
1498 	result->token |= pid << EHCI_QTD_PID_SHIFT;
1499 	result->token |= EHCI_QTD_STATUS_ACTIVE;
1500 	if (bufferSize == 0) {
1501 		result->buffer_log = NULL;
1502 		for (int32 i = 0; i < 5; i++) {
1503 			result->buffer_phy[i] = 0;
1504 			result->ext_buffer_phy[i] = 0;
1505 		}
1506 
1507 		return result;
1508 	}
1509 
1510 	if (fStack->AllocateChunk(&result->buffer_log, &physicalAddress,
1511 		bufferSize) < B_OK) {
1512 		TRACE_ERROR("unable to allocate qtd buffer\n");
1513 		fStack->FreeChunk(result, (void *)result->this_phy, sizeof(ehci_qtd));
1514 		return NULL;
1515 	}
1516 
1517 	addr_t physicalBase = (addr_t)physicalAddress;
1518 	result->buffer_phy[0] = physicalBase;
1519 	result->ext_buffer_phy[0] = 0;
1520 	for (int32 i = 1; i < 5; i++) {
1521 		physicalBase += B_PAGE_SIZE;
1522 		result->buffer_phy[i] = physicalBase & EHCI_QTD_PAGE_MASK;
1523 		result->ext_buffer_phy[i] = 0;
1524 	}
1525 
1526 	return result;
1527 }
1528 
1529 
1530 status_t
1531 EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **_firstDescriptor,
1532 	ehci_qtd **_lastDescriptor, ehci_qtd *strayDescriptor, size_t bufferSize,
1533 	uint8 pid)
1534 {
1535 	size_t packetSize = B_PAGE_SIZE * 4;
1536 	int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize;
1537 
1538 	bool dataToggle = pipe->DataToggle();
1539 	ehci_qtd *firstDescriptor = NULL;
1540 	ehci_qtd *lastDescriptor = *_firstDescriptor;
1541 	for (int32 i = 0; i < descriptorCount; i++) {
1542 		ehci_qtd *descriptor = CreateDescriptor(min_c(packetSize, bufferSize),
1543 			pid);
1544 
1545 		if (!descriptor) {
1546 			FreeDescriptorChain(firstDescriptor);
1547 			return B_NO_MEMORY;
1548 		}
1549 
1550 		if (dataToggle)
1551 			descriptor->token |= EHCI_QTD_DATA_TOGGLE;
1552 
1553 		if (lastDescriptor)
1554 			LinkDescriptors(lastDescriptor, descriptor, strayDescriptor);
1555 
1556 		bufferSize -= packetSize;
1557 		lastDescriptor = descriptor;
1558 		if (!firstDescriptor)
1559 			firstDescriptor = descriptor;
1560 	}
1561 
1562 	*_firstDescriptor = firstDescriptor;
1563 	*_lastDescriptor = lastDescriptor;
1564 	return B_OK;
1565 }
1566 
1567 
1568 void
1569 EHCI::FreeDescriptor(ehci_qtd *descriptor)
1570 {
1571 	if (!descriptor)
1572 		return;
1573 
1574 	if (descriptor->buffer_log) {
1575 		fStack->FreeChunk(descriptor->buffer_log,
1576 			(void *)descriptor->buffer_phy[0], descriptor->buffer_size);
1577 	}
1578 
1579 	fStack->FreeChunk(descriptor, (void *)descriptor->this_phy, sizeof(ehci_qtd));
1580 }
1581 
1582 
1583 void
1584 EHCI::FreeDescriptorChain(ehci_qtd *topDescriptor)
1585 {
1586 	ehci_qtd *current = topDescriptor;
1587 	ehci_qtd *next = NULL;
1588 
1589 	while (current) {
1590 		next = (ehci_qtd *)current->next_log;
1591 		FreeDescriptor(current);
1592 		current = next;
1593 	}
1594 }
1595 
1596 
1597 void
1598 EHCI::LinkDescriptors(ehci_qtd *first, ehci_qtd *last, ehci_qtd *alt)
1599 {
1600 	first->next_phy = last->this_phy;
1601 	first->next_log = last;
1602 
1603 	if (alt) {
1604 		first->alt_next_phy = alt->this_phy;
1605 		first->alt_next_log = alt;
1606 	} else {
1607 		first->alt_next_phy = EHCI_QTD_TERMINATE;
1608 		first->alt_next_log = NULL;
1609 	}
1610 }
1611 
1612 
1613 size_t
1614 EHCI::WriteDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
1615 	size_t vectorCount)
1616 {
1617 	ehci_qtd *current = topDescriptor;
1618 	size_t actualLength = 0;
1619 	size_t vectorIndex = 0;
1620 	size_t vectorOffset = 0;
1621 	size_t bufferOffset = 0;
1622 
1623 	while (current) {
1624 		if (!current->buffer_log)
1625 			break;
1626 
1627 		while (true) {
1628 			size_t length = min_c(current->buffer_size - bufferOffset,
1629 				vector[vectorIndex].iov_len - vectorOffset);
1630 
1631 			memcpy((uint8 *)current->buffer_log + bufferOffset,
1632 				(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
1633 
1634 			actualLength += length;
1635 			vectorOffset += length;
1636 			bufferOffset += length;
1637 
1638 			if (vectorOffset >= vector[vectorIndex].iov_len) {
1639 				if (++vectorIndex >= vectorCount) {
1640 					TRACE("wrote descriptor chain (%ld bytes, no more vectors)\n", actualLength);
1641 					return actualLength;
1642 				}
1643 
1644 				vectorOffset = 0;
1645 			}
1646 
1647 			if (bufferOffset >= current->buffer_size) {
1648 				bufferOffset = 0;
1649 				break;
1650 			}
1651 		}
1652 
1653 		if (current->next_phy & EHCI_QTD_TERMINATE)
1654 			break;
1655 
1656 		current = (ehci_qtd *)current->next_log;
1657 	}
1658 
1659 	TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
1660 	return actualLength;
1661 }
1662 
1663 
1664 size_t
1665 EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
1666 	size_t vectorCount, bool *nextDataToggle)
1667 {
1668 	uint32 dataToggle = 0;
1669 	ehci_qtd *current = topDescriptor;
1670 	size_t actualLength = 0;
1671 	size_t vectorIndex = 0;
1672 	size_t vectorOffset = 0;
1673 	size_t bufferOffset = 0;
1674 
1675 	while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) {
1676 		if (!current->buffer_log)
1677 			break;
1678 
1679 		dataToggle = current->token & EHCI_QTD_DATA_TOGGLE;
1680 		size_t bufferSize = current->buffer_size;
1681 		bufferSize -= (current->token >> EHCI_QTD_BYTES_SHIFT) & EHCI_QTD_BYTES_MASK;
1682 
1683 		while (true) {
1684 			size_t length = min_c(bufferSize - bufferOffset,
1685 				vector[vectorIndex].iov_len - vectorOffset);
1686 
1687 			memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
1688 				(uint8 *)current->buffer_log + bufferOffset, length);
1689 
1690 			actualLength += length;
1691 			vectorOffset += length;
1692 			bufferOffset += length;
1693 
1694 			if (vectorOffset >= vector[vectorIndex].iov_len) {
1695 				if (++vectorIndex >= vectorCount) {
1696 					TRACE("read descriptor chain (%ld bytes, no more vectors)\n", actualLength);
1697 					*nextDataToggle = dataToggle > 0 ? true : false;
1698 					return actualLength;
1699 				}
1700 
1701 				vectorOffset = 0;
1702 			}
1703 
1704 			if (bufferOffset >= bufferSize) {
1705 				bufferOffset = 0;
1706 				break;
1707 			}
1708 		}
1709 
1710 		if (current->next_phy & EHCI_QTD_TERMINATE)
1711 			break;
1712 
1713 		current = (ehci_qtd *)current->next_log;
1714 	}
1715 
1716 	TRACE("read descriptor chain (%ld bytes)\n", actualLength);
1717 	*nextDataToggle = dataToggle > 0 ? true : false;
1718 	return actualLength;
1719 }
1720 
1721 
1722 size_t
1723 EHCI::ReadActualLength(ehci_qtd *topDescriptor, bool *nextDataToggle)
1724 {
1725 	size_t actualLength = 0;
1726 	ehci_qtd *current = topDescriptor;
1727 	uint32 dataToggle = 0;
1728 
1729 	while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) {
1730 		dataToggle = current->token & EHCI_QTD_DATA_TOGGLE;
1731 		size_t length = current->buffer_size;
1732 		length -= (current->token >> EHCI_QTD_BYTES_SHIFT) & EHCI_QTD_BYTES_MASK;
1733 		actualLength += length;
1734 
1735 		if (current->next_phy & EHCI_QTD_TERMINATE)
1736 			break;
1737 
1738 		current = (ehci_qtd *)current->next_log;
1739 	}
1740 
1741 	TRACE("read actual length (%ld bytes)\n", actualLength);
1742 	*nextDataToggle = dataToggle > 0 ? true : false;
1743 	return actualLength;
1744 }
1745 
1746 
1747 inline void
1748 EHCI::WriteOpReg(uint32 reg, uint32 value)
1749 {
1750 	*(volatile uint32 *)(fOperationalRegisters + reg) = value;
1751 }
1752 
1753 
1754 inline uint32
1755 EHCI::ReadOpReg(uint32 reg)
1756 {
1757 	return *(volatile uint32 *)(fOperationalRegisters + reg);
1758 }
1759 
1760 
1761 inline uint8
1762 EHCI::ReadCapReg8(uint32 reg)
1763 {
1764 	return *(volatile uint8 *)(fCapabilityRegisters + reg);
1765 }
1766 
1767 
1768 inline uint16
1769 EHCI::ReadCapReg16(uint32 reg)
1770 {
1771 	return *(volatile uint16 *)(fCapabilityRegisters + reg);
1772 }
1773 
1774 
1775 inline uint32
1776 EHCI::ReadCapReg32(uint32 reg)
1777 {
1778 	return *(volatile uint32 *)(fCapabilityRegisters + reg);
1779 }
1780