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