xref: /haiku/src/add-ons/kernel/busses/usb/ohci.cpp (revision e6b30aee0fd7a23d6a6baab9f3718945a0cd838a)
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  */
9 
10 #include <module.h>
11 #include <PCI.h>
12 #include <USB3.h>
13 #include <KernelExport.h>
14 
15 #include "ohci.h"
16 
17 pci_module_info *OHCI::sPCIModule = NULL;
18 
19 
20 static int32
21 ohci_std_ops(int32 op, ...)
22 {
23 	switch (op)	{
24 		case B_MODULE_INIT:
25 			TRACE(("usb_ohci_module: init module\n"));
26 			return B_OK;
27 		case B_MODULE_UNINIT:
28 			TRACE(("usb_ohci_module: uninit module\n"));
29 			return B_OK;
30 	}
31 
32 	return EINVAL;
33 }
34 
35 
36 host_controller_info ohci_module = {
37 	{
38 		"busses/usb/ohci",
39 		0,
40 		ohci_std_ops
41 	},
42 	NULL,
43 	OHCI::AddTo
44 };
45 
46 
47 module_info *modules[] = {
48 	(module_info *)&ohci_module,
49 	NULL
50 };
51 
52 
53 //------------------------------------------------------
54 //	OHCI:: 	Reverse the bits in a value between 0 and 31
55 //			(Section 3.3.2)
56 //------------------------------------------------------
57 static uint8 revbits[OHCI_NUMBER_OF_INTERRUPTS] =
58   { 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
59     0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
60     0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
61     0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f };
62 
63 
64 OHCI::OHCI(pci_info *info, Stack *stack)
65 	:	BusManager(stack),
66 		fPCIInfo(info),
67 		fStack(stack),
68 		fRegisterArea(-1),
69 		fHccaArea(-1),
70 		fDummyControl(NULL),
71 		fDummyBulk(NULL),
72 		fDummyIsochronous(NULL),
73 		fFirstTransfer(NULL),
74 		fLastTransfer(NULL),
75 		fFinishThread(-1),
76 		fStopFinishThread(false),
77 		fRootHub(NULL),
78 		fRootHubAddress(0),
79 		fPortCount(0)
80 {
81 	if (!fInitOK) {
82 		TRACE_ERROR(("usb_ohci: bus manager failed to init\n"));
83 		return;
84 	}
85 
86 	TRACE(("usb_ohci: constructing new OHCI Host Controller Driver\n"));
87 	fInitOK = false;
88 
89 	// enable busmaster and memory mapped access
90 	uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
91 		fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
92 	command &= ~PCI_command_io;
93 	command |= PCI_command_master | PCI_command_memory;
94 
95 	sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
96 		fPCIInfo->function, PCI_command, 2, command);
97 
98 	// map the registers
99 	uint32 offset = sPCIModule->read_pci_config(fPCIInfo->bus,
100 		fPCIInfo->device, fPCIInfo->function, PCI_base_registers, 4);
101 	offset &= PCI_address_memory_32_mask;
102 	TRACE(("usb_ohci: iospace offset: %lx\n", offset));
103 	fRegisterArea = map_physical_memory("OHCI memory mapped registers",
104 		(void *)offset,	B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS,
105 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA,
106 		(void **)&fOperationalRegisters);
107 	if (fRegisterArea < B_OK) {
108 		TRACE_ERROR(("usb_ohci: failed to map register memory\n"));
109 		return;
110 	}
111 
112 	TRACE(("usb_ohci: mapped operational registers: 0x%08lx\n",
113 		*fOperationalRegisters));
114 
115 	// Check the revision of the controller, which should be 10h
116 	uint32 revision = _ReadReg(OHCI_REVISION) & 0xff;
117 	TRACE(("usb_ohci: version %ld.%ld%s\n", OHCI_REVISION_HIGH(revision),
118 		OHCI_REVISION_LOW(revision), OHCI_REVISION_LEGACY(revision)
119 		? ", legacy support" : ""));
120 	if (OHCI_REVISION_HIGH(revision) != 1 || OHCI_REVISION_LOW(revision) != 0) {
121 		TRACE_ERROR(("usb_ohci: unsupported OHCI revision\n"));
122 		return;
123 	}
124 
125 	// Set up the Host Controller Communications Area
126 	// which is 256 bytes (2048 bits) and must be aligned
127 	void *hccaPhysicalAddress;
128 	fHccaArea = fStack->AllocateArea((void **)&fHcca, &hccaPhysicalAddress,
129 		2048, "USB OHCI Host Controller Communication Area");
130 
131 	if (fHccaArea < B_OK) {
132 		TRACE_ERROR(("usb_ohci: unable to create the HCCA block area\n"));
133 		return;
134 	}
135 
136 	memset((void *)fHcca, 0, sizeof(ohci_hcca));
137 
138 	// Allocate hash tables
139 	fHashGenericTable = (ohci_general_td **)
140 		malloc(sizeof(ohci_general_td *) * OHCI_HASH_SIZE);
141 	if (fHashGenericTable == NULL) {
142 		TRACE_ERROR(("usb_ohci: unable to allocate hash generic table\n"));
143 		return;
144 	}
145 	fHashIsochronousTable = (ohci_isochronous_td **)
146 		malloc(sizeof(ohci_isochronous_td *) * OHCI_HASH_SIZE);
147 	if (fHashIsochronousTable == NULL) {
148 		free(fHashGenericTable);
149 		TRACE_ERROR(("usb_ohci: unable to allocate hash isochronous table\n"));
150 		return;
151 	}
152 
153 	// Set Up Host controller
154 	// Dummy endpoints
155 	fDummyControl = _AllocateEndpoint();
156 	if (!fDummyControl)
157 		return;
158 	fDummyControl->flags |= OHCI_ENDPOINT_SKIP;
159 
160 	fDummyBulk = _AllocateEndpoint();
161 	if (!fDummyBulk) {
162 		_FreeEndpoint(fDummyControl);
163 		return;
164 	}
165 	fDummyBulk->flags |= OHCI_ENDPOINT_SKIP;
166 
167 	fDummyIsochronous = _AllocateEndpoint();
168 	if (!fDummyIsochronous) {
169 		_FreeEndpoint(fDummyControl);
170 		_FreeEndpoint(fDummyBulk);
171 		return;
172 	}
173 	fDummyIsochronous->flags |= OHCI_ENDPOINT_SKIP;
174 
175 	// Static endpoints that get linked in the HCCA
176 	fInterruptEndpoints = new(std::nothrow)
177 		ohci_endpoint_descriptor *[OHCI_NUMBER_OF_INTERRUPTS];
178 	if (!fInterruptEndpoints) {
179 		TRACE_ERROR(("ohci_usb: cannot allocate memory for"
180 			" fInterruptEndpoints array\n"));
181 		_FreeEndpoint(fDummyControl);
182 		_FreeEndpoint(fDummyBulk);
183 		_FreeEndpoint(fDummyIsochronous);
184 		return;
185 	}
186 	for (uint32 i = 0; i < OHCI_NUMBER_OF_INTERRUPTS; i++) {
187 		fInterruptEndpoints[i] = _AllocateEndpoint();
188 		if (!fInterruptEndpoints[i]) {
189 			TRACE_ERROR(("ohci_usb: cannot allocate memory for"
190 				" fInterruptEndpoints[%ld] endpoint\n", i));
191 			while (--i >= 0)
192 				_FreeEndpoint(fInterruptEndpoints[i]);
193 			_FreeEndpoint(fDummyBulk);
194 			_FreeEndpoint(fDummyControl);
195 			_FreeEndpoint(fDummyIsochronous);
196 			return;
197 		}
198 		// Make them point all to the dummy isochronous endpoint
199 		fInterruptEndpoints[i]->flags |= OHCI_ENDPOINT_SKIP;
200 		fInterruptEndpoints[i]->next_physical_endpoint
201 			= fDummyIsochronous->physical_address;
202 	}
203 
204 	// Fill HCCA interrupt table.
205 	for (uint32 i = 0; i < OHCI_NUMBER_OF_INTERRUPTS; i++)
206 		fHcca->interrupt_table[i] = fInterruptEndpoints[i]->physical_address;
207 
208 	// Determine in what context we are running (Kindly copied from FreeBSD)
209 	uint32 control = _ReadReg(OHCI_CONTROL);
210 	if (control & OHCI_INTERRUPT_ROUTING) {
211 		TRACE(("usb_ohci: SMM is in control of the host controller\n"));
212 		uint32 status = _ReadReg(OHCI_COMMAND_STATUS);
213 		_WriteReg(OHCI_COMMAND_STATUS, status | OHCI_OWNERSHIP_CHANGE_REQUEST);
214 		for (uint32 i = 0; i < 100 	&& (control & OHCI_INTERRUPT_ROUTING); i++) {
215 			snooze(1000);
216 			control = _ReadReg(OHCI_CONTROL);
217 		}
218 		if (!(control & OHCI_INTERRUPT_ROUTING)) {
219 			TRACE(("usb_ohci: SMM does not respond. Resetting...\n"));
220 			_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
221 			snooze(USB_DELAY_BUS_RESET);
222 		}
223 	} else {
224 		TRACE(("usb_ohci: cold started\n"));
225 		snooze(USB_DELAY_BUS_RESET);
226 	}
227 
228 	// This reset should not be necessary according to the OHCI spec, but
229 	// without it some controllers do not start.
230 	_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
231 	snooze(USB_DELAY_BUS_RESET);
232 
233 	// We now own the host controller and the bus has been reset
234 	uint32 frameInterval = _ReadReg(OHCI_FRAME_INTERVAL);
235 	uint32 intervalValue = OHCI_GET_INTERVAL_VALUE(frameInterval);
236 
237 	// Disable interrupts right before we reset
238 	cpu_status former = disable_interrupts();
239 	_WriteReg(OHCI_COMMAND_STATUS, OHCI_HOST_CONTROLLER_RESET);
240 	// Nominal time for a reset is 10 us
241 	uint32 reset = 0;
242 	for (uint32 i = 0; i < 10; i++) {
243 		spin(10);
244 		reset = _ReadReg(OHCI_COMMAND_STATUS) & OHCI_HOST_CONTROLLER_RESET;
245 		if (!reset)
246 			break;
247 	}
248 	if (reset) {
249 		TRACE_ERROR(("usb_ohci: Error resetting the host controller (timeout)\n"));
250 		restore_interrupts(former);
251 		return;
252 	}
253 
254 	// The controller is now in SUSPEND state, we have 2ms to go OPERATIONAL.
255 	// Interrupts are disabled.
256 
257 	// Set up host controller register
258 	_WriteReg(OHCI_HCCA, (uint32)hccaPhysicalAddress);
259 	_WriteReg(OHCI_CONTROL_HEAD_ED, (uint32)fDummyControl->physical_address);
260 	_WriteReg(OHCI_BULK_HEAD_ED, (uint32)fDummyBulk->physical_address);
261 	// Disable all interrupts and then switch on all desired interrupts
262 	_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS);
263 	_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS
264 		| OHCI_MASTER_INTERRUPT_ENABLE);
265 	// Switch on desired functional features
266 	control = _ReadReg(OHCI_CONTROL);
267 	control &= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK | OHCI_ENABLE_LIST
268 		| OHCI_HC_FUNCTIONAL_STATE_MASK | OHCI_INTERRUPT_ROUTING);
269 	control |= OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4
270 		| OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL;
271 	// And finally start the controller
272 	_WriteReg(OHCI_CONTROL, control);
273 
274 	restore_interrupts(former);
275 
276 	// The controller is now OPERATIONAL.
277 	frameInterval = (_ReadReg(OHCI_FRAME_INTERVAL) & OHCI_FRAME_INTERVAL_TOGGLE)
278 		^ OHCI_FRAME_INTERVAL_TOGGLE;
279 	frameInterval |= OHCI_FSMPS(intervalValue) | intervalValue;
280 	_WriteReg(OHCI_FRAME_INTERVAL, frameInterval);
281 	// 90% periodic
282 	uint32 periodic = OHCI_PERIODIC(intervalValue);
283 	_WriteReg(OHCI_PERIODIC_START, periodic);
284 
285 	// Fiddle the No Over Current Protection bit to avoid chip bug
286 	uint32 desca = _ReadReg(OHCI_RH_DESCRIPTOR_A);
287 	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca | OHCI_RH_NO_OVER_CURRENT_PROTECTION);
288 	_WriteReg(OHCI_RH_STATUS, OHCI_RH_LOCAL_POWER_STATUS_CHANGE);
289 	snooze(OHCI_ENABLE_POWER_DELAY);
290 	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca);
291 
292 	// The AMD756 requires a delay before re-reading the register,
293 	// otherwise it will occasionally report 0 ports.
294 	uint32 numberOfPorts = 0;
295 	for (uint32 i = 0; i < 10 && numberOfPorts == 0; i++) {
296 		snooze(OHCI_READ_DESC_DELAY);
297 		uint32 descriptor = _ReadReg(OHCI_RH_DESCRIPTOR_A);
298 		numberOfPorts = OHCI_RH_GET_PORT_COUNT(descriptor);
299 	}
300 	fPortCount = numberOfPorts;
301 
302 	// Create semaphore the finisher thread will wait for
303 	fFinishTransfersSem = create_sem(0, "OHCI Finish Transfers");
304 	if (fFinishTransfersSem < B_OK) {
305 		TRACE_ERROR(("usb_ohci: failed to create semaphore\n"));
306 		return;
307 	}
308 
309 	// Create the finisher service thread
310 	fFinishThread = spawn_kernel_thread(_FinishThread, "ohci finish thread",
311 		B_URGENT_DISPLAY_PRIORITY, (void *)this);
312 	resume_thread(fFinishThread);
313 
314 	// Install the interrupt handler
315 	TRACE(("usb_ohci: installing interrupt handler\n"));
316 	install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
317 		_InterruptHandler, (void *)this, 0);
318 
319 	TRACE(("usb_ohci: OHCI Host Controller Driver constructed\n"));
320 	fInitOK = true;
321 }
322 
323 
324 OHCI::~OHCI()
325 {
326 	int32 result = 0;
327 	fStopFinishThread = true;
328 	delete_sem(fFinishTransfersSem);
329 	wait_for_thread(fFinishThread, &result);
330 
331 	if (fHccaArea > 0)
332 		delete_area(fHccaArea);
333 	if (fRegisterArea > 0)
334 		delete_area(fRegisterArea);
335 	if (fHashGenericTable)
336 		free(fHashGenericTable);
337 	if (fHashIsochronousTable)
338 		free(fHashIsochronousTable);
339 	if (fDummyControl)
340 		_FreeEndpoint(fDummyControl);
341 	if (fDummyBulk)
342 		_FreeEndpoint(fDummyBulk);
343 	if (fDummyIsochronous)
344 		_FreeEndpoint(fDummyIsochronous);
345 	if (fRootHub)
346 		delete fRootHub;
347 	for (int i = 0; i < OHCI_NUMBER_OF_INTERRUPTS; i++)
348 		if (fInterruptEndpoints[i])
349 			_FreeEndpoint(fInterruptEndpoints[i]);
350 	delete [] fInterruptEndpoints;
351 	put_module(B_PCI_MODULE_NAME);
352 }
353 
354 
355 int32
356 OHCI::_InterruptHandler(void *data)
357 {
358 	return ((OHCI *)data)->_Interrupt();
359 }
360 
361 
362 int32
363 OHCI::_Interrupt()
364 {
365 	static spinlock lock = 0;
366 	acquire_spinlock(&lock);
367 
368 	uint32 status = 0;
369 	uint32 acknowledge = 0;
370 	bool finishTransfers = false;
371 	int32 result = B_HANDLED_INTERRUPT;
372 
373 	// The LSb of done_head is used to inform the HCD that an interrupt
374 	// condition exists for both the done list and for another event recorded in
375 	// the HcInterruptStatus register. If done_head is 0, then the interrupt
376 	// was caused by other than the HccaDoneHead update and the
377 	// HcInterruptStatus register needs to be accessed to determine that exact
378 	// interrupt cause. If HccDoneHead is nonzero, then a done list update
379 	// interrupt is indicated and if the LSb of the Dword is nonzero, then an
380 	// additional interrupt event is indicated and HcInterruptStatus shuold be
381 	// checked to determine its cause.
382 	uint32 doneHead = fHcca->done_head;
383 	if (doneHead != 0) {
384 		status = OHCI_WRITEBACK_DONE_HEAD;
385 		if (doneHead & OHCI_DONE_INTERRUPTS)
386 			status |= _ReadReg(OHCI_INTERRUPT_STATUS)
387 				& _ReadReg(OHCI_INTERRUPT_ENABLE);
388 	} else {
389 		status = _ReadReg(OHCI_INTERRUPT_STATUS) & _ReadReg(OHCI_INTERRUPT_ENABLE)
390 			& ~OHCI_WRITEBACK_DONE_HEAD;
391 		if (status == 0) {
392 			// Nothing to be done (PCI shared interrupt)
393 			release_spinlock(&lock);
394 			return B_UNHANDLED_INTERRUPT;
395 		}
396 	}
397 
398 	if (status & OHCI_SCHEDULING_OVERRUN) {
399 		// TODO
400 		TRACE(("usb_ohci: scheduling overrun occured\n"));
401 	}
402 
403 	if (status & OHCI_WRITEBACK_DONE_HEAD) {
404 		TRACE(("usb_ohci: transfer descriptor processed\n"));
405 		// Ack it in the finisher thread, not here.
406 		result = B_INVOKE_SCHEDULER;
407 		finishTransfers = true;
408 	}
409 
410 	if (status & OHCI_RESUME_DETECTED) {
411 		// TODO
412 		TRACE(("usb_ohci: resume detected\n"));
413 	}
414 
415 	if (status & OHCI_UNRECOVERABLE_ERROR) {
416 		TRACE(("usb_ohci: unrecoverable error. Controller halted\n"));
417 		_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
418 		// TODO: what else?
419 		// Perhaps, clean up all the memory.
420 	}
421 
422 	if (status & OHCI_ROOT_HUB_STATUS_CHANGE) {
423 		// TODO
424 		TRACE(("usb_ohci: root hub status change\n"));
425 	}
426 
427 	release_spinlock(&lock);
428 
429 	if (finishTransfers)
430 		release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
431 
432 	return result;
433 }
434 
435 
436 int32
437 OHCI::_FinishThread(void *data)
438 {
439 	((OHCI *)data)->_FinishTransfer();
440 	return B_OK;
441 }
442 
443 
444 void
445 OHCI::_FinishTransfer()
446 {
447 	while (!fStopFinishThread) {
448 		if (acquire_sem(fFinishTransfersSem) < B_OK)
449 			continue;
450 
451 		// eat up sems that have been released by multiple interrupts
452 		int32 semCount = 0;
453 		get_sem_count(fFinishTransfersSem, &semCount);
454 		if (semCount > 0)
455 			acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
456 
457 		uint32 done_list = fHcca->done_head & ~OHCI_DONE_INTERRUPTS;
458 		// If done_head is zero, there are not processed descriptors
459 		// in the done list and we have been woken up by CancelQueuedTransfers
460 		// or CancelQueuedIsochronousTransfers in order to do some clean up
461 		// and back to sleep.
462 		if (done_list) {
463 			// Pull out the done list and reverse its order
464 			// for both general and isochronous descriptors
465 			ohci_general_td *current, *top;
466 			ohci_isochronous_td *isoCurrent, *isoTop;
467 			for ( top = NULL, isoTop = NULL ; done_list != 0; ) {
468 				if ((current = _FindDescriptorInHash(done_list))) {
469 					done_list = current->next_physical_descriptor;
470 					current->next_done_descriptor = (void *)top;
471 					top = current;
472 					continue;
473 				}
474 				if ((isoCurrent = _FindIsoDescriptorInHash(done_list))) {
475 					done_list = isoCurrent->next_physical_descriptor;
476 					isoCurrent->next_done_descriptor = (void *)isoTop;
477 					isoTop = isoCurrent;
478 					continue;
479 				}
480 				// TODO: Should I panic here? :)
481 				TRACE_ERROR(("usb_ohci: address 0x%08lx not found!\n",
482 					done_list));
483 				break;
484 			}
485 
486 			// Acknowledge the interrupt
487 			// TODO: Move the acknowledgement in the interrupt handler.
488 			// The done_head value can be passed through a shared variable.
489 			fHcca->done_head = 0;
490 			_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_WRITEBACK_DONE_HEAD);
491 
492 			// Process isochronous list first
493 			for (isoCurrent = isoTop; isoCurrent != NULL; isoCurrent
494 				= (ohci_isochronous_td *)isoCurrent->next_done_descriptor) {
495 				// TODO: Process isochronous descriptors
496 			}
497 
498 			// Now process the general list
499 			for (current = top; current != NULL; ) {
500 				ohci_general_td *next
501 					= (ohci_general_td *)current->next_done_descriptor;
502 
503 				transfer_data *transfer = (transfer_data *)current->transfer;
504 				if (transfer->canceled) {
505 					// Clear canceled transfer later on
506 					current = next;
507 					continue;
508 				}
509 
510 				bool transferDone = false;
511 				status_t callbackStatus = B_OK;
512 				uint32 conditionCode = OHCI_TD_GET_CONDITION_CODE(current->flags);
513 				if (conditionCode != OHCI_NO_ERROR) {
514 					// Endpoint is halted: unlink all descriptors belonging to
515 					// the failed transfer from the endpoint and restart the
516 					// endpoint.
517 					// NOTE: There can(should) not be more than one
518 					// invalid descriptor from the same transfer in the
519 					// done list, as the controller halt the endpoint right
520 					// away if a descriptor fails. This means that, if we reversed
521 					// the order of the done list (which we did), there is
522 					// not reason to look for more failed descriptors in the
523 					// done list from the same transfer, as *BSD code does.
524 					TRACE(("usb_ohci: transfer failed! ohci error code: %d\n",
525 						conditionCode));
526 
527 					// Remove remaining descriptors from the same transfer
528 					if (!current->is_last)
529 						_RemoveTransferFromEndpoint(transfer);
530 
531 					// TODO: Fix the following with the appropriate error
532 					callbackStatus = B_DEV_MULTIPLE_ERRORS;
533 					transferDone = true;
534 					continue;
535 				} else if (current->is_last)
536 					transferDone = true;
537 
538 				if (transferDone) {
539 					size_t actualLength = 0;
540 					if (callbackStatus == B_OK) {
541 						if (transfer->data_descriptor && transfer->incoming) {
542 							// Read data out
543 						} else {
544 							// How much was transfer?
545 						}
546 						if (transfer->transfer->IsFragmented()) {
547 							// TODO
548 						}
549 					}
550 					_UnlinkTransfer(transfer);
551 					transfer->transfer->Finished(callbackStatus, actualLength);
552 					// Update next before current gets deleted
553 					next = (ohci_general_td *)current->next_done_descriptor;
554 					_FreeDescriptorChain(transfer->first_descriptor);
555 
556 					delete transfer->transfer;
557 					delete transfer;
558 
559 				}
560 				current = next;
561 			}
562 
563 		}
564 
565 		// Quick look for canceled transfer before
566 		// we go back to sleep
567 		transfer_data *current = fFirstTransfer;
568 		while (current) {
569 			transfer_data *next = current->link;
570 			if (current->canceled) {
571 				_UnlinkTransfer(current);
572 				_FreeDescriptorChain(current->first_descriptor);
573 				delete current->transfer;
574 				delete current;
575 			}
576 			current = next;
577 		}
578 	}
579 }
580 
581 
582 status_t
583 OHCI::_AppendChainDescriptorsToEndpoint(ohci_endpoint_descriptor *endpoint,
584 	ohci_general_td *first, ohci_general_td *last)
585 {
586 	endpoint->flags |= OHCI_ENDPOINT_SKIP;
587 	snooze(1000);
588 
589 	// TODO: Lock on endpoint
590 	ohci_general_td *head = (ohci_general_td *)endpoint->head_logical_descriptor;
591 	ohci_general_td *tail = (ohci_general_td *)endpoint->tail_logical_descriptor;
592 	if (head != tail) {
593 		// Find the last real descriptor
594 		ohci_general_td *current = head;
595 		while (current->next_logical_descriptor != tail)
596 			current = (ohci_general_td *)current->next_logical_descriptor;
597 		// Append to current
598 		current->next_logical_descriptor = first;
599 		current->next_physical_descriptor = first->physical_address;
600 	} else {
601 		// Endpoint has only the dummy descriptor
602 		endpoint->head_logical_descriptor = first;
603 		endpoint->head_physical_descriptor = first->physical_address;
604 	}
605 
606 	// Make the last descriptor point to the dummy
607 	last->next_logical_descriptor = tail;
608 	last->next_physical_descriptor = tail->physical_address;
609 
610 	endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
611 	return B_OK;
612 }
613 
614 
615 void
616 OHCI::_RemoveTransferFromEndpoint(transfer_data *transfer)
617 {
618 	// TODO: Add lock for endpoint
619 	ohci_endpoint_descriptor *endpoint = transfer->endpoint;
620 	ohci_general_td *next = (ohci_general_td *)endpoint->head_logical_descriptor;
621 
622 	// Find the first descriptor of a different transfer.
623 	// Worst scenario we get the dummy descriptor
624 	while ((transfer_data *)next->transfer == transfer)
625 		next = (ohci_general_td *)next->next_logical_descriptor;
626 	// Update head
627 	endpoint->head_logical_descriptor = next;
628 	endpoint->head_physical_descriptor = next->physical_address;
629 }
630 
631 
632 status_t
633 OHCI::_UnlinkTransfer(transfer_data *transfer)
634 {
635 	if (Lock()) {
636 		if (transfer == fFirstTransfer) {
637 			// It was the first element
638 			fFirstTransfer = fFirstTransfer->link;
639 			if (transfer == fLastTransfer)
640 				// Also the only one
641 				fLastTransfer = NULL;
642 		} else {
643 			transfer_data *data = fFirstTransfer->link;
644 			transfer_data *previous = fFirstTransfer;
645 			while (data != NULL) {
646 				if (data == transfer) {
647 					previous->link = data->link;
648 					if (data == fLastTransfer)
649 						fLastTransfer = previous;
650 					break;
651 				}
652 				previous = data;
653 				data = data->link;
654 			}
655 		}
656 		Unlock();
657 		return B_OK;
658 	}
659 	return B_ERROR;
660 }
661 
662 
663 void
664 OHCI::_AddDescriptorToHash(ohci_general_td *descriptor)
665 {
666 	// TODO
667 }
668 
669 
670 void
671 OHCI::_RemoveDescriptorFromHash(ohci_general_td *descriptor)
672 {
673 	// TODO
674 }
675 
676 
677 ohci_general_td*
678 OHCI::_FindDescriptorInHash(uint32 physicalAddress)
679 {
680 	// TODO
681 	return NULL;
682 }
683 
684 
685 void
686 OHCI::_AddIsoDescriptorToHash(ohci_isochronous_td *descriptor)
687 {
688 	// TODO
689 }
690 
691 
692 void
693 OHCI::_RemoveIsoDescriptorFromHash(ohci_isochronous_td *descriptor)
694 {
695 	// TODO
696 }
697 
698 
699 ohci_isochronous_td*
700 OHCI::_FindIsoDescriptorInHash(uint32 physicalAddress)
701 {
702 	// TODO
703 	return NULL;
704 }
705 
706 
707 status_t
708 OHCI::Start()
709 {
710 	TRACE(("usb_ohci: starting OHCI Host Controller\n"));
711 
712 	if ((_ReadReg(OHCI_CONTROL) & OHCI_HC_FUNCTIONAL_STATE_MASK)
713 		!= OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL) {
714 		TRACE_ERROR(("usb_ohci: Controller not started!\n"));
715 		return B_ERROR;
716 	} else {
717 		TRACE(("usb_ohci: Controller is OPERATIONAL!\n"));
718 	}
719 
720 	fRootHubAddress = AllocateAddress();
721 	fRootHub = new(std::nothrow) OHCIRootHub(RootObject(), fRootHubAddress);
722 	if (!fRootHub) {
723 		TRACE_ERROR(("usb_ohci: no memory to allocate root hub\n"));
724 		return B_NO_MEMORY;
725 	}
726 
727 	if (fRootHub->InitCheck() < B_OK) {
728 		TRACE_ERROR(("usb_ohci: root hub failed init check\n"));
729 		return B_ERROR;
730 	}
731 
732 	SetRootHub(fRootHub);
733 	TRACE(("usb_ohci: Host Controller started\n"));
734 	return BusManager::Start();
735 }
736 
737 
738 status_t
739 OHCI::SubmitTransfer(Transfer *transfer)
740 {
741 	// short circuit the root hub
742 	if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
743 		return fRootHub->ProcessTransfer(this, transfer);
744 
745 	uint32 type = transfer->TransferPipe()->Type();
746 	if ((type & USB_OBJECT_CONTROL_PIPE)) {
747 		TRACE(("usb_ohci: submitting control request\n"));
748 		return _SubmitControlRequest(transfer);
749 	}
750 
751 	if ((type & USB_OBJECT_BULK_PIPE)) {
752 		TRACE(("usb_ohci: submitting bulk transfer\n"));
753 		return _SubmitBulkTransfer(transfer);
754 	}
755 
756 	if (((type & USB_OBJECT_ISO_PIPE) || (type & USB_OBJECT_INTERRUPT_PIPE))) {
757 		TRACE(("usb_ohci: submitting periodic transfer\n"));
758 		return _SubmitPeriodicTransfer(transfer);
759 	}
760 
761 	TRACE_ERROR(("usb_ohci: tried to submit transfer for unknown pipe"
762 		" type %lu\n", type));
763 	return B_ERROR;
764 }
765 
766 
767 status_t
768 OHCI::_SubmitControlRequest(Transfer *transfer)
769 {
770 	usb_request_data *requestData = transfer->RequestData();
771 	bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0;
772 
773 	ohci_general_td *setupDescriptor
774 		= _CreateGeneralDescriptor(sizeof(usb_request_data));
775 	if (!setupDescriptor) {
776 		TRACE_ERROR(("usb_ohci: failed to allocate setup descriptor\n"));
777 		return B_NO_MEMORY;
778 	}
779 	// Flags set up could be moved into _CreateGeneralDescriptor
780 	setupDescriptor->flags |= OHCI_TD_DIRECTION_PID_SETUP
781 		| OHCI_TD_NO_CONDITION_CODE
782 		| OHCI_TD_TOGGLE_0
783 		| OHCI_TD_SET_DELAY_INTERRUPT(6); // Not sure about this.
784 
785 	ohci_general_td *statusDescriptor
786 		= _CreateGeneralDescriptor(0);
787 	if (!statusDescriptor) {
788 		TRACE_ERROR(("usb_ohci: failed to allocate status descriptor\n"));
789 		_FreeGeneralDescriptor(setupDescriptor);
790 		return B_NO_MEMORY;
791 	}
792 	statusDescriptor->flags
793 		|= (directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN)
794 		| OHCI_TD_NO_CONDITION_CODE
795 		| OHCI_TD_TOGGLE_1
796 		| OHCI_TD_SET_DELAY_INTERRUPT(1);
797 
798 	iovec vector;
799 	vector.iov_base = requestData;
800 	vector.iov_len = sizeof(usb_request_data);
801 	_WriteDescriptorChain(setupDescriptor, &vector, 1);
802 
803 	status_t  result;
804 	ohci_general_td *dataDescriptor = NULL;
805 	if (transfer->VectorCount() > 0) {
806 		ohci_general_td *lastDescriptor = NULL;
807 		result = _CreateDescriptorChain(&dataDescriptor,
808 			&lastDescriptor,
809 			directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN,
810 			transfer->VectorLength());
811 		if (result < B_OK) {
812 			_FreeGeneralDescriptor(setupDescriptor);
813 			_FreeGeneralDescriptor(statusDescriptor);
814 			return result;
815 		}
816 
817 		if (!directionIn) {
818 			_WriteDescriptorChain(dataDescriptor, transfer->Vector(),
819 				transfer->VectorCount());
820 		}
821 
822 		_LinkDescriptors(setupDescriptor, dataDescriptor);
823 		_LinkDescriptors(lastDescriptor, statusDescriptor);
824 	} else {
825 		_LinkDescriptors(setupDescriptor, statusDescriptor);
826 	}
827 
828 	// Append Transfer
829 	ohci_endpoint_descriptor *endpoint
830 		= (ohci_endpoint_descriptor *)transfer->TransferPipe()->ControllerCookie();
831 	result = _AddPendingTransfer(transfer, endpoint, setupDescriptor,
832 		dataDescriptor,	directionIn);
833 	if (result < B_OK) {
834 		TRACE_ERROR(("usb_ohci: failed to add pending transfer\n"));
835 		_FreeDescriptorChain(setupDescriptor);
836 		return result;
837 	}
838 
839 	// Append descriptors chain to the endpoint
840 	result = _AppendChainDescriptorsToEndpoint(endpoint, setupDescriptor,
841 		statusDescriptor);
842 	if (result < B_OK) {
843 		TRACE_ERROR(("usb_ohci: failed to append chain descriptors to endpoint\n"));
844 		// TODO: Remove transfer_data from list
845 		_FreeDescriptorChain(setupDescriptor);
846 	}
847 
848 	// Tell the controller to process the control list
849 	_WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED);
850 	return B_OK;
851 }
852 
853 
854 status_t
855 OHCI::_SubmitBulkTransfer(Transfer *transfer)
856 {
857 	// TODO
858 	return B_ERROR;
859 }
860 
861 
862 status_t
863 OHCI::_AddPendingTransfer(Transfer *transfer, ohci_endpoint_descriptor *endpoint,
864 	ohci_general_td *firstDescriptor, ohci_general_td *dataDescriptor, bool directionIn)
865 {
866 	if (!transfer || !endpoint || !firstDescriptor)
867 		return B_BAD_VALUE;
868 
869 	transfer_data *data = new(std::nothrow) transfer_data;
870 	if (!data)
871 		return B_NO_MEMORY;
872 
873 	status_t result = transfer->InitKernelAccess();
874 	if (result < B_OK) {
875 		delete data;
876 		return result;
877 	}
878 
879 	data->transfer = transfer;
880 	data->endpoint = endpoint;
881 	data->first_descriptor = firstDescriptor;
882 	data->data_descriptor = dataDescriptor;
883 	data->incoming = directionIn;
884 	data->canceled = false;
885 	data->link = NULL;
886 
887 	if (!Lock()) {
888 		delete data;
889 		return B_ERROR;
890 	}
891 
892 	if (fLastTransfer)
893 		fLastTransfer->link = data;
894 	else
895 		fFirstTransfer = data;
896 
897 	fLastTransfer = data;
898 	Unlock();
899 
900 	return B_OK;
901 }
902 
903 
904 status_t
905 OHCI::_SubmitPeriodicTransfer(Transfer *transfer)
906 {
907 	return B_ERROR;
908 }
909 
910 
911 void
912 OHCI::_LinkDescriptors(ohci_general_td *first, ohci_general_td *second)
913 {
914 	first->next_physical_descriptor = second->physical_address;
915 	first->next_logical_descriptor = second;
916 }
917 
918 
919 status_t
920 OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor,
921 	ohci_general_td **_lastDescriptor, uint8 direction, size_t bufferSize)
922 {
923 	return B_ERROR;
924 }
925 
926 
927 void
928 OHCI::_FreeDescriptorChain(ohci_general_td *topDescriptor)
929 {
930 	ohci_general_td *current = topDescriptor;
931 	ohci_general_td *next = NULL;
932 
933 	while (current) {
934 		next = (ohci_general_td *)current->next_logical_descriptor;
935 		_FreeGeneralDescriptor(current);
936 		current = next;
937 	}
938 }
939 
940 
941 size_t
942 OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
943 	size_t vectorCount)
944 {
945 	ohci_general_td *current = topDescriptor;
946 	size_t actualLength = 0;
947 	size_t vectorIndex = 0;
948 	size_t vectorOffset = 0;
949 	size_t bufferOffset = 0;
950 
951 	while (current) {
952 		if (!current->buffer_logical)
953 			break;
954 
955 		while (true) {
956 			size_t length = min_c(current->buffer_size - bufferOffset,
957 				vector[vectorIndex].iov_len - vectorOffset);
958 
959 			TRACE(("usb_ohci: copying %ld bytes to bufferOffset %ld from"
960 				" vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
961 				vectorOffset, vectorIndex, vectorCount));
962 			memcpy((uint8 *)current->buffer_logical + bufferOffset,
963 				(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
964 
965 			actualLength += length;
966 			vectorOffset += length;
967 			bufferOffset += length;
968 
969 			if (vectorOffset >= vector[vectorIndex].iov_len) {
970 				if (++vectorIndex >= vectorCount) {
971 					TRACE(("usb_ohci: wrote descriptor chain (%ld bytes, no"
972 						" more vectors)\n", actualLength));
973 					return actualLength;
974 				}
975 
976 				vectorOffset = 0;
977 			}
978 
979 			if (bufferOffset >= current->buffer_size) {
980 				bufferOffset = 0;
981 				break;
982 			}
983 		}
984 
985 		if (!current->next_logical_descriptor)
986 			break;
987 
988 		current = (ohci_general_td *)current->next_logical_descriptor;
989 	}
990 
991 	TRACE(("usb_ohci: wrote descriptor chain (%ld bytes)\n", actualLength));
992 	return actualLength;
993 }
994 
995 
996 status_t
997 OHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
998 {
999 	TRACE(("usb_ohci: pipe change %d for pipe 0x%08lx\n", change, (uint32)pipe));
1000 	switch (change) {
1001 		case USB_CHANGE_CREATED: {
1002 			TRACE(("usb_ohci: inserting endpoint\n"));
1003 			return _InsertEndpointForPipe(pipe);
1004 		}
1005 		case USB_CHANGE_DESTROYED: {
1006 			TRACE(("usb_ohci: removing endpoint\n"));
1007 			return _RemoveEndpointForPipe(pipe);
1008 		}
1009 		case USB_CHANGE_PIPE_POLICY_CHANGED: {
1010 			TRACE(("usb_ohci: pipe policy changing unhandled!\n"));
1011 			break;
1012 		}
1013 		default: {
1014 			TRACE_ERROR(("usb_ohci: unknown pipe change!\n"));
1015 			return B_ERROR;
1016 		}
1017 	}
1018 	return B_OK;
1019 }
1020 
1021 
1022 status_t
1023 OHCI::AddTo(Stack *stack)
1024 {
1025 #ifdef TRACE_USB
1026 	set_dprintf_enabled(true);
1027 	load_driver_symbols("ohci");
1028 #endif
1029 
1030 	if (!sPCIModule) {
1031 		status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
1032 		if (status < B_OK) {
1033 			TRACE_ERROR(("usb_ohci: getting pci module failed! 0x%08lx\n",
1034 				status));
1035 			return status;
1036 		}
1037 	}
1038 
1039 	TRACE(("usb_ohci: searching devices\n"));
1040 	bool found = false;
1041 	pci_info *item = new(std::nothrow) pci_info;
1042 	if (!item) {
1043 		sPCIModule = NULL;
1044 		put_module(B_PCI_MODULE_NAME);
1045 		return B_NO_MEMORY;
1046 	}
1047 
1048 	for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
1049 
1050 		if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
1051 			&& item->class_api == PCI_usb_ohci) {
1052 			if (item->u.h0.interrupt_line == 0
1053 				|| item->u.h0.interrupt_line == 0xFF) {
1054 				TRACE_ERROR(("usb_ohci: found device with invalid IRQ -"
1055 					" check IRQ assignement\n"));
1056 				continue;
1057 			}
1058 
1059 			TRACE(("usb_ohci: found device at IRQ %u\n",
1060 				item->u.h0.interrupt_line));
1061 			OHCI *bus = new(std::nothrow) OHCI(item, stack);
1062 			if (!bus) {
1063 				delete item;
1064 				sPCIModule = NULL;
1065 				put_module(B_PCI_MODULE_NAME);
1066 				return B_NO_MEMORY;
1067 			}
1068 
1069 			if (bus->InitCheck() < B_OK) {
1070 				TRACE_ERROR(("usb_ohci: bus failed init check\n"));
1071 				delete bus;
1072 				continue;
1073 			}
1074 
1075 			// the bus took it away
1076 			item = new(std::nothrow) pci_info;
1077 
1078 			bus->Start();
1079 			stack->AddBusManager(bus);
1080 			found = true;
1081 		}
1082 	}
1083 
1084 	if (!found) {
1085 		TRACE_ERROR(("usb_ohci: no devices found\n"));
1086 		delete item;
1087 		sPCIModule = NULL;
1088 		put_module(B_PCI_MODULE_NAME);
1089 		return ENODEV;
1090 	}
1091 
1092 	delete item;
1093 	return B_OK;
1094 }
1095 
1096 
1097 status_t
1098 OHCI::GetPortStatus(uint8 index, usb_port_status *status)
1099 {
1100 	TRACE(("usb_ohci::%s(%ud, )\n", __FUNCTION__, index));
1101 	if (index >= fPortCount)
1102 		return B_BAD_INDEX;
1103 
1104 	status->status = status->change = 0;
1105 	uint32 portStatus = _ReadReg(OHCI_RH_PORT_STATUS(index));
1106 
1107 	TRACE(("usb_ohci: RootHub::GetPortStatus: Port %i Value 0x%lx\n", OHCI_RH_PORT_STATUS(index), portStatus));
1108 
1109 	// status
1110 	if (portStatus & OHCI_RH_PORTSTATUS_CCS)
1111 		status->status |= PORT_STATUS_CONNECTION;
1112 	if (portStatus & OHCI_RH_PORTSTATUS_PES)
1113 		status->status |= PORT_STATUS_ENABLE;
1114 	if (portStatus & OHCI_RH_PORTSTATUS_PRS)
1115 		status->status |= PORT_STATUS_RESET;
1116 	if (portStatus & OHCI_RH_PORTSTATUS_LSDA)
1117 		status->status |= PORT_STATUS_LOW_SPEED;
1118 	if (portStatus & OHCI_RH_PORTSTATUS_PSS)
1119 		status->status |= PORT_STATUS_SUSPEND;
1120 	if (portStatus & OHCI_RH_PORTSTATUS_POCI)
1121 		status->status |= PORT_STATUS_OVER_CURRENT;
1122 	if (portStatus & OHCI_RH_PORTSTATUS_PPS)
1123 		status->status |= PORT_STATUS_POWER;
1124 
1125 	// change
1126 	if (portStatus & OHCI_RH_PORTSTATUS_CSC)
1127 		status->change |= PORT_STATUS_CONNECTION;
1128 	if (portStatus & OHCI_RH_PORTSTATUS_PESC)
1129 		status->change |= PORT_STATUS_ENABLE;
1130 	if (portStatus & OHCI_RH_PORTSTATUS_PSSC)
1131 		status->change |= PORT_STATUS_SUSPEND;
1132 	if (portStatus & OHCI_RH_PORTSTATUS_OCIC)
1133 		status->change |= PORT_STATUS_OVER_CURRENT;
1134 	if (portStatus & OHCI_RH_PORTSTATUS_PRSC)
1135 		status->change |= PORT_STATUS_RESET;
1136 
1137 	return B_OK;
1138 }
1139 
1140 
1141 status_t
1142 OHCI::SetPortFeature(uint8 index, uint16 feature)
1143 {
1144 	TRACE(("OHCI::%s(%ud, %ud)\n", __FUNCTION__, index, feature));
1145 	if (index > fPortCount)
1146 		return B_BAD_INDEX;
1147 
1148 	switch (feature) {
1149 		case PORT_RESET:
1150 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRS);
1151 			return B_OK;
1152 
1153 		case PORT_POWER:
1154 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PPS);
1155 			return B_OK;
1156 	}
1157 
1158 	return B_BAD_VALUE;
1159 }
1160 
1161 
1162 status_t
1163 OHCI::ClearPortFeature(uint8 index, uint16 feature)
1164 {
1165 	TRACE(("OHCI::%s(%ud, %ud)\n", __FUNCTION__, index, feature));
1166 	if (index > fPortCount)
1167 		return B_BAD_INDEX;
1168 
1169 	switch (feature) {
1170 		case C_PORT_RESET:
1171 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CSC);
1172 			return B_OK;
1173 
1174 		case C_PORT_CONNECTION:
1175 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CSC);
1176 			return B_OK;
1177 	}
1178 
1179 	return B_BAD_VALUE;
1180 }
1181 
1182 
1183 ohci_endpoint_descriptor*
1184 OHCI::_AllocateEndpoint()
1185 {
1186 	ohci_endpoint_descriptor *endpoint;
1187 	void* physicalAddress;
1188 
1189 	// Allocate memory chunk
1190 	if (fStack->AllocateChunk((void **)&endpoint, &physicalAddress,
1191 		sizeof(ohci_endpoint_descriptor)) < B_OK) {
1192 		TRACE_ERROR(("usb_ohci: failed to allocate endpoint descriptor\n"));
1193 		return NULL;
1194 	}
1195 	memset((void *)endpoint, 0, sizeof(ohci_endpoint_descriptor));
1196 
1197 	endpoint->physical_address = (addr_t)physicalAddress;
1198 
1199 	endpoint->head_physical_descriptor = NULL;
1200 	endpoint->tail_physical_descriptor = NULL;
1201 
1202 	endpoint->head_logical_descriptor = NULL;
1203 	endpoint->tail_logical_descriptor = NULL;
1204 
1205 	return endpoint;
1206 }
1207 
1208 
1209 void
1210 OHCI::_FreeEndpoint(ohci_endpoint_descriptor *endpoint)
1211 {
1212 	if (!endpoint)
1213 		return;
1214 
1215 	fStack->FreeChunk((void *)endpoint, (void *)endpoint->physical_address,
1216 		sizeof(ohci_endpoint_descriptor));
1217 }
1218 
1219 
1220 ohci_general_td*
1221 OHCI::_CreateGeneralDescriptor(size_t bufferSize)
1222 {
1223 	ohci_general_td *descriptor;
1224 	void *physicalAddress;
1225 
1226 	if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
1227 		sizeof(ohci_general_td)) != B_OK) {
1228 		TRACE_ERROR(("usb_ohci: failed to allocate general descriptor\n"));
1229 		return NULL;
1230 	}
1231 	memset((void *)descriptor, 0, sizeof(ohci_general_td));
1232 	descriptor->physical_address = (addr_t)physicalAddress;
1233 
1234 	if (!bufferSize) {
1235 		descriptor->buffer_physical = 0;
1236 		descriptor->buffer_logical = NULL;
1237 		descriptor->last_physical_byte_address = 0;
1238 		return descriptor;
1239 	}
1240 
1241 	if (fStack->AllocateChunk(&descriptor->buffer_logical,
1242 		(void **)&descriptor->buffer_physical, bufferSize) != B_OK) {
1243 		TRACE_ERROR(("usb_ohci: failed to allocate space for buffer\n"));
1244 		fStack->FreeChunk(descriptor, (void *)descriptor->physical_address,
1245 			sizeof(ohci_general_td));
1246 		return NULL;
1247 	}
1248 	descriptor->last_physical_byte_address
1249 		= descriptor->buffer_physical + bufferSize - 1;
1250 
1251 	return descriptor;
1252 }
1253 
1254 
1255 void
1256 OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor)
1257 {
1258 	if (!descriptor)
1259 		return;
1260 
1261 	if (descriptor->buffer_logical) {
1262 		fStack->FreeChunk(descriptor->buffer_logical,
1263 			(void *)descriptor->buffer_physical, descriptor->buffer_size);
1264 	}
1265 
1266 	fStack->FreeChunk((void *)descriptor, (void *)descriptor->physical_address,
1267 		sizeof(ohci_general_td));
1268 }
1269 
1270 
1271 ohci_isochronous_td*
1272 _CreateIsochronousDescriptor()
1273 {
1274 	// TODO
1275 	return NULL;
1276 }
1277 
1278 
1279 void _FreeIsochronousDescriptor(ohci_isochronous_td *descriptor)
1280 {
1281 	// TODO
1282 }
1283 
1284 
1285 status_t
1286 OHCI::_InsertEndpointForPipe(Pipe *pipe)
1287 {
1288 	TRACE(("OHCI: Inserting Endpoint for device %u function %u\n",
1289 		pipe->DeviceAddress(), pipe->EndpointAddress()));
1290 
1291 	ohci_endpoint_descriptor *endpoint = _AllocateEndpoint();
1292 	if (!endpoint) {
1293 		TRACE_ERROR(("usb_ohci: cannot allocate memory for endpoint\n"));
1294 		return B_NO_MEMORY;
1295 	}
1296 
1297 	uint32 flags = 0;
1298 	flags |= OHCI_ENDPOINT_SKIP;
1299 
1300 	// Set up device and endpoint address
1301 	flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(pipe->DeviceAddress())
1302 		| OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(pipe->EndpointAddress());
1303 
1304 	// Set the direction
1305 	switch (pipe->Direction()) {
1306 		case Pipe::In:
1307 			flags |= OHCI_ENDPOINT_DIRECTION_IN;
1308 			break;
1309 		case Pipe::Out:
1310 			flags |= OHCI_ENDPOINT_DIRECTION_OUT;
1311 			break;
1312 		case Pipe::Default:
1313 			flags |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR;
1314 			break;
1315 		default:
1316 			TRACE_ERROR(("usb_ohci: direction unknown. Wrong value!\n"));
1317 			_FreeEndpoint(endpoint);
1318 			return B_ERROR;
1319 	}
1320 
1321 	// Set up the speed
1322 	switch (pipe->Speed()) {
1323 		case USB_SPEED_LOWSPEED:
1324 			flags |= OHCI_ENDPOINT_LOW_SPEED;
1325 			break;
1326 		case USB_SPEED_FULLSPEED:
1327 			flags |= OHCI_ENDPOINT_FULL_SPEED;
1328 			break;
1329 		case USB_SPEED_HIGHSPEED:
1330 		default:
1331 			TRACE_ERROR(("usb_ohci: unaccetable speed. Wrong value!\n"));
1332 			_FreeEndpoint(endpoint);
1333 			return B_ERROR;
1334 	}
1335 
1336 	// Set the maximum packet size
1337 	flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(pipe->MaxPacketSize());
1338 
1339 	endpoint->flags = flags;
1340 
1341 	// Add the endpoint to the appropriate list
1342 	ohci_endpoint_descriptor *head = NULL;
1343 	switch (pipe->Type()) {
1344 		case USB_OBJECT_CONTROL_PIPE:
1345 			head = fDummyControl;
1346 			break;
1347 		case USB_OBJECT_BULK_PIPE:
1348 			head = fDummyBulk;
1349 			break;
1350 		case USB_OBJECT_ISO_PIPE:
1351 			// Set the isochronous bit format
1352 			endpoint->flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
1353 			head = fDummyIsochronous;
1354 			break;
1355 		case USB_OBJECT_INTERRUPT_PIPE:
1356 			head = _FindInterruptEndpoint(pipe->Interval());
1357 			break;
1358 		default:
1359 			TRACE_ERROR(("usb_ohci: unknown type of pipe. Wrong value!\n"));
1360 			_FreeEndpoint(endpoint);
1361 			return B_ERROR;
1362 	}
1363 
1364 	// Create (necessary) dummy descriptor
1365 	if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
1366 		// TODO
1367 	} else {
1368 		ohci_general_td *dummy = _CreateGeneralDescriptor(0);
1369 		dummy->next_logical_descriptor = NULL;
1370 		dummy->next_physical_descriptor = NULL;
1371 		endpoint->head_logical_descriptor
1372 			= endpoint->tail_logical_descriptor
1373 			= dummy;
1374 		endpoint->head_physical_descriptor
1375 			= endpoint->tail_physical_descriptor
1376 			= dummy->physical_address;
1377 	}
1378 
1379 	// TODO: Change lock lo LockEndpoint()
1380 	Lock();
1381 	pipe->SetControllerCookie((void *)endpoint);
1382 	endpoint->next_logical_endpoint = head->next_logical_endpoint;
1383 	endpoint->next_physical_endpoint = head->next_physical_endpoint;
1384 	head->next_logical_endpoint = (void *)endpoint;
1385 	head->next_physical_endpoint = (uint32)endpoint->physical_address;
1386 	Unlock();
1387 
1388 	return B_OK;
1389 }
1390 
1391 
1392 ohci_endpoint_descriptor*
1393 OHCI::_FindInterruptEndpoint(uint8 interval)
1394 {
1395 	return NULL;
1396 }
1397 
1398 
1399 status_t
1400 OHCI::_RemoveEndpointForPipe(Pipe *pipe)
1401 {
1402 	return B_ERROR;
1403 }
1404 
1405 
1406 inline void
1407 OHCI::_WriteReg(uint32 reg, uint32 value)
1408 {
1409 	*(volatile uint32 *)(fOperationalRegisters + reg) = value;
1410 }
1411 
1412 
1413 inline uint32
1414 OHCI::_ReadReg(uint32 reg)
1415 {
1416 	return *(volatile uint32 *)(fOperationalRegisters + reg);
1417 }
1418 
1419 
1420 status_t
1421 OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
1422 {
1423 	if (pipe->Type() & USB_OBJECT_ISO_PIPE)
1424 		return _CancelQueuedIsochronousTransfers(pipe, force);
1425 
1426 	if (!Lock())
1427 		return B_ERROR;
1428 
1429 	transfer_data *current = fFirstTransfer;
1430 	while (current) {
1431 		if (current->transfer->TransferPipe() == pipe) {
1432 			// Check if the skip bit is already set
1433 			if (!(current->endpoint->flags & OHCI_ENDPOINT_SKIP)) {
1434 				current->endpoint->flags |= OHCI_ENDPOINT_SKIP;
1435 				// In case the controller is processing
1436 				// this endpoint, wait for it to finish
1437 				snooze(1000);
1438 			}
1439 			// Clear the endpoint
1440 			current->endpoint->head_physical_descriptor = NULL;
1441 			current->endpoint->tail_physical_descriptor = NULL;
1442 			current->endpoint->head_logical_descriptor = NULL;
1443 			current->endpoint->tail_logical_descriptor = NULL;
1444 
1445 			if (!force) {
1446 				// If the transfer is canceled by force, the one causing the
1447 				// cancel is probably not the one who initiated the transfer
1448 				// and the callback is likely not safe anymore
1449 				current->transfer->Finished(B_CANCELED, 0);
1450 			}
1451 			current->canceled = true;
1452 		}
1453 		current = current->link;
1454 	}
1455 
1456 	Unlock();
1457 
1458 	// notify the finisher so it can clean up the canceled transfers
1459 	release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
1460 	return B_OK;
1461 }
1462 
1463 
1464 status_t
1465 OHCI::_CancelQueuedIsochronousTransfers(Pipe *pipe, bool force)
1466 {
1467 	// TODO
1468 	return B_ERROR;
1469 }
1470