xref: /haiku/src/add-ons/kernel/busses/usb/ohci.cpp (revision 1b80286772b529a3d6de3bbeb0720c62e6a32fed)
1 /*
2  * Copyright 2005-2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Jan-Rixt Van Hoye
7  *		Salvatore Benedetto <salvatore.benedetto@gmail.com>
8  *		Michael Lotz <mmlr@mlotz.ch>
9  */
10 
11 #include <module.h>
12 #include <PCI.h>
13 #include <USB3.h>
14 #include <KernelExport.h>
15 
16 #include "ohci.h"
17 
18 #define USB_MODULE_NAME "ohci"
19 
20 pci_module_info *OHCI::sPCIModule = NULL;
21 
22 
23 static int32
24 ohci_std_ops(int32 op, ...)
25 {
26 	switch (op)	{
27 		case B_MODULE_INIT:
28 			TRACE_MODULE("init module\n");
29 			return B_OK;
30 		case B_MODULE_UNINIT:
31 			TRACE_MODULE("uninit module\n");
32 			return B_OK;
33 	}
34 
35 	return EINVAL;
36 }
37 
38 
39 usb_host_controller_info ohci_module = {
40 	{
41 		"busses/usb/ohci",
42 		0,
43 		ohci_std_ops
44 	},
45 	NULL,
46 	OHCI::AddTo
47 };
48 
49 
50 module_info *modules[] = {
51 	(module_info *)&ohci_module,
52 	NULL
53 };
54 
55 
56 OHCI::OHCI(pci_info *info, Stack *stack)
57 	:	BusManager(stack),
58 		fPCIInfo(info),
59 		fStack(stack),
60 		fOperationalRegisters(NULL),
61 		fRegisterArea(-1),
62 		fHccaArea(-1),
63 		fHcca(NULL),
64 		fInterruptEndpoints(NULL),
65 		fDummyControl(NULL),
66 		fDummyBulk(NULL),
67 		fDummyIsochronous(NULL),
68 		fFirstTransfer(NULL),
69 		fLastTransfer(NULL),
70 		fFinishTransfersSem(-1),
71 		fFinishThread(-1),
72 		fStopFinishThread(false),
73 		fRootHub(NULL),
74 		fRootHubAddress(0),
75 		fPortCount(0)
76 {
77 	if (!fInitOK) {
78 		TRACE_ERROR("bus manager failed to init\n");
79 		return;
80 	}
81 
82 	TRACE("constructing new OHCI host controller driver\n");
83 	fInitOK = false;
84 
85 	mutex_init(&fEndpointLock, "ohci endpoint lock");
86 
87 	// enable busmaster and memory mapped access
88 	uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
89 		fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
90 	command &= ~PCI_command_io;
91 	command |= PCI_command_master | PCI_command_memory;
92 
93 	sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
94 		fPCIInfo->function, PCI_command, 2, command);
95 
96 	// map the registers
97 	uint32 offset = sPCIModule->read_pci_config(fPCIInfo->bus,
98 		fPCIInfo->device, fPCIInfo->function, PCI_base_registers, 4);
99 	offset &= PCI_address_memory_32_mask;
100 	TRACE_ALWAYS("iospace offset: 0x%lx\n", offset);
101 	fRegisterArea = map_physical_memory("OHCI memory mapped registers",
102 		(void *)offset,	B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS,
103 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA,
104 		(void **)&fOperationalRegisters);
105 	if (fRegisterArea < B_OK) {
106 		TRACE_ERROR("failed to map register memory\n");
107 		return;
108 	}
109 
110 	TRACE("mapped operational registers: %p\n", fOperationalRegisters);
111 
112 	// Check the revision of the controller, which should be 10h
113 	uint32 revision = _ReadReg(OHCI_REVISION) & 0xff;
114 	TRACE("version %ld.%ld%s\n", OHCI_REVISION_HIGH(revision),
115 		OHCI_REVISION_LOW(revision), OHCI_REVISION_LEGACY(revision)
116 		? ", legacy support" : "");
117 	if (OHCI_REVISION_HIGH(revision) != 1 || OHCI_REVISION_LOW(revision) != 0) {
118 		TRACE_ERROR("unsupported OHCI revision\n");
119 		return;
120 	}
121 
122 	void *hccaPhysicalAddress;
123 	fHccaArea = fStack->AllocateArea((void **)&fHcca, &hccaPhysicalAddress,
124 		sizeof(ohci_hcca), "USB OHCI Host Controller Communication Area");
125 
126 	if (fHccaArea < B_OK) {
127 		TRACE_ERROR("unable to create the HCCA block area\n");
128 		return;
129 	}
130 
131 	memset(fHcca, 0, sizeof(ohci_hcca));
132 
133 	// Set Up Host controller
134 	// Dummy endpoints
135 	fDummyControl = _AllocateEndpoint();
136 	if (!fDummyControl)
137 		return;
138 
139 	fDummyBulk = _AllocateEndpoint();
140 	if (!fDummyBulk) {
141 		_FreeEndpoint(fDummyControl);
142 		return;
143 	}
144 
145 	fDummyIsochronous = _AllocateEndpoint();
146 	if (!fDummyIsochronous) {
147 		_FreeEndpoint(fDummyControl);
148 		_FreeEndpoint(fDummyBulk);
149 		return;
150 	}
151 
152 	// Static endpoints that get linked in the HCCA
153 	fInterruptEndpoints = new(std::nothrow)
154 		ohci_endpoint_descriptor *[OHCI_STATIC_ENDPOINT_COUNT];
155 	if (!fInterruptEndpoints) {
156 		TRACE_ERROR("failed to allocate memory for interrupt endpoints\n");
157 		_FreeEndpoint(fDummyControl);
158 		_FreeEndpoint(fDummyBulk);
159 		_FreeEndpoint(fDummyIsochronous);
160 		return;
161 	}
162 
163 	for (int32 i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
164 		fInterruptEndpoints[i] = _AllocateEndpoint();
165 		if (!fInterruptEndpoints[i]) {
166 			TRACE_ERROR("failed to allocate interrupt endpoint %ld", i);
167 			while (--i >= 0)
168 				_FreeEndpoint(fInterruptEndpoints[i]);
169 			_FreeEndpoint(fDummyBulk);
170 			_FreeEndpoint(fDummyControl);
171 			_FreeEndpoint(fDummyIsochronous);
172 			return;
173 		}
174 	}
175 
176 	// build flat tree so that at each of the static interrupt endpoints
177 	// fInterruptEndpoints[i] == interrupt endpoint for interval 2^i
178 	uint32 interval = OHCI_BIGGEST_INTERVAL;
179 	uint32 intervalIndex = OHCI_STATIC_ENDPOINT_COUNT - 1;
180 	while (interval > 1) {
181 		uint32 insertIndex = interval / 2;
182 		while (insertIndex < OHCI_BIGGEST_INTERVAL) {
183 			fHcca->interrupt_table[insertIndex]
184 				= fInterruptEndpoints[intervalIndex]->physical_address;
185 			insertIndex += interval;
186 		}
187 
188 		intervalIndex--;
189 		interval /= 2;
190 	}
191 
192 	// setup the empty slot in the list and linking of all -> first
193 	fHcca->interrupt_table[0] = fInterruptEndpoints[0]->physical_address;
194 	for (int32 i = 1; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
195 		fInterruptEndpoints[i]->next_physical_endpoint
196 			= fInterruptEndpoints[0]->physical_address;
197 		fInterruptEndpoints[i]->next_logical_endpoint
198 			= fInterruptEndpoints[0];
199 	}
200 
201 	// Now link the first endpoint to the isochronous endpoint
202 	fInterruptEndpoints[0]->next_physical_endpoint
203 		= fDummyIsochronous->physical_address;
204 
205 	// Determine in what context we are running (Kindly copied from FreeBSD)
206 	uint32 control = _ReadReg(OHCI_CONTROL);
207 	if (control & OHCI_INTERRUPT_ROUTING) {
208 		TRACE_ALWAYS("smm is in control of the host controller\n");
209 		uint32 status = _ReadReg(OHCI_COMMAND_STATUS);
210 		_WriteReg(OHCI_COMMAND_STATUS, status | OHCI_OWNERSHIP_CHANGE_REQUEST);
211 		for (uint32 i = 0; i < 100 && (control & OHCI_INTERRUPT_ROUTING); i++) {
212 			snooze(1000);
213 			control = _ReadReg(OHCI_CONTROL);
214 		}
215 
216 		if ((control & OHCI_INTERRUPT_ROUTING) != 0) {
217 			TRACE_ERROR("smm does not respond. resetting...\n");
218 			_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
219 			snooze(USB_DELAY_BUS_RESET);
220 		} else
221 			TRACE_ALWAYS("ownership change successful\n");
222 	} else {
223 		TRACE("cold started\n");
224 		snooze(USB_DELAY_BUS_RESET);
225 	}
226 
227 	// This reset should not be necessary according to the OHCI spec, but
228 	// without it some controllers do not start.
229 	_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
230 	snooze(USB_DELAY_BUS_RESET);
231 
232 	// We now own the host controller and the bus has been reset
233 	uint32 frameInterval = _ReadReg(OHCI_FRAME_INTERVAL);
234 	uint32 intervalValue = OHCI_GET_INTERVAL_VALUE(frameInterval);
235 
236 	// Disable interrupts right before we reset
237 	_WriteReg(OHCI_COMMAND_STATUS, OHCI_HOST_CONTROLLER_RESET);
238 	// Nominal time for a reset is 10 us
239 	uint32 reset = 0;
240 	for (uint32 i = 0; i < 10; i++) {
241 		spin(10);
242 		reset = _ReadReg(OHCI_COMMAND_STATUS) & OHCI_HOST_CONTROLLER_RESET;
243 		if (reset == 0)
244 			break;
245 	}
246 
247 	if (reset) {
248 		TRACE_ERROR("error resetting the host controller (timeout)\n");
249 		return;
250 	}
251 
252 	// The controller is now in SUSPEND state, we have 2ms to go OPERATIONAL.
253 	// Interrupts are disabled.
254 
255 	// Set up host controller register
256 	_WriteReg(OHCI_HCCA, (uint32)hccaPhysicalAddress);
257 	_WriteReg(OHCI_CONTROL_HEAD_ED, (uint32)fDummyControl->physical_address);
258 	_WriteReg(OHCI_BULK_HEAD_ED, (uint32)fDummyBulk->physical_address);
259 	// Disable all interrupts
260 	_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS);
261 	// Switch on desired functional features
262 	control = _ReadReg(OHCI_CONTROL);
263 	control &= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK | OHCI_ENABLE_LIST
264 		| OHCI_HC_FUNCTIONAL_STATE_MASK | OHCI_INTERRUPT_ROUTING);
265 	control |= OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4
266 		| OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL;
267 	// And finally start the controller
268 	_WriteReg(OHCI_CONTROL, control);
269 
270 	// The controller is now OPERATIONAL.
271 	frameInterval = (_ReadReg(OHCI_FRAME_INTERVAL) & OHCI_FRAME_INTERVAL_TOGGLE)
272 		^ OHCI_FRAME_INTERVAL_TOGGLE;
273 	frameInterval |= OHCI_FSMPS(intervalValue) | intervalValue;
274 	_WriteReg(OHCI_FRAME_INTERVAL, frameInterval);
275 	// 90% periodic
276 	uint32 periodic = OHCI_PERIODIC(intervalValue);
277 	_WriteReg(OHCI_PERIODIC_START, periodic);
278 
279 	// Fiddle the No Over Current Protection bit to avoid chip bug
280 	uint32 desca = _ReadReg(OHCI_RH_DESCRIPTOR_A);
281 	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca | OHCI_RH_NO_OVER_CURRENT_PROTECTION);
282 	_WriteReg(OHCI_RH_STATUS, OHCI_RH_LOCAL_POWER_STATUS_CHANGE);
283 	snooze(OHCI_ENABLE_POWER_DELAY);
284 	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca);
285 
286 	// The AMD756 requires a delay before re-reading the register,
287 	// otherwise it will occasionally report 0 ports.
288 	uint32 numberOfPorts = 0;
289 	for (uint32 i = 0; i < 10 && numberOfPorts == 0; i++) {
290 		snooze(OHCI_READ_DESC_DELAY);
291 		uint32 descriptor = _ReadReg(OHCI_RH_DESCRIPTOR_A);
292 		numberOfPorts = OHCI_RH_GET_PORT_COUNT(descriptor);
293 	}
294 	if (numberOfPorts > OHCI_MAX_PORT_COUNT)
295 		numberOfPorts = OHCI_MAX_PORT_COUNT;
296 	fPortCount = numberOfPorts;
297 	TRACE("port count is %d\n", fPortCount);
298 
299 	// Create semaphore the finisher thread will wait for
300 	fFinishTransfersSem = create_sem(0, "OHCI Finish Transfers");
301 	if (fFinishTransfersSem < B_OK) {
302 		TRACE_ERROR("failed to create semaphore\n");
303 		return;
304 	}
305 
306 	// Create the finisher service thread
307 	fFinishThread = spawn_kernel_thread(_FinishThread, "ohci finish thread",
308 		B_URGENT_DISPLAY_PRIORITY, (void *)this);
309 	resume_thread(fFinishThread);
310 
311 	// Install the interrupt handler
312 	TRACE("installing interrupt handler\n");
313 	install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
314 		_InterruptHandler, (void *)this, 0);
315 
316 	// Enable interesting interrupts now that the handler is in place
317 	_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS
318 		| OHCI_MASTER_INTERRUPT_ENABLE);
319 
320 	TRACE("OHCI host controller driver constructed\n");
321 	fInitOK = true;
322 }
323 
324 
325 OHCI::~OHCI()
326 {
327 	int32 result = 0;
328 	fStopFinishThread = true;
329 	delete_sem(fFinishTransfersSem);
330 	wait_for_thread(fFinishThread, &result);
331 
332 	_LockEndpoints();
333 	mutex_destroy(&fEndpointLock);
334 
335 	if (fHccaArea >= B_OK)
336 		delete_area(fHccaArea);
337 	if (fRegisterArea >= B_OK)
338 		delete_area(fRegisterArea);
339 
340 	_FreeEndpoint(fDummyControl);
341 	_FreeEndpoint(fDummyBulk);
342 	_FreeEndpoint(fDummyIsochronous);
343 
344 	if (fInterruptEndpoints != NULL) {
345 		for (int i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++)
346 			_FreeEndpoint(fInterruptEndpoints[i]);
347 	}
348 
349 	delete [] fInterruptEndpoints;
350 	delete fRootHub;
351 
352 	put_module(B_PCI_MODULE_NAME);
353 }
354 
355 
356 status_t
357 OHCI::Start()
358 {
359 	TRACE("starting OHCI host controller\n");
360 
361 	uint32 control = _ReadReg(OHCI_CONTROL);
362 	if ((control & OHCI_HC_FUNCTIONAL_STATE_MASK)
363 		!= OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL) {
364 		TRACE_ERROR("controller not started (0x%08lx)!\n", control);
365 		return B_ERROR;
366 	} else
367 		TRACE("controller is operational!\n");
368 
369 	fRootHubAddress = AllocateAddress();
370 	fRootHub = new(std::nothrow) OHCIRootHub(RootObject(), fRootHubAddress);
371 	if (!fRootHub) {
372 		TRACE_ERROR("no memory to allocate root hub\n");
373 		return B_NO_MEMORY;
374 	}
375 
376 	if (fRootHub->InitCheck() < B_OK) {
377 		TRACE_ERROR("root hub failed init check\n");
378 		return B_ERROR;
379 	}
380 
381 	SetRootHub(fRootHub);
382 	TRACE_ALWAYS("successfully started the controller\n");
383 	return BusManager::Start();
384 }
385 
386 
387 status_t
388 OHCI::SubmitTransfer(Transfer *transfer)
389 {
390 	// short circuit the root hub
391 	if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
392 		return fRootHub->ProcessTransfer(this, transfer);
393 
394 	uint32 type = transfer->TransferPipe()->Type();
395 	if (type & USB_OBJECT_CONTROL_PIPE) {
396 		TRACE("submitting request\n");
397 		return _SubmitRequest(transfer);
398 	}
399 
400 	if ((type & USB_OBJECT_BULK_PIPE) || (type & USB_OBJECT_INTERRUPT_PIPE)) {
401 		TRACE("submitting %s transfer\n",
402 			(type & USB_OBJECT_BULK_PIPE) ? "bulk" : "interrupt");
403 		return _SubmitTransfer(transfer);
404 	}
405 
406 	if (type & USB_OBJECT_ISO_PIPE) {
407 		TRACE("submitting isochronous transfer\n");
408 		return _SubmitIsochronousTransfer(transfer);
409 	}
410 
411 	TRACE_ERROR("tried to submit transfer for unknown pipe type %lu\n", type);
412 	return B_ERROR;
413 }
414 
415 
416 status_t
417 OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
418 {
419 	if (pipe->Type() & USB_OBJECT_ISO_PIPE)
420 		return _CancelQueuedIsochronousTransfers(pipe, force);
421 
422 	if (!Lock())
423 		return B_ERROR;
424 
425 	struct transfer_entry {
426 		Transfer *			transfer;
427 		transfer_entry *	next;
428 	};
429 
430 	transfer_entry *list = NULL;
431 	transfer_data *current = fFirstTransfer;
432 	while (current) {
433 		if (current->transfer && current->transfer->TransferPipe() == pipe) {
434 			// Check if the skip bit is already set
435 			if (!(current->endpoint->flags & OHCI_ENDPOINT_SKIP)) {
436 				current->endpoint->flags |= OHCI_ENDPOINT_SKIP;
437 				// In case the controller is processing
438 				// this endpoint, wait for it to finish
439 				snooze(1000);
440 			}
441 
442 			// Clear the endpoint
443 			current->endpoint->head_physical_descriptor
444 				= current->endpoint->tail_physical_descriptor;
445 
446 			if (!force) {
447 				// If the transfer is canceled by force, the one causing the
448 				// cancel is probably not the one who initiated the transfer
449 				// and the callback is likely not safe anymore
450 				transfer_entry *entry
451 					= (transfer_entry *)malloc(sizeof(transfer_entry));
452 				if (entry != NULL) {
453 					entry->transfer = current->transfer;
454 					current->transfer = NULL;
455 					entry->next = list;
456 					list = entry;
457 				}
458 			}
459 			current->canceled = true;
460 		}
461 		current = current->link;
462 	}
463 
464 	Unlock();
465 
466 	while (list != NULL) {
467 		transfer_entry *next = list->next;
468 		list->transfer->Finished(B_CANCELED, 0);
469 		delete list->transfer;
470 		free(list);
471 		list = next;
472 	}
473 
474 	// notify the finisher so it can clean up the canceled transfers
475 	release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
476 	return B_OK;
477 }
478 
479 
480 status_t
481 OHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
482 {
483 	TRACE("pipe change %d for pipe 0x%08lx\n", change, (uint32)pipe);
484 	if (pipe->DeviceAddress() == fRootHubAddress) {
485 		// no need to insert/remove endpoint descriptors for the root hub
486 		return B_OK;
487 	}
488 
489 	switch (change) {
490 		case USB_CHANGE_CREATED:
491 			return _InsertEndpointForPipe(pipe);
492 
493 		case USB_CHANGE_DESTROYED:
494 			return _RemoveEndpointForPipe(pipe);
495 
496 		case USB_CHANGE_PIPE_POLICY_CHANGED:
497 			TRACE("pipe policy changing unhandled!\n");
498 			break;
499 
500 		default:
501 			TRACE_ERROR("unknown pipe change!\n");
502 			return B_ERROR;
503 	}
504 
505 	return B_OK;
506 }
507 
508 
509 status_t
510 OHCI::AddTo(Stack *stack)
511 {
512 #ifdef TRACE_USB
513 	set_dprintf_enabled(true);
514 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
515 	load_driver_symbols("ohci");
516 #endif
517 #endif
518 
519 	if (!sPCIModule) {
520 		status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
521 		if (status < B_OK) {
522 			TRACE_MODULE_ERROR("getting pci module failed! 0x%08lx\n", status);
523 			return status;
524 		}
525 	}
526 
527 	TRACE_MODULE("searching devices\n");
528 	bool found = false;
529 	pci_info *item = new(std::nothrow) pci_info;
530 	if (!item) {
531 		sPCIModule = NULL;
532 		put_module(B_PCI_MODULE_NAME);
533 		return B_NO_MEMORY;
534 	}
535 
536 	for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
537 		if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
538 			&& item->class_api == PCI_usb_ohci) {
539 			if (item->u.h0.interrupt_line == 0
540 				|| item->u.h0.interrupt_line == 0xFF) {
541 				TRACE_MODULE_ERROR("found device with invalid IRQ -"
542 					" check IRQ assignement\n");
543 				continue;
544 			}
545 
546 			TRACE_MODULE("found device at IRQ %u\n",
547 				item->u.h0.interrupt_line);
548 			OHCI *bus = new(std::nothrow) OHCI(item, stack);
549 			if (!bus) {
550 				delete item;
551 				sPCIModule = NULL;
552 				put_module(B_PCI_MODULE_NAME);
553 				return B_NO_MEMORY;
554 			}
555 
556 			if (bus->InitCheck() < B_OK) {
557 				TRACE_MODULE_ERROR("bus failed init check\n");
558 				delete bus;
559 				continue;
560 			}
561 
562 			// the bus took it away
563 			item = new(std::nothrow) pci_info;
564 
565 			bus->Start();
566 			stack->AddBusManager(bus);
567 			found = true;
568 		}
569 	}
570 
571 	if (!found) {
572 		TRACE_MODULE_ERROR("no devices found\n");
573 		delete item;
574 		sPCIModule = NULL;
575 		put_module(B_PCI_MODULE_NAME);
576 		return ENODEV;
577 	}
578 
579 	delete item;
580 	return B_OK;
581 }
582 
583 
584 status_t
585 OHCI::GetPortStatus(uint8 index, usb_port_status *status)
586 {
587 	if (index >= fPortCount) {
588 		TRACE_ERROR("get port status for invalid port %u\n", index);
589 		return B_BAD_INDEX;
590 	}
591 
592 	status->status = status->change = 0;
593 	uint32 portStatus = _ReadReg(OHCI_RH_PORT_STATUS(index));
594 
595 	// status
596 	if (portStatus & OHCI_RH_PORTSTATUS_CCS)
597 		status->status |= PORT_STATUS_CONNECTION;
598 	if (portStatus & OHCI_RH_PORTSTATUS_PES)
599 		status->status |= PORT_STATUS_ENABLE;
600 	if (portStatus & OHCI_RH_PORTSTATUS_PSS)
601 		status->status |= PORT_STATUS_SUSPEND;
602 	if (portStatus & OHCI_RH_PORTSTATUS_POCI)
603 		status->status |= PORT_STATUS_OVER_CURRENT;
604 	if (portStatus & OHCI_RH_PORTSTATUS_PRS)
605 		status->status |= PORT_STATUS_RESET;
606 	if (portStatus & OHCI_RH_PORTSTATUS_PPS)
607 		status->status |= PORT_STATUS_POWER;
608 	if (portStatus & OHCI_RH_PORTSTATUS_LSDA)
609 		status->status |= PORT_STATUS_LOW_SPEED;
610 
611 	// change
612 	if (portStatus & OHCI_RH_PORTSTATUS_CSC)
613 		status->change |= PORT_STATUS_CONNECTION;
614 	if (portStatus & OHCI_RH_PORTSTATUS_PESC)
615 		status->change |= PORT_STATUS_ENABLE;
616 	if (portStatus & OHCI_RH_PORTSTATUS_PSSC)
617 		status->change |= PORT_STATUS_SUSPEND;
618 	if (portStatus & OHCI_RH_PORTSTATUS_OCIC)
619 		status->change |= PORT_STATUS_OVER_CURRENT;
620 	if (portStatus & OHCI_RH_PORTSTATUS_PRSC)
621 		status->change |= PORT_STATUS_RESET;
622 
623 	TRACE("port %u status 0x%04x change 0x%04x\n", index,
624 		status->status, status->change);
625 	return B_OK;
626 }
627 
628 
629 status_t
630 OHCI::SetPortFeature(uint8 index, uint16 feature)
631 {
632 	TRACE("set port feature index %u feature %u\n", index, feature);
633 	if (index > fPortCount)
634 		return B_BAD_INDEX;
635 
636 	switch (feature) {
637 		case PORT_ENABLE:
638 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PES);
639 			return B_OK;
640 
641 		case PORT_SUSPEND:
642 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSS);
643 			return B_OK;
644 
645 		case PORT_RESET:
646 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRS);
647 			return B_OK;
648 
649 		case PORT_POWER:
650 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PPS);
651 			return B_OK;
652 	}
653 
654 	return B_BAD_VALUE;
655 }
656 
657 
658 status_t
659 OHCI::ClearPortFeature(uint8 index, uint16 feature)
660 {
661 	TRACE("clear port feature index %u feature %u\n", index, feature);
662 	if (index > fPortCount)
663 		return B_BAD_INDEX;
664 
665 	switch (feature) {
666 		case PORT_ENABLE:
667 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CCS);
668 			return B_OK;
669 
670 		case PORT_SUSPEND:
671 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_POCI);
672 			return B_OK;
673 
674 		case PORT_POWER:
675 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_LSDA);
676 			return B_OK;
677 
678 		case C_PORT_CONNECTION:
679 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CSC);
680 			return B_OK;
681 
682 		case C_PORT_ENABLE:
683 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PESC);
684 			return B_OK;
685 
686 		case C_PORT_SUSPEND:
687 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSSC);
688 			return B_OK;
689 
690 		case C_PORT_OVER_CURRENT:
691 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_OCIC);
692 			return B_OK;
693 
694 		case C_PORT_RESET:
695 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRSC);
696 			return B_OK;
697 	}
698 
699 	return B_BAD_VALUE;
700 }
701 
702 
703 int32
704 OHCI::_InterruptHandler(void *data)
705 {
706 	return ((OHCI *)data)->_Interrupt();
707 }
708 
709 
710 int32
711 OHCI::_Interrupt()
712 {
713 	static spinlock lock = B_SPINLOCK_INITIALIZER;
714 	acquire_spinlock(&lock);
715 
716 	uint32 status = 0;
717 	uint32 acknowledge = 0;
718 	bool finishTransfers = false;
719 	int32 result = B_HANDLED_INTERRUPT;
720 
721 	// The LSb of done_head is used to inform the HCD that an interrupt
722 	// condition exists for both the done list and for another event recorded in
723 	// the HcInterruptStatus register. If done_head is 0, then the interrupt
724 	// was caused by other than the HccaDoneHead update and the
725 	// HcInterruptStatus register needs to be accessed to determine that exact
726 	// interrupt cause. If HccDoneHead is nonzero, then a done list update
727 	// interrupt is indicated and if the LSb of the Dword is nonzero, then an
728 	// additional interrupt event is indicated and HcInterruptStatus should be
729 	// checked to determine its cause.
730 	uint32 doneHead = fHcca->done_head;
731 	if (doneHead != 0) {
732 		status = OHCI_WRITEBACK_DONE_HEAD;
733 		if (doneHead & OHCI_DONE_INTERRUPTS)
734 			status |= _ReadReg(OHCI_INTERRUPT_STATUS)
735 				& _ReadReg(OHCI_INTERRUPT_ENABLE);
736 	} else {
737 		status = _ReadReg(OHCI_INTERRUPT_STATUS) & _ReadReg(OHCI_INTERRUPT_ENABLE)
738 			& ~OHCI_WRITEBACK_DONE_HEAD;
739 		if (status == 0) {
740 			// Nothing to be done (PCI shared interrupt)
741 			release_spinlock(&lock);
742 			return B_UNHANDLED_INTERRUPT;
743 		}
744 	}
745 
746 	if (status & OHCI_SCHEDULING_OVERRUN) {
747 		TRACE_MODULE("scheduling overrun occured\n");
748 		acknowledge |= OHCI_SCHEDULING_OVERRUN;
749 	}
750 
751 	if (status & OHCI_WRITEBACK_DONE_HEAD) {
752 		TRACE_MODULE("transfer descriptors processed\n");
753 		fHcca->done_head = 0;
754 		acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
755 		result = B_INVOKE_SCHEDULER;
756 		finishTransfers = true;
757 	}
758 
759 	if (status & OHCI_RESUME_DETECTED) {
760 		TRACE_MODULE("resume detected\n");
761 		acknowledge |= OHCI_RESUME_DETECTED;
762 	}
763 
764 	if (status & OHCI_UNRECOVERABLE_ERROR) {
765 		TRACE_MODULE_ERROR("unrecoverable error - controller halted\n");
766 		_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
767 		// TODO: clear all pending transfers, reset and resetup the controller
768 	}
769 
770 	if (status & OHCI_ROOT_HUB_STATUS_CHANGE) {
771 		TRACE_MODULE("root hub status change\n");
772 		// Disable the interrupt as it will otherwise be retriggered until the
773 		// port has been reset and the change is cleared explicitly.
774 		// TODO: renable it once we use status changes instead of polling
775 		_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ROOT_HUB_STATUS_CHANGE);
776 		acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE;
777 	}
778 
779 	if (acknowledge != 0)
780 		_WriteReg(OHCI_INTERRUPT_STATUS, acknowledge);
781 
782 	release_spinlock(&lock);
783 
784 	if (finishTransfers)
785 		release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
786 
787 	return result;
788 }
789 
790 
791 status_t
792 OHCI::_AddPendingTransfer(Transfer *transfer,
793 	ohci_endpoint_descriptor *endpoint, ohci_general_td *firstDescriptor,
794 	ohci_general_td *dataDescriptor, ohci_general_td *lastDescriptor,
795 	bool directionIn)
796 {
797 	if (!transfer || !endpoint || !lastDescriptor)
798 		return B_BAD_VALUE;
799 
800 	transfer_data *data = new(std::nothrow) transfer_data;
801 	if (!data)
802 		return B_NO_MEMORY;
803 
804 	status_t result = transfer->InitKernelAccess();
805 	if (result < B_OK) {
806 		delete data;
807 		return result;
808 	}
809 
810 	data->transfer = transfer;
811 	data->endpoint = endpoint;
812 	data->incoming = directionIn;
813 	data->canceled = false;
814 	data->link = NULL;
815 
816 	// the current tail will become the fist descriptor
817 	data->first_descriptor = (ohci_general_td *)endpoint->tail_logical_descriptor;
818 
819 	// the data and first descriptors might be the same
820 	if (dataDescriptor == firstDescriptor)
821 		data->data_descriptor = data->first_descriptor;
822 	else
823 		data->data_descriptor = dataDescriptor;
824 
825 	// even the last and the first descriptor might be the same
826 	if (lastDescriptor == firstDescriptor)
827 		data->last_descriptor = data->first_descriptor;
828 	else
829 		data->last_descriptor = lastDescriptor;
830 
831 	if (!Lock()) {
832 		delete data;
833 		return B_ERROR;
834 	}
835 
836 	if (fLastTransfer)
837 		fLastTransfer->link = data;
838 	else
839 		fFirstTransfer = data;
840 
841 	fLastTransfer = data;
842 	Unlock();
843 
844 	return B_OK;
845 }
846 
847 
848 status_t
849 OHCI::_CancelQueuedIsochronousTransfers(Pipe *pipe, bool force)
850 {
851 	// TODO
852 	return B_ERROR;
853 }
854 
855 
856 int32
857 OHCI::_FinishThread(void *data)
858 {
859 	((OHCI *)data)->_FinishTransfers();
860 	return B_OK;
861 }
862 
863 
864 void
865 OHCI::_FinishTransfers()
866 {
867 	while (!fStopFinishThread) {
868 		if (acquire_sem(fFinishTransfersSem) < B_OK)
869 			continue;
870 
871 		// eat up sems that have been released by multiple interrupts
872 		int32 semCount = 0;
873 		get_sem_count(fFinishTransfersSem, &semCount);
874 		if (semCount > 0)
875 			acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
876 
877 		if (!Lock())
878 			continue;
879 
880 		TRACE("finishing transfers (first transfer: %p; last"
881 			" transfer: %p)\n", fFirstTransfer, fLastTransfer);
882 		transfer_data *lastTransfer = NULL;
883 		transfer_data *transfer = fFirstTransfer;
884 		Unlock();
885 
886 		while (transfer) {
887 			bool transferDone = false;
888 			ohci_general_td *descriptor = transfer->first_descriptor;
889 			status_t callbackStatus = B_OK;
890 
891 			while (descriptor && !transfer->canceled) {
892 				uint32 status = OHCI_TD_GET_CONDITION_CODE(descriptor->flags);
893 				if (status == OHCI_TD_CONDITION_NOT_ACCESSED) {
894 					// td is still active
895 					TRACE("td %p still active\n", descriptor);
896 					break;
897 				}
898 
899 				if (status != OHCI_TD_CONDITION_NO_ERROR) {
900 					// an error occured, but we must ensure that the td
901 					// was actually done
902 					ohci_endpoint_descriptor *endpoint = transfer->endpoint;
903 					if (endpoint->head_physical_descriptor & OHCI_ENDPOINT_HALTED) {
904 						// the endpoint is halted, this guaratees us that this
905 						// descriptor has passed (we don't know if the endpoint
906 						// was halted because of this td, but we do not need
907 						// to know, as when it was halted by another td this
908 						// still ensures that this td was handled before).
909 						TRACE_ERROR("td error: 0x%08lx\n", status);
910 
911 						switch (status) {
912 							case OHCI_TD_CONDITION_CRC_ERROR:
913 							case OHCI_TD_CONDITION_BIT_STUFFING:
914 							case OHCI_TD_CONDITION_TOGGLE_MISMATCH:
915 								callbackStatus = B_DEV_CRC_ERROR;
916 								break;
917 
918 							case OHCI_TD_CONDITION_STALL:
919 								callbackStatus = B_DEV_STALLED;
920 								break;
921 
922 							case OHCI_TD_CONDITION_NO_RESPONSE:
923 								callbackStatus = B_TIMED_OUT;
924 								break;
925 
926 							case OHCI_TD_CONDITION_PID_CHECK_FAILURE:
927 								callbackStatus = B_DEV_BAD_PID;
928 								break;
929 
930 							case OHCI_TD_CONDITION_UNEXPECTED_PID:
931 								callbackStatus = B_DEV_UNEXPECTED_PID;
932 								break;
933 
934 							case OHCI_TD_CONDITION_DATA_OVERRUN:
935 								callbackStatus = B_DEV_DATA_OVERRUN;
936 								break;
937 
938 							case OHCI_TD_CONDITION_DATA_UNDERRUN:
939 								callbackStatus = B_DEV_DATA_UNDERRUN;
940 								break;
941 
942 							case OHCI_TD_CONDITION_BUFFER_OVERRUN:
943 								callbackStatus = B_DEV_FIFO_OVERRUN;
944 								break;
945 
946 							case OHCI_TD_CONDITION_BUFFER_UNDERRUN:
947 								callbackStatus = B_DEV_FIFO_UNDERRUN;
948 								break;
949 
950 							default:
951 								callbackStatus = B_ERROR;
952 								break;
953 						}
954 
955 						transferDone = true;
956 						break;
957 					} else {
958 						// an error occured but the endpoint is not halted so
959 						// the td is in fact still active
960 						TRACE("td %p active with error\n", descriptor);
961 						break;
962 					}
963 				}
964 
965 				// the td has complete without an error
966 				TRACE("td %p done\n", descriptor);
967 
968 				if (descriptor == transfer->last_descriptor
969 					|| descriptor->buffer_physical != 0) {
970 					// this is the last td of the transfer or a short packet
971 					callbackStatus = B_OK;
972 					transferDone = true;
973 					break;
974 				}
975 
976 				descriptor
977 					= (ohci_general_td *)descriptor->next_logical_descriptor;
978 			}
979 
980 			if (transfer->canceled) {
981 				// when a transfer is canceled, all transfers to that endpoint
982 				// are canceled by setting the head pointer to the tail pointer
983 				// which causes all of the tds to become "free" (as they are
984 				// inaccessible and not accessed anymore (as setting the head
985 				// pointer required disabling the endpoint))
986 				callbackStatus = B_OK;
987 				transferDone = true;
988 			}
989 
990 			if (!transferDone) {
991 				lastTransfer = transfer;
992 				transfer = transfer->link;
993 				continue;
994 			}
995 
996 			// remove the transfer from the list first so we are sure
997 			// it doesn't get canceled while we still process it
998 			transfer_data *next = transfer->link;
999 			if (Lock()) {
1000 				if (lastTransfer)
1001 					lastTransfer->link = transfer->link;
1002 
1003 				if (transfer == fFirstTransfer)
1004 					fFirstTransfer = transfer->link;
1005 				if (transfer == fLastTransfer)
1006 					fLastTransfer = lastTransfer;
1007 
1008 				transfer->link = NULL;
1009 				Unlock();
1010 			}
1011 
1012 			// break the descriptor chain on the last descriptor
1013 			transfer->last_descriptor->next_logical_descriptor = NULL;
1014 			TRACE("transfer %p done with status 0x%08lx\n",
1015 				transfer, callbackStatus);
1016 
1017 			// if canceled the callback has already been called
1018 			if (!transfer->canceled) {
1019 				size_t actualLength = 0;
1020 				if (callbackStatus == B_OK) {
1021 					if (transfer->data_descriptor && transfer->incoming) {
1022 						// data to read out
1023 						iovec *vector = transfer->transfer->Vector();
1024 						size_t vectorCount = transfer->transfer->VectorCount();
1025 
1026 						transfer->transfer->PrepareKernelAccess();
1027 						actualLength = _ReadDescriptorChain(
1028 							transfer->data_descriptor,
1029 							vector, vectorCount);
1030 					} else if (transfer->data_descriptor) {
1031 						// read the actual length that was sent
1032 						actualLength = _ReadActualLength(
1033 							transfer->data_descriptor);
1034 					}
1035 
1036 					if (transfer->transfer->IsFragmented()) {
1037 						// this transfer may still have data left
1038 						TRACE("advancing fragmented transfer\n");
1039 						transfer->transfer->AdvanceByFragment(actualLength);
1040 						if (transfer->transfer->VectorLength() > 0) {
1041 							TRACE("still %ld bytes left on transfer\n",
1042 								transfer->transfer->VectorLength());
1043 							// TODO actually resubmit the transfer
1044 						}
1045 
1046 						// the transfer is done, but we already set the
1047 						// actualLength with AdvanceByFragment()
1048 						actualLength = 0;
1049 					}
1050 				}
1051 
1052 				transfer->transfer->Finished(callbackStatus, actualLength);
1053 			}
1054 
1055 			if (callbackStatus != B_OK) {
1056 				// remove the transfer and make the head pointer valid again
1057 				// (including clearing the halt state)
1058 				_RemoveTransferFromEndpoint(transfer);
1059 			}
1060 
1061 			// free the descriptors
1062 			_FreeDescriptorChain(transfer->first_descriptor);
1063 
1064 			delete transfer->transfer;
1065 			delete transfer;
1066 			transfer = next;
1067 		}
1068 	}
1069 }
1070 
1071 
1072 status_t
1073 OHCI::_SubmitRequest(Transfer *transfer)
1074 {
1075 	usb_request_data *requestData = transfer->RequestData();
1076 	bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0;
1077 
1078 	ohci_general_td *setupDescriptor
1079 		= _CreateGeneralDescriptor(sizeof(usb_request_data));
1080 	if (!setupDescriptor) {
1081 		TRACE_ERROR("failed to allocate setup descriptor\n");
1082 		return B_NO_MEMORY;
1083 	}
1084 
1085 	setupDescriptor->flags = OHCI_TD_DIRECTION_PID_SETUP
1086 		| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1087 		| OHCI_TD_TOGGLE_0
1088 		| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
1089 
1090 	ohci_general_td *statusDescriptor = _CreateGeneralDescriptor(0);
1091 	if (!statusDescriptor) {
1092 		TRACE_ERROR("failed to allocate status descriptor\n");
1093 		_FreeGeneralDescriptor(setupDescriptor);
1094 		return B_NO_MEMORY;
1095 	}
1096 
1097 	statusDescriptor->flags
1098 		= (directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN)
1099 		| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1100 		| OHCI_TD_TOGGLE_1
1101 		| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1102 
1103 	iovec vector;
1104 	vector.iov_base = requestData;
1105 	vector.iov_len = sizeof(usb_request_data);
1106 	_WriteDescriptorChain(setupDescriptor, &vector, 1);
1107 
1108 	status_t result;
1109 	ohci_general_td *dataDescriptor = NULL;
1110 	if (transfer->VectorCount() > 0) {
1111 		ohci_general_td *lastDescriptor = NULL;
1112 		result = _CreateDescriptorChain(&dataDescriptor, &lastDescriptor,
1113 			directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT,
1114 			transfer->VectorLength());
1115 		if (result < B_OK) {
1116 			_FreeGeneralDescriptor(setupDescriptor);
1117 			_FreeGeneralDescriptor(statusDescriptor);
1118 			return result;
1119 		}
1120 
1121 		if (!directionIn) {
1122 			_WriteDescriptorChain(dataDescriptor, transfer->Vector(),
1123 				transfer->VectorCount());
1124 		}
1125 
1126 		_LinkDescriptors(setupDescriptor, dataDescriptor);
1127 		_LinkDescriptors(lastDescriptor, statusDescriptor);
1128 	} else {
1129 		_LinkDescriptors(setupDescriptor, statusDescriptor);
1130 	}
1131 
1132 	// Add to the transfer list
1133 	ohci_endpoint_descriptor *endpoint
1134 		= (ohci_endpoint_descriptor *)transfer->TransferPipe()->ControllerCookie();
1135 	result = _AddPendingTransfer(transfer, endpoint, setupDescriptor,
1136 		dataDescriptor, statusDescriptor, directionIn);
1137 	if (result < B_OK) {
1138 		TRACE_ERROR("failed to add pending transfer\n");
1139 		_FreeDescriptorChain(setupDescriptor);
1140 		return result;
1141 	}
1142 
1143 	// Add the descriptor chain to the endpoint
1144 	_SwitchEndpointTail(endpoint, setupDescriptor, statusDescriptor);
1145 
1146 	// Tell the controller to process the control list
1147 	endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1148 	_WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED);
1149 	return B_OK;
1150 }
1151 
1152 
1153 status_t
1154 OHCI::_SubmitTransfer(Transfer *transfer)
1155 {
1156 	Pipe *pipe = transfer->TransferPipe();
1157 	bool directionIn = (pipe->Direction() == Pipe::In);
1158 
1159 	ohci_general_td *firstDescriptor = NULL;
1160 	ohci_general_td *lastDescriptor = NULL;
1161 	status_t result = _CreateDescriptorChain(&firstDescriptor, &lastDescriptor,
1162 		directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT,
1163 		transfer->VectorLength());
1164 
1165 	if (result < B_OK)
1166 		return result;
1167 
1168 	// Set the last descriptor to generate an interrupt
1169 	lastDescriptor->flags &= ~OHCI_TD_INTERRUPT_MASK;
1170 	lastDescriptor->flags |=
1171 		OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1172 
1173 	if (!directionIn) {
1174 		_WriteDescriptorChain(firstDescriptor, transfer->Vector(),
1175 			transfer->VectorCount());
1176 	}
1177 
1178 	// Add to the transfer list
1179 	ohci_endpoint_descriptor *endpoint
1180 		= (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1181 	result = _AddPendingTransfer(transfer, endpoint, firstDescriptor,
1182 		firstDescriptor, lastDescriptor, directionIn);
1183 	if (result < B_OK) {
1184 		TRACE_ERROR("failed to add pending transfer\n");
1185 		_FreeDescriptorChain(firstDescriptor);
1186 		return result;
1187 	}
1188 
1189 	// Add the descriptor chain to the endpoint
1190 	_SwitchEndpointTail(endpoint, firstDescriptor, lastDescriptor);
1191 	endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1192 
1193 	if (pipe->Type() & USB_OBJECT_BULK_PIPE) {
1194 		// Tell the controller to process the bulk list
1195 		_WriteReg(OHCI_COMMAND_STATUS, OHCI_BULK_LIST_FILLED);
1196 	}
1197 
1198 	return B_OK;
1199 }
1200 
1201 
1202 status_t
1203 OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
1204 {
1205 	return B_ERROR;
1206 }
1207 
1208 
1209 void
1210 OHCI::_SwitchEndpointTail(ohci_endpoint_descriptor *endpoint,
1211 	ohci_general_td *first, ohci_general_td *last)
1212 {
1213 	// fill in the information of the first descriptor into the current tail
1214 	ohci_general_td *tail = (ohci_general_td *)endpoint->tail_logical_descriptor;
1215 	tail->flags = first->flags;
1216 	tail->buffer_physical = first->buffer_physical;
1217 	tail->next_physical_descriptor = first->next_physical_descriptor;
1218 	tail->last_physical_byte_address = first->last_physical_byte_address;
1219 	tail->buffer_size = first->buffer_size;
1220 	tail->buffer_logical = first->buffer_logical;
1221 	tail->next_logical_descriptor = first->next_logical_descriptor;
1222 
1223 	// the first descriptor becomes the new tail
1224 	first->flags = 0;
1225 	first->buffer_physical = 0;
1226 	first->next_physical_descriptor = 0;
1227 	first->last_physical_byte_address = 0;
1228 	first->buffer_size = 0;
1229 	first->buffer_logical = NULL;
1230 	first->next_logical_descriptor = NULL;
1231 
1232 	if (first == last)
1233 		_LinkDescriptors(tail, first);
1234 	else
1235 		_LinkDescriptors(last, first);
1236 
1237 	// update the endpoint tail pointer to reflect the change
1238 	endpoint->tail_logical_descriptor = first;
1239 	endpoint->tail_physical_descriptor = (uint32)first->physical_address;
1240 
1241 #if 0
1242 	_PrintEndpoint(endpoint);
1243 	_PrintDescriptorChain(tail);
1244 #endif
1245 }
1246 
1247 
1248 void
1249 OHCI::_RemoveTransferFromEndpoint(transfer_data *transfer)
1250 {
1251 	// The transfer failed and the endpoint was halted. This means that the
1252 	// endpoint head pointer might point somewhere into the descriptor chain
1253 	// of this transfer. As we do not know if this transfer actually caused
1254 	// the halt on the endpoint we have to make sure this is the case. If we
1255 	// find the head to point to somewhere into the descriptor chain then
1256 	// simply advancing the head pointer to the link of the last transfer
1257 	// will bring the endpoint into a valid state again. This operation is
1258 	// safe as the endpoint is currently halted and we therefore can change
1259 	// the head pointer.
1260 	ohci_endpoint_descriptor *endpoint = transfer->endpoint;
1261 	ohci_general_td *descriptor = transfer->first_descriptor;
1262 	while (descriptor) {
1263 		if ((endpoint->head_physical_descriptor & OHCI_ENDPOINT_HEAD_MASK)
1264 			== descriptor->physical_address) {
1265 			// This descriptor caused the halt. Advance the head pointer. This
1266 			// will either move the head to the next valid transfer that can
1267 			// then be restarted, or it will move the head to the tail when
1268 			// there are no more transfer descriptors. Setting the head will
1269 			// also clear the halt state as it is stored in the first bit of
1270 			// the head pointer.
1271 			endpoint->head_physical_descriptor
1272 				= transfer->last_descriptor->next_physical_descriptor;
1273 			return;
1274 		}
1275 
1276 		descriptor = (ohci_general_td *)descriptor->next_logical_descriptor;
1277 	}
1278 }
1279 
1280 
1281 ohci_endpoint_descriptor *
1282 OHCI::_AllocateEndpoint()
1283 {
1284 	ohci_endpoint_descriptor *endpoint;
1285 	void *physicalAddress;
1286 
1287 	// Allocate memory chunk
1288 	if (fStack->AllocateChunk((void **)&endpoint, &physicalAddress,
1289 		sizeof(ohci_endpoint_descriptor)) < B_OK) {
1290 		TRACE_ERROR("failed to allocate endpoint descriptor\n");
1291 		return NULL;
1292 	}
1293 
1294 	endpoint->flags = OHCI_ENDPOINT_SKIP;
1295 	endpoint->physical_address = (addr_t)physicalAddress;
1296 	endpoint->head_physical_descriptor = 0;
1297 	endpoint->tail_logical_descriptor = NULL;
1298 	endpoint->tail_physical_descriptor = 0;
1299 	endpoint->next_logical_endpoint = NULL;
1300 	endpoint->next_physical_endpoint = 0;
1301 	return endpoint;
1302 }
1303 
1304 
1305 void
1306 OHCI::_FreeEndpoint(ohci_endpoint_descriptor *endpoint)
1307 {
1308 	if (!endpoint)
1309 		return;
1310 
1311 	fStack->FreeChunk((void *)endpoint, (void *)endpoint->physical_address,
1312 		sizeof(ohci_endpoint_descriptor));
1313 }
1314 
1315 
1316 status_t
1317 OHCI::_InsertEndpointForPipe(Pipe *pipe)
1318 {
1319 	TRACE("inserting endpoint for device %u endpoint %u\n",
1320 		pipe->DeviceAddress(), pipe->EndpointAddress());
1321 
1322 	ohci_endpoint_descriptor *endpoint = _AllocateEndpoint();
1323 	if (!endpoint) {
1324 		TRACE_ERROR("cannot allocate memory for endpoint\n");
1325 		return B_NO_MEMORY;
1326 	}
1327 
1328 	uint32 flags = OHCI_ENDPOINT_SKIP;
1329 
1330 	// Set up device and endpoint address
1331 	flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(pipe->DeviceAddress())
1332 		| OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(pipe->EndpointAddress());
1333 
1334 	// Set the direction
1335 	switch (pipe->Direction()) {
1336 		case Pipe::In:
1337 			flags |= OHCI_ENDPOINT_DIRECTION_IN;
1338 			break;
1339 
1340 		case Pipe::Out:
1341 			flags |= OHCI_ENDPOINT_DIRECTION_OUT;
1342 			break;
1343 
1344 		case Pipe::Default:
1345 			flags |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR;
1346 			break;
1347 
1348 		default:
1349 			TRACE_ERROR("direction unknown\n");
1350 			_FreeEndpoint(endpoint);
1351 			return B_ERROR;
1352 	}
1353 
1354 	// Set up the speed
1355 	switch (pipe->Speed()) {
1356 		case USB_SPEED_LOWSPEED:
1357 			flags |= OHCI_ENDPOINT_LOW_SPEED;
1358 			break;
1359 
1360 		case USB_SPEED_FULLSPEED:
1361 			flags |= OHCI_ENDPOINT_FULL_SPEED;
1362 			break;
1363 
1364 		default:
1365 			TRACE_ERROR("unaccetable speed\n");
1366 			_FreeEndpoint(endpoint);
1367 			return B_ERROR;
1368 	}
1369 
1370 	// Set the maximum packet size
1371 	flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(pipe->MaxPacketSize());
1372 	endpoint->flags = flags;
1373 
1374 	// Add the endpoint to the appropriate list
1375 	uint32 type = pipe->Type();
1376 	ohci_endpoint_descriptor *head = NULL;
1377 	if (type & USB_OBJECT_CONTROL_PIPE)
1378 		head = fDummyControl;
1379 	else if (type & USB_OBJECT_BULK_PIPE)
1380 		head = fDummyBulk;
1381 	else if (type & USB_OBJECT_INTERRUPT_PIPE)
1382 		head = _FindInterruptEndpoint(pipe->Interval());
1383 	else if (type & USB_OBJECT_ISO_PIPE)
1384 		head = fDummyIsochronous;
1385 	else
1386 		TRACE_ERROR("unknown pipe type\n");
1387 
1388 	if (head == NULL) {
1389 		TRACE_ERROR("no list found for endpoint\n");
1390 		_FreeEndpoint(endpoint);
1391 		return B_ERROR;
1392 	}
1393 
1394 	// Create (necessary) tail descriptor
1395 	if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
1396 		// Set the isochronous bit format
1397 		endpoint->flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
1398 		// TODO
1399 		_FreeEndpoint(endpoint);
1400 		return B_ERROR;
1401 	} else {
1402 		ohci_general_td *tail = _CreateGeneralDescriptor(0);
1403 		endpoint->tail_logical_descriptor = tail;
1404 		endpoint->head_physical_descriptor = tail->physical_address;
1405 		endpoint->tail_physical_descriptor = tail->physical_address;
1406 	}
1407 
1408 	if (!_LockEndpoints()) {
1409 		if (endpoint->tail_logical_descriptor) {
1410 			_FreeGeneralDescriptor(
1411 				(ohci_general_td *)endpoint->tail_logical_descriptor);
1412 		}
1413 
1414 		_FreeEndpoint(endpoint);
1415 		return B_ERROR;
1416 	}
1417 
1418 	pipe->SetControllerCookie((void *)endpoint);
1419 	endpoint->next_logical_endpoint = head->next_logical_endpoint;
1420 	endpoint->next_physical_endpoint = head->next_physical_endpoint;
1421 	head->next_logical_endpoint = (void *)endpoint;
1422 	head->next_physical_endpoint = (uint32)endpoint->physical_address;
1423 
1424 	_UnlockEndpoints();
1425 	return B_OK;
1426 }
1427 
1428 
1429 status_t
1430 OHCI::_RemoveEndpointForPipe(Pipe *pipe)
1431 {
1432 	TRACE("removing endpoint for device %u endpoint %u\n",
1433 		pipe->DeviceAddress(), pipe->EndpointAddress());
1434 
1435 	ohci_endpoint_descriptor *endpoint
1436 		= (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1437 	if (endpoint == NULL)
1438 		return B_OK;
1439 
1440 	// TODO implement properly, but at least disable it for now
1441 	endpoint->flags |= OHCI_ENDPOINT_SKIP;
1442 	return B_OK;
1443 }
1444 
1445 
1446 ohci_endpoint_descriptor *
1447 OHCI::_FindInterruptEndpoint(uint8 interval)
1448 {
1449 	uint32 index = 0;
1450 	uint32 power = 1;
1451 	while (power <= OHCI_BIGGEST_INTERVAL / 2) {
1452 		if (power * 2 > interval)
1453 			break;
1454 
1455 		power *= 2;
1456 		index++;
1457 	}
1458 
1459 	return fInterruptEndpoints[index];
1460 }
1461 
1462 
1463 ohci_general_td *
1464 OHCI::_CreateGeneralDescriptor(size_t bufferSize)
1465 {
1466 	ohci_general_td *descriptor;
1467 	void *physicalAddress;
1468 
1469 	if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
1470 		sizeof(ohci_general_td)) != B_OK) {
1471 		TRACE_ERROR("failed to allocate general descriptor\n");
1472 		return NULL;
1473 	}
1474 
1475 	descriptor->physical_address = (addr_t)physicalAddress;
1476 	descriptor->next_physical_descriptor = 0;
1477 	descriptor->next_logical_descriptor = NULL;
1478 	descriptor->buffer_size = bufferSize;
1479 	if (bufferSize == 0) {
1480 		descriptor->buffer_physical = 0;
1481 		descriptor->buffer_logical = NULL;
1482 		descriptor->last_physical_byte_address = 0;
1483 		return descriptor;
1484 	}
1485 
1486 	if (fStack->AllocateChunk(&descriptor->buffer_logical,
1487 		(void **)&descriptor->buffer_physical, bufferSize) != B_OK) {
1488 		TRACE_ERROR("failed to allocate space for buffer\n");
1489 		fStack->FreeChunk(descriptor, (void *)descriptor->physical_address,
1490 			sizeof(ohci_general_td));
1491 		return NULL;
1492 	}
1493 
1494 	descriptor->last_physical_byte_address
1495 		= descriptor->buffer_physical + bufferSize - 1;
1496 	return descriptor;
1497 }
1498 
1499 
1500 void
1501 OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor)
1502 {
1503 	if (!descriptor)
1504 		return;
1505 
1506 	if (descriptor->buffer_logical) {
1507 		fStack->FreeChunk(descriptor->buffer_logical,
1508 			(void *)descriptor->buffer_physical, descriptor->buffer_size);
1509 	}
1510 
1511 	fStack->FreeChunk((void *)descriptor, (void *)descriptor->physical_address,
1512 		sizeof(ohci_general_td));
1513 }
1514 
1515 
1516 status_t
1517 OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor,
1518 	ohci_general_td **_lastDescriptor, uint32 direction, size_t bufferSize)
1519 {
1520 	size_t blockSize = 8192;
1521 	int32 descriptorCount = (bufferSize + blockSize - 1) / blockSize;
1522 	if (descriptorCount == 0)
1523 		descriptorCount = 1;
1524 
1525 	ohci_general_td *firstDescriptor = NULL;
1526 	ohci_general_td *lastDescriptor = *_firstDescriptor;
1527 	for (int32 i = 0; i < descriptorCount; i++) {
1528 		ohci_general_td *descriptor = _CreateGeneralDescriptor(
1529 			min_c(blockSize, bufferSize));
1530 
1531 		if (!descriptor) {
1532 			_FreeDescriptorChain(firstDescriptor);
1533 			return B_NO_MEMORY;
1534 		}
1535 
1536 		descriptor->flags = direction
1537 			| OHCI_TD_BUFFER_ROUNDING
1538 			| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1539 			| OHCI_TD_TOGGLE_CARRY
1540 			| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
1541 
1542 		// link to previous
1543 		if (lastDescriptor)
1544 			_LinkDescriptors(lastDescriptor, descriptor);
1545 
1546 		bufferSize -= blockSize;
1547 		lastDescriptor = descriptor;
1548 		if (!firstDescriptor)
1549 			firstDescriptor = descriptor;
1550 	}
1551 
1552 	*_firstDescriptor = firstDescriptor;
1553 	*_lastDescriptor = lastDescriptor;
1554 	return B_OK;
1555 }
1556 
1557 
1558 void
1559 OHCI::_FreeDescriptorChain(ohci_general_td *topDescriptor)
1560 {
1561 	ohci_general_td *current = topDescriptor;
1562 	ohci_general_td *next = NULL;
1563 
1564 	while (current) {
1565 		next = (ohci_general_td *)current->next_logical_descriptor;
1566 		_FreeGeneralDescriptor(current);
1567 		current = next;
1568 	}
1569 }
1570 
1571 
1572 size_t
1573 OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
1574 	size_t vectorCount)
1575 {
1576 	ohci_general_td *current = topDescriptor;
1577 	size_t actualLength = 0;
1578 	size_t vectorIndex = 0;
1579 	size_t vectorOffset = 0;
1580 	size_t bufferOffset = 0;
1581 
1582 	while (current) {
1583 		if (!current->buffer_logical)
1584 			break;
1585 
1586 		while (true) {
1587 			size_t length = min_c(current->buffer_size - bufferOffset,
1588 				vector[vectorIndex].iov_len - vectorOffset);
1589 
1590 			TRACE("copying %ld bytes to bufferOffset %ld from"
1591 				" vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
1592 				vectorOffset, vectorIndex, vectorCount);
1593 			memcpy((uint8 *)current->buffer_logical + bufferOffset,
1594 				(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
1595 
1596 			actualLength += length;
1597 			vectorOffset += length;
1598 			bufferOffset += length;
1599 
1600 			if (vectorOffset >= vector[vectorIndex].iov_len) {
1601 				if (++vectorIndex >= vectorCount) {
1602 					TRACE("wrote descriptor chain (%ld bytes, no"
1603 						" more vectors)\n", actualLength);
1604 					return actualLength;
1605 				}
1606 
1607 				vectorOffset = 0;
1608 			}
1609 
1610 			if (bufferOffset >= current->buffer_size) {
1611 				bufferOffset = 0;
1612 				break;
1613 			}
1614 		}
1615 
1616 		if (!current->next_logical_descriptor)
1617 			break;
1618 
1619 		current = (ohci_general_td *)current->next_logical_descriptor;
1620 	}
1621 
1622 	TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
1623 	return actualLength;
1624 }
1625 
1626 
1627 size_t
1628 OHCI::_ReadDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
1629 	size_t vectorCount)
1630 {
1631 	ohci_general_td *current = topDescriptor;
1632 	size_t actualLength = 0;
1633 	size_t vectorIndex = 0;
1634 	size_t vectorOffset = 0;
1635 	size_t bufferOffset = 0;
1636 
1637 	while (current && OHCI_TD_GET_CONDITION_CODE(current->flags)
1638 		!= OHCI_TD_CONDITION_NOT_ACCESSED) {
1639 		if (!current->buffer_logical)
1640 			break;
1641 
1642 		size_t bufferSize = current->buffer_size;
1643 		if (current->buffer_physical != 0) {
1644 			bufferSize = current->last_physical_byte_address
1645 				- current->buffer_physical + 1;
1646 		}
1647 
1648 		while (true) {
1649 			size_t length = min_c(bufferSize - bufferOffset,
1650 				vector[vectorIndex].iov_len - vectorOffset);
1651 
1652 			TRACE("copying %ld bytes to vectorOffset %ld from"
1653 				" bufferOffset %ld at index %ld of %ld\n", length, vectorOffset,
1654 				bufferOffset, vectorIndex, vectorCount);
1655 			memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
1656 				(uint8 *)current->buffer_logical + bufferOffset, length);
1657 
1658 			actualLength += length;
1659 			vectorOffset += length;
1660 			bufferOffset += length;
1661 
1662 			if (vectorOffset >= vector[vectorIndex].iov_len) {
1663 				if (++vectorIndex >= vectorCount) {
1664 					TRACE("read descriptor chain (%ld bytes, no more vectors)\n",
1665 						actualLength);
1666 					return actualLength;
1667 				}
1668 
1669 				vectorOffset = 0;
1670 			}
1671 
1672 			if (bufferOffset >= bufferSize) {
1673 				bufferOffset = 0;
1674 				break;
1675 			}
1676 		}
1677 
1678 		current = (ohci_general_td *)current->next_logical_descriptor;
1679 	}
1680 
1681 	TRACE("read descriptor chain (%ld bytes)\n", actualLength);
1682 	return actualLength;
1683 }
1684 
1685 
1686 size_t
1687 OHCI::_ReadActualLength(ohci_general_td *topDescriptor)
1688 {
1689 	ohci_general_td *current = topDescriptor;
1690 	size_t actualLength = 0;
1691 
1692 	while (current && OHCI_TD_GET_CONDITION_CODE(current->flags)
1693 		!= OHCI_TD_CONDITION_NOT_ACCESSED) {
1694 		size_t length = current->buffer_size;
1695 		if (current->buffer_physical != 0) {
1696 			length = current->last_physical_byte_address
1697 				- current->buffer_physical + 1;
1698 		}
1699 
1700 		actualLength += length;
1701 		current = (ohci_general_td *)current->next_logical_descriptor;
1702 	}
1703 
1704 	TRACE("read actual length (%ld bytes)\n", actualLength);
1705 	return actualLength;
1706 }
1707 
1708 
1709 void
1710 OHCI::_LinkDescriptors(ohci_general_td *first, ohci_general_td *second)
1711 {
1712 	first->next_physical_descriptor = second->physical_address;
1713 	first->next_logical_descriptor = second;
1714 }
1715 
1716 
1717 ohci_isochronous_td *
1718 OHCI::_CreateIsochronousDescriptor()
1719 {
1720 	// TODO
1721 	return NULL;
1722 }
1723 
1724 
1725 void
1726 OHCI::_FreeIsochronousDescriptor(ohci_isochronous_td *descriptor)
1727 {
1728 	// TODO
1729 }
1730 
1731 
1732 bool
1733 OHCI::_LockEndpoints()
1734 {
1735 	return (mutex_lock(&fEndpointLock) == B_OK);
1736 }
1737 
1738 
1739 void
1740 OHCI::_UnlockEndpoints()
1741 {
1742 	mutex_unlock(&fEndpointLock);
1743 }
1744 
1745 
1746 inline void
1747 OHCI::_WriteReg(uint32 reg, uint32 value)
1748 {
1749 	*(volatile uint32 *)(fOperationalRegisters + reg) = value;
1750 }
1751 
1752 
1753 inline uint32
1754 OHCI::_ReadReg(uint32 reg)
1755 {
1756 	return *(volatile uint32 *)(fOperationalRegisters + reg);
1757 }
1758 
1759 
1760 void
1761 OHCI::_PrintEndpoint(ohci_endpoint_descriptor *endpoint)
1762 {
1763 	TRACE_ALWAYS("endpoint %p\n", endpoint);
1764 	dprintf("\tflags........... 0x%08lx\n", endpoint->flags);
1765 	dprintf("\ttail_physical... 0x%08lx\n", endpoint->tail_physical_descriptor);
1766 	dprintf("\thead_physical... 0x%08lx\n", endpoint->head_physical_descriptor);
1767 	dprintf("\tnext_physical... 0x%08lx\n", endpoint->next_physical_endpoint);
1768 	dprintf("\tphysical........ 0x%08lx\n", endpoint->physical_address);
1769 	dprintf("\ttail_logical.... %p\n", endpoint->tail_logical_descriptor);
1770 	dprintf("\tnext_logical.... %p\n", endpoint->next_logical_endpoint);
1771 }
1772 
1773 
1774 void
1775 OHCI::_PrintDescriptorChain(ohci_general_td *topDescriptor)
1776 {
1777 	while (topDescriptor) {
1778 		TRACE_ALWAYS("descriptor %p\n", topDescriptor);
1779 		dprintf("\tflags........... 0x%08lx\n", topDescriptor->flags);
1780 		dprintf("\tbuffer_physical. 0x%08lx\n", topDescriptor->buffer_physical);
1781 		dprintf("\tnext_physical... 0x%08lx\n", topDescriptor->next_physical_descriptor);
1782 		dprintf("\tlast_byte....... 0x%08lx\n", topDescriptor->last_physical_byte_address);
1783 		dprintf("\tphysical........ 0x%08lx\n", topDescriptor->physical_address);
1784 		dprintf("\tbuffer_size..... %lu\n", topDescriptor->buffer_size);
1785 		dprintf("\tbuffer_logical.. %p\n", topDescriptor->buffer_logical);
1786 		dprintf("\tnext_logical.... %p\n", topDescriptor->next_logical_descriptor);
1787 
1788 		topDescriptor = (ohci_general_td *)topDescriptor->next_logical_descriptor;
1789 	}
1790 }
1791