xref: /haiku/src/add-ons/kernel/busses/usb/ohci.cpp (revision 020cbad9d40235a2c50a81a42d69912a5ff8fbc4)
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 		// Pull out the done list and reverse its order
458 		// for both general and isochronous descriptors
459 		ohci_general_td *current, *top;
460 		ohci_isochronous_td *isoCurrent, *isoTop;
461 		uint32 done_list = fHcca->done_head & ~OHCI_DONE_INTERRUPTS;
462 		for ( top = NULL, isoTop = NULL ; done_list != 0; ) {
463 			if ((current = _FindDescriptorInHash(done_list))) {
464 				done_list = current->next_physical_descriptor;
465 				current->next_done_descriptor = (void *)top;
466 				top = current;
467 				continue;
468 			}
469 			if ((isoCurrent = _FindIsoDescriptorInHash(done_list))) {
470 				done_list = isoCurrent->next_physical_descriptor;
471 				isoCurrent->next_done_descriptor = (void *)isoTop;
472 				isoTop = isoCurrent;
473 				continue;
474 			}
475 			// TODO: Should I panic here? :)
476 			TRACE_ERROR(("usb_ohci: address 0x%08lx not found!\n",done_list));
477 			break;
478 		}
479 
480 		// Acknowledge the interrupt
481 		// TODO: Move the acknowledgement in the interrupt handler. The done_head
482 		// value can be passed through a shared variable.
483 		fHcca->done_head = 0;
484 		_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_WRITEBACK_DONE_HEAD);
485 
486 		// Process isochronous list first
487 		for (isoCurrent = isoTop; isoCurrent != NULL; isoCurrent
488 			= (ohci_isochronous_td *)isoCurrent->next_done_descriptor) {
489 			// TODO: Process isochronous descriptors
490 		}
491 		// Now process the general list
492 		for (current = top; current != NULL; ) {
493 			ohci_general_td *next = (ohci_general_td *)current->next_done_descriptor;
494 			// TODO: Handle cancelled and timeout
495 			uint32 conditionCode = OHCI_TD_GET_CONDITION_CODE(current->flags);
496 			if (conditionCode != OHCI_NO_ERROR) {
497 				// Endpoint is halted
498 				// 1. Unlink the transfer
499 				// 2. Free all descriptors of the transfer
500 				// 3. Notify the caller.
501 				// 4. Restart the endpoint
502 				// NOTE: There can(should) not be more than one
503 				// invalid descriptor from the same transfer in the
504 				// done list, as the controller halt the endpoint right
505 				// away if a descriptor fails. This means that, if we reversed
506 				// the order of the done list (which we did), there is
507 				// not reason to look for more failed descriptors in the
508 				// done list from the same transfer, as *BSD code does.
509 				TRACE(("usb_ohci: transfer failed! ohci error code: %d\n",
510 					conditionCode));
511 
512 				// Unlink the transfer
513 				// TODO: check the return value
514 				transfer_data *transfer = (transfer_data *)current->transfer;
515 				_UnlinkTransfer(transfer);
516 
517 				// Free all descriptors of this transfer
518 				next = (ohci_general_td *)current->next_done_descriptor;
519 				_FreeDescriptorChain(transfer->first_descriptor);
520 
521 				// Restart the endpoint
522 				// TODO: what if there are other transfer to this endpoint?
523 				ohci_endpoint_descriptor *endpoint
524 					= (ohci_endpoint_descriptor *)transfer->endpoint;
525 				endpoint->head_physical_descriptor = 0;
526 
527 				// Notify the caller
528 				transfer->transfer->Finished(B_CANCELED, 0);
529 				delete transfer->transfer;
530 				delete transfer;
531 				continue;
532 			}
533 
534 			if (current->is_last) {
535 				// TODO: Trasfer completed
536 			}
537 
538 			current = next;
539 		}
540 	}
541 }
542 
543 
544 status_t
545 OHCI::_UnlinkTransfer(transfer_data *transfer)
546 {
547 	if (Lock()) {
548 		if (transfer == fFirstTransfer) {
549 			// It was the first element
550 			fFirstTransfer = fFirstTransfer->link;
551 			if (transfer == fLastTransfer)
552 				// Also the only one
553 				fLastTransfer = NULL;
554 		} else {
555 			transfer_data *data = fFirstTransfer->link;
556 			transfer_data *previous = fFirstTransfer;
557 			while (data != NULL) {
558 				if (data == transfer) {
559 					previous->link = data->link;
560 					if (data == fLastTransfer)
561 						fLastTransfer = previous;
562 					break;
563 				}
564 				previous = data;
565 				data = data->link;
566 			}
567 		}
568 		Unlock();
569 		return B_OK;
570 	}
571 	return B_ERROR;
572 }
573 
574 
575 void
576 OHCI::_AddDescriptorToHash(ohci_general_td *descriptor)
577 {
578 	// TODO
579 }
580 
581 
582 void
583 OHCI::_RemoveDescriptorFromHash(ohci_general_td *descriptor)
584 {
585 	// TODO
586 }
587 
588 
589 ohci_general_td*
590 OHCI::_FindDescriptorInHash(uint32 physicalAddress)
591 {
592 	// TODO
593 	return NULL;
594 }
595 
596 
597 void
598 OHCI::_AddIsoDescriptorToHash(ohci_isochronous_td *descriptor)
599 {
600 	// TODO
601 }
602 
603 
604 void
605 OHCI::_RemoveIsoDescriptorFromHash(ohci_isochronous_td *descriptor)
606 {
607 	// TODO
608 }
609 
610 
611 ohci_isochronous_td*
612 OHCI::_FindIsoDescriptorInHash(uint32 physicalAddress)
613 {
614 	// TODO
615 	return NULL;
616 }
617 
618 
619 status_t
620 OHCI::Start()
621 {
622 	TRACE(("usb_ohci: starting OHCI Host Controller\n"));
623 
624 	if ((_ReadReg(OHCI_CONTROL) & OHCI_HC_FUNCTIONAL_STATE_MASK)
625 		!= OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL) {
626 		TRACE_ERROR(("usb_ohci: Controller not started!\n"));
627 		return B_ERROR;
628 	} else {
629 		TRACE(("usb_ohci: Controller is OPERATIONAL!\n"));
630 	}
631 
632 	fRootHubAddress = AllocateAddress();
633 	fRootHub = new(std::nothrow) OHCIRootHub(RootObject(), fRootHubAddress);
634 	if (!fRootHub) {
635 		TRACE_ERROR(("usb_ohci: no memory to allocate root hub\n"));
636 		return B_NO_MEMORY;
637 	}
638 
639 	if (fRootHub->InitCheck() < B_OK) {
640 		TRACE_ERROR(("usb_ohci: root hub failed init check\n"));
641 		return B_ERROR;
642 	}
643 
644 	SetRootHub(fRootHub);
645 	TRACE(("usb_ohci: Host Controller started\n"));
646 	return BusManager::Start();
647 }
648 
649 
650 status_t
651 OHCI::SubmitTransfer(Transfer *transfer)
652 {
653 	// short circuit the root hub
654 	if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
655 		return fRootHub->ProcessTransfer(this, transfer);
656 
657 	uint32 type = transfer->TransferPipe()->Type();
658 	if ((type & USB_OBJECT_CONTROL_PIPE)) {
659 		TRACE(("usb_ohci: submitting control request\n"));
660 		return _SubmitControlRequest(transfer);
661 	}
662 
663 	if ((type & USB_OBJECT_INTERRUPT_PIPE) || (type & USB_OBJECT_BULK_PIPE)) {
664 		// TODO
665 		return B_OK;
666 	}
667 
668 	if ((type & USB_OBJECT_ISO_PIPE)) {
669 		TRACE(("usb_ohci: submitting isochronous transfer\n"));
670 		return _SubmitIsochronousTransfer(transfer);
671 	}
672 
673 	TRACE_ERROR(("usb_ohci: tried to submit transfer for unknown pipe"
674 		" type %lu\n", type));
675 	return B_ERROR;
676 }
677 
678 
679 status_t
680 OHCI::_SubmitControlRequest(Transfer *transfer)
681 {
682 	usb_request_data *requestData = transfer->RequestData();
683 	bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0;
684 
685 	ohci_general_td *setupDescriptor
686 		= _CreateGeneralDescriptor(sizeof(usb_request_data));
687 	if (!setupDescriptor) {
688 		TRACE_ERROR(("usb_ohci: failed to allocate setup descriptor\n"));
689 		return B_NO_MEMORY;
690 	}
691 	// Flags set up could be moved into _CreateGeneralDescriptor
692 	setupDescriptor->flags |= OHCI_TD_DIRECTION_PID_SETUP
693 		| OHCI_TD_NO_CONDITION_CODE
694 		| OHCI_TD_TOGGLE_0
695 		| OHCI_TD_SET_DELAY_INTERRUPT(6); // Not sure about this.
696 
697 	ohci_general_td *statusDescriptor
698 		= _CreateGeneralDescriptor(0);
699 	if (!statusDescriptor) {
700 		TRACE_ERROR(("usb_ohci: failed to allocate status descriptor\n"));
701 		_FreeGeneralDescriptor(setupDescriptor);
702 		return B_NO_MEMORY;
703 	}
704 	statusDescriptor->flags
705 		|= (directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN)
706 		| OHCI_TD_NO_CONDITION_CODE
707 		| OHCI_TD_TOGGLE_1
708 		| OHCI_TD_SET_DELAY_INTERRUPT(1);
709 
710 	iovec vector;
711 	vector.iov_base = requestData;
712 	vector.iov_len = sizeof(usb_request_data);
713 	_WriteDescriptorChain(setupDescriptor, &vector, 1);
714 
715 	status_t  result;
716 	ohci_general_td *dataDescriptor = NULL;
717 	if (transfer->VectorCount() > 0) {
718 		ohci_general_td *lastDescriptor = NULL;
719 		result = _CreateDescriptorChain(&dataDescriptor,
720 			&lastDescriptor,
721 			directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN,
722 			transfer->VectorLength());
723 		if (result < B_OK) {
724 			_FreeGeneralDescriptor(setupDescriptor);
725 			_FreeGeneralDescriptor(statusDescriptor);
726 			return result;
727 		}
728 
729 		if (!directionIn) {
730 			_WriteDescriptorChain(dataDescriptor, transfer->Vector(),
731 				transfer->VectorCount());
732 		}
733 
734 		_LinkDescriptors(setupDescriptor, dataDescriptor);
735 		_LinkDescriptors(lastDescriptor, statusDescriptor);
736 	} else {
737 		_LinkDescriptors(setupDescriptor, statusDescriptor);
738 	}
739 
740 	// 1. Insert the chain descriptors to the endpoint
741 	ohci_endpoint_descriptor *endpoint
742 		= (ohci_endpoint_descriptor *)transfer->TransferPipe()->ControllerCookie();
743 	endpoint->tail_physical_descriptor = statusDescriptor->physical_address;
744 	endpoint->head_physical_descriptor = setupDescriptor->physical_address;
745 	// 2. Clear the Skip bit in the enpoint
746 	endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
747 	// 3. Tell the controller to process the control list
748 	_WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED);
749 
750 	result = _AddPendingTransfer(transfer, endpoint, setupDescriptor,
751 		dataDescriptor,	directionIn);
752 	if (result < B_OK) {
753 		TRACE_ERROR(("usb_ohci: failed to add pending transfer\n"));
754 		_FreeDescriptorChain(setupDescriptor);
755 		return result;
756 	}
757 
758 	return B_OK;
759 }
760 
761 
762 status_t
763 OHCI::_AddPendingTransfer(Transfer *transfer, ohci_endpoint_descriptor *endpoint,
764 	ohci_general_td *firstDescriptor, ohci_general_td *dataDescriptor, bool directionIn)
765 {
766 	if (!transfer || !endpoint || !firstDescriptor)
767 		return B_BAD_VALUE;
768 
769 	transfer_data *data = new(std::nothrow) transfer_data;
770 	if (!data)
771 		return B_NO_MEMORY;
772 
773 	status_t result = transfer->InitKernelAccess();
774 	if (result < B_OK) {
775 		delete data;
776 		return result;
777 	}
778 
779 	data->transfer = transfer;
780 	data->endpoint = endpoint;
781 	data->first_descriptor = firstDescriptor;
782 	data->data_descriptor = dataDescriptor;
783 	data->incoming = directionIn;
784 	data->canceled = false;
785 	data->link = NULL;
786 
787 	if (!Lock()) {
788 		delete data;
789 		return B_ERROR;
790 	}
791 
792 	if (fLastTransfer)
793 		fLastTransfer->link = data;
794 	else
795 		fFirstTransfer = data;
796 
797 	fLastTransfer = data;
798 	Unlock();
799 
800 	return B_OK;
801 }
802 
803 
804 status_t
805 OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
806 {
807 	return B_ERROR;
808 }
809 
810 
811 void
812 OHCI::_LinkDescriptors(ohci_general_td *first, ohci_general_td *second)
813 {
814 	first->next_physical_descriptor = second->physical_address;
815 	first->next_logical_descriptor = second;
816 }
817 
818 
819 status_t
820 OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor,
821 	ohci_general_td **_lastDescriptor, uint8 direction, size_t bufferSize)
822 {
823 	return B_ERROR;
824 }
825 
826 
827 void
828 OHCI::_FreeDescriptorChain(ohci_general_td *topDescriptor)
829 {
830 	ohci_general_td *current = topDescriptor;
831 	ohci_general_td *next = NULL;
832 
833 	while (current) {
834 		next = (ohci_general_td *)current->next_logical_descriptor;
835 		_FreeGeneralDescriptor(current);
836 		current = next;
837 	}
838 
839 }
840 
841 
842 size_t
843 OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
844 	size_t vectorCount)
845 {
846 	ohci_general_td *current = topDescriptor;
847 	size_t actualLength = 0;
848 	size_t vectorIndex = 0;
849 	size_t vectorOffset = 0;
850 	size_t bufferOffset = 0;
851 
852 	while (current) {
853 		if (!current->buffer_logical)
854 			break;
855 
856 		while (true) {
857 			size_t length = min_c(current->buffer_size - bufferOffset,
858 				vector[vectorIndex].iov_len - vectorOffset);
859 
860 			TRACE(("usb_ohci: copying %ld bytes to bufferOffset %ld from"
861 				" vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
862 				vectorOffset, vectorIndex, vectorCount));
863 			memcpy((uint8 *)current->buffer_logical + bufferOffset,
864 				(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
865 
866 			actualLength += length;
867 			vectorOffset += length;
868 			bufferOffset += length;
869 
870 			if (vectorOffset >= vector[vectorIndex].iov_len) {
871 				if (++vectorIndex >= vectorCount) {
872 					TRACE(("usb_ohci: wrote descriptor chain (%ld bytes, no"
873 						" more vectors)\n", actualLength));
874 					return actualLength;
875 				}
876 
877 				vectorOffset = 0;
878 			}
879 
880 			if (bufferOffset >= current->buffer_size) {
881 				bufferOffset = 0;
882 				break;
883 			}
884 		}
885 
886 		if (!current->next_logical_descriptor)
887 			break;
888 
889 		current = (ohci_general_td *)current->next_logical_descriptor;
890 	}
891 
892 	TRACE(("usb_ohci: wrote descriptor chain (%ld bytes)\n", actualLength));
893 	return actualLength;
894 }
895 
896 
897 status_t
898 OHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
899 {
900 	TRACE(("usb_ohci: pipe change %d for pipe 0x%08lx\n", change, (uint32)pipe));
901 	switch (change) {
902 		case USB_CHANGE_CREATED: {
903 			TRACE(("usb_ohci: inserting endpoint\n"));
904 			return _InsertEndpointForPipe(pipe);
905 		}
906 		case USB_CHANGE_DESTROYED: {
907 			TRACE(("usb_ohci: removing endpoint\n"));
908 			return _RemoveEndpointForPipe(pipe);
909 		}
910 		case USB_CHANGE_PIPE_POLICY_CHANGED: {
911 			TRACE(("usb_ohci: pipe policy changing unhandled!\n"));
912 			break;
913 		}
914 		default: {
915 			TRACE_ERROR(("usb_ohci: unknown pipe change!\n"));
916 			return B_ERROR;
917 		}
918 	}
919 	return B_OK;
920 }
921 
922 
923 status_t
924 OHCI::AddTo(Stack *stack)
925 {
926 #ifdef TRACE_USB
927 	set_dprintf_enabled(true);
928 	load_driver_symbols("ohci");
929 #endif
930 
931 	if (!sPCIModule) {
932 		status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
933 		if (status < B_OK) {
934 			TRACE_ERROR(("usb_ohci: getting pci module failed! 0x%08lx\n",
935 				status));
936 			return status;
937 		}
938 	}
939 
940 	TRACE(("usb_ohci: searching devices\n"));
941 	bool found = false;
942 	pci_info *item = new(std::nothrow) pci_info;
943 	if (!item) {
944 		sPCIModule = NULL;
945 		put_module(B_PCI_MODULE_NAME);
946 		return B_NO_MEMORY;
947 	}
948 
949 	for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
950 
951 		if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
952 			&& item->class_api == PCI_usb_ohci) {
953 			if (item->u.h0.interrupt_line == 0
954 				|| item->u.h0.interrupt_line == 0xFF) {
955 				TRACE_ERROR(("usb_ohci: found device with invalid IRQ -"
956 					" check IRQ assignement\n"));
957 				continue;
958 			}
959 
960 			TRACE(("usb_ohci: found device at IRQ %u\n",
961 				item->u.h0.interrupt_line));
962 			OHCI *bus = new(std::nothrow) OHCI(item, stack);
963 			if (!bus) {
964 				delete item;
965 				sPCIModule = NULL;
966 				put_module(B_PCI_MODULE_NAME);
967 				return B_NO_MEMORY;
968 			}
969 
970 			if (bus->InitCheck() < B_OK) {
971 				TRACE_ERROR(("usb_ohci: bus failed init check\n"));
972 				delete bus;
973 				continue;
974 			}
975 
976 			// the bus took it away
977 			item = new(std::nothrow) pci_info;
978 
979 			bus->Start();
980 			stack->AddBusManager(bus);
981 			found = true;
982 		}
983 	}
984 
985 	if (!found) {
986 		TRACE_ERROR(("usb_ohci: no devices found\n"));
987 		delete item;
988 		sPCIModule = NULL;
989 		put_module(B_PCI_MODULE_NAME);
990 		return ENODEV;
991 	}
992 
993 	delete item;
994 	return B_OK;
995 }
996 
997 
998 status_t
999 OHCI::GetPortStatus(uint8 index, usb_port_status *status)
1000 {
1001 	TRACE(("usb_ohci::%s(%ud, )\n", __FUNCTION__, index));
1002 	if (index >= fPortCount)
1003 		return B_BAD_INDEX;
1004 
1005 	status->status = status->change = 0;
1006 	uint32 portStatus = _ReadReg(OHCI_RH_PORT_STATUS(index));
1007 
1008 	TRACE(("usb_ohci: RootHub::GetPortStatus: Port %i Value 0x%lx\n", OHCI_RH_PORT_STATUS(index), portStatus));
1009 
1010 	// status
1011 	if (portStatus & OHCI_RH_PORTSTATUS_CCS)
1012 		status->status |= PORT_STATUS_CONNECTION;
1013 	if (portStatus & OHCI_RH_PORTSTATUS_PES)
1014 		status->status |= PORT_STATUS_ENABLE;
1015 	if (portStatus & OHCI_RH_PORTSTATUS_PRS)
1016 		status->status |= PORT_STATUS_RESET;
1017 	if (portStatus & OHCI_RH_PORTSTATUS_LSDA)
1018 		status->status |= PORT_STATUS_LOW_SPEED;
1019 	if (portStatus & OHCI_RH_PORTSTATUS_PSS)
1020 		status->status |= PORT_STATUS_SUSPEND;
1021 	if (portStatus & OHCI_RH_PORTSTATUS_POCI)
1022 		status->status |= PORT_STATUS_OVER_CURRENT;
1023 	if (portStatus & OHCI_RH_PORTSTATUS_PPS)
1024 		status->status |= PORT_STATUS_POWER;
1025 
1026 
1027 	// change
1028 	if (portStatus & OHCI_RH_PORTSTATUS_CSC)
1029 		status->change |= PORT_STATUS_CONNECTION;
1030 	if (portStatus & OHCI_RH_PORTSTATUS_PESC)
1031 		status->change |= PORT_STATUS_ENABLE;
1032 	if (portStatus & OHCI_RH_PORTSTATUS_PSSC)
1033 		status->change |= PORT_STATUS_SUSPEND;
1034 	if (portStatus & OHCI_RH_PORTSTATUS_OCIC)
1035 		status->change |= PORT_STATUS_OVER_CURRENT;
1036 	if (portStatus & OHCI_RH_PORTSTATUS_PRSC)
1037 		status->change |= PORT_STATUS_RESET;
1038 
1039 	return B_OK;
1040 }
1041 
1042 
1043 status_t
1044 OHCI::SetPortFeature(uint8 index, uint16 feature)
1045 {
1046 	TRACE(("OHCI::%s(%ud, %ud)\n", __FUNCTION__, index, feature));
1047 	if (index > fPortCount)
1048 		return B_BAD_INDEX;
1049 
1050 	switch (feature) {
1051 		case PORT_RESET:
1052 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRS);
1053 			return B_OK;
1054 
1055 		case PORT_POWER:
1056 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PPS);
1057 			return B_OK;
1058 	}
1059 
1060 	return B_BAD_VALUE;
1061 }
1062 
1063 
1064 status_t
1065 OHCI::ClearPortFeature(uint8 index, uint16 feature)
1066 {
1067 	TRACE(("OHCI::%s(%ud, %ud)\n", __FUNCTION__, index, feature));
1068 	if (index > fPortCount)
1069 		return B_BAD_INDEX;
1070 
1071 	switch (feature) {
1072 		case C_PORT_RESET:
1073 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CSC);
1074 			return B_OK;
1075 
1076 		case C_PORT_CONNECTION:
1077 			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CSC);
1078 			return B_OK;
1079 	}
1080 
1081 	return B_BAD_VALUE;
1082 }
1083 
1084 
1085 ohci_endpoint_descriptor*
1086 OHCI::_AllocateEndpoint()
1087 {
1088 	ohci_endpoint_descriptor *endpoint;
1089 	void* physicalAddress;
1090 
1091 	// Allocate memory chunk
1092 	if (fStack->AllocateChunk((void **)&endpoint, &physicalAddress,
1093 		sizeof(ohci_endpoint_descriptor)) < B_OK) {
1094 		TRACE_ERROR(("usb_ohci: failed to allocate endpoint descriptor\n"));
1095 		return NULL;
1096 	}
1097 	memset((void *)endpoint, 0, sizeof(ohci_endpoint_descriptor));
1098 
1099 	endpoint->physical_address = (addr_t)physicalAddress;
1100 
1101 	endpoint->head_physical_descriptor = NULL;
1102 	endpoint->tail_physical_descriptor = NULL;
1103 
1104 	endpoint->head_logical_descriptor = NULL;
1105 	endpoint->tail_logical_descriptor = NULL;
1106 
1107 	return endpoint;
1108 }
1109 
1110 
1111 void
1112 OHCI::_FreeEndpoint(ohci_endpoint_descriptor *endpoint)
1113 {
1114 	if (!endpoint)
1115 		return;
1116 
1117 	fStack->FreeChunk((void *)endpoint, (void *)endpoint->physical_address,
1118 		sizeof(ohci_endpoint_descriptor));
1119 }
1120 
1121 
1122 ohci_general_td*
1123 OHCI::_CreateGeneralDescriptor(size_t bufferSize)
1124 {
1125 	ohci_general_td *descriptor;
1126 	void *physicalAddress;
1127 
1128 	if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
1129 		sizeof(ohci_general_td)) != B_OK) {
1130 		TRACE_ERROR(("usb_ohci: failed to allocate general descriptor\n"));
1131 		return NULL;
1132 	}
1133 	memset((void *)descriptor, 0, sizeof(ohci_general_td));
1134 	descriptor->physical_address = (addr_t)physicalAddress;
1135 
1136 	if (!bufferSize) {
1137 		descriptor->buffer_physical = 0;
1138 		descriptor->buffer_logical = NULL;
1139 		descriptor->last_physical_byte_address = 0;
1140 		return descriptor;
1141 	}
1142 
1143 	if (fStack->AllocateChunk(&descriptor->buffer_logical,
1144 		(void **)&descriptor->buffer_physical, bufferSize) != B_OK) {
1145 		TRACE_ERROR(("usb_ohci: failed to allocate space for buffer\n"));
1146 		fStack->FreeChunk(descriptor, (void *)descriptor->physical_address,
1147 			sizeof(ohci_general_td));
1148 		return NULL;
1149 	}
1150 	descriptor->last_physical_byte_address
1151 		= descriptor->buffer_physical + bufferSize - 1;
1152 
1153 	return descriptor;
1154 }
1155 
1156 
1157 void
1158 OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor)
1159 {
1160 	if (!descriptor)
1161 		return;
1162 
1163 	if (descriptor->buffer_logical) {
1164 		fStack->FreeChunk(descriptor->buffer_logical,
1165 			(void *)descriptor->buffer_physical, descriptor->buffer_size);
1166 	}
1167 
1168 	fStack->FreeChunk((void *)descriptor, (void *)descriptor->physical_address,
1169 		sizeof(ohci_general_td));
1170 }
1171 
1172 
1173 ohci_isochronous_td*
1174 _CreateIsochronousDescriptor()
1175 {
1176 	// TODO
1177 	return NULL;
1178 }
1179 
1180 
1181 void _FreeIsochronousDescriptor(ohci_isochronous_td *descriptor)
1182 {
1183 	// TODO
1184 }
1185 
1186 
1187 status_t
1188 OHCI::_InsertEndpointForPipe(Pipe *pipe)
1189 {
1190 	TRACE(("OHCI: Inserting Endpoint for device %u function %u\n",
1191 		pipe->DeviceAddress(), pipe->EndpointAddress()));
1192 
1193 	ohci_endpoint_descriptor *endpoint = _AllocateEndpoint();
1194 	if (!endpoint) {
1195 		TRACE_ERROR(("usb_ohci: cannot allocate memory for endpoint\n"));
1196 		return B_NO_MEMORY;
1197 	}
1198 
1199 	uint32 flags = 0;
1200 	flags |= OHCI_ENDPOINT_SKIP;
1201 
1202 	// Set up flag field for the endpoint
1203 	flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(pipe->DeviceAddress())
1204 		| OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(pipe->EndpointAddress());
1205 
1206 	// Set the direction
1207 	switch (pipe->Direction()) {
1208 		case Pipe::In:
1209 			flags |= OHCI_ENDPOINT_DIRECTION_IN;
1210 			break;
1211 		case Pipe::Out:
1212 			flags |= OHCI_ENDPOINT_DIRECTION_OUT;
1213 			break;
1214 		case Pipe::Default:
1215 			flags |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR;
1216 			break;
1217 		default:
1218 			TRACE_ERROR(("usb_ohci: direction unknown. Wrong value!\n"));
1219 			_FreeEndpoint(endpoint);
1220 			return B_ERROR;
1221 	}
1222 
1223 	// Set up the speed
1224 	switch (pipe->Speed()) {
1225 		case USB_SPEED_LOWSPEED:
1226 			flags |= OHCI_ENDPOINT_LOW_SPEED;
1227 			break;
1228 		case USB_SPEED_FULLSPEED:
1229 			flags |= OHCI_ENDPOINT_FULL_SPEED;
1230 			break;
1231 		case USB_SPEED_HIGHSPEED:
1232 		default:
1233 			TRACE_ERROR(("usb_ohci: unaccetable speed. Wrong value!\n"));
1234 			_FreeEndpoint(endpoint);
1235 			return B_ERROR;
1236 	}
1237 
1238 	// Set the maximum packet size
1239 	flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(pipe->MaxPacketSize());
1240 
1241 	endpoint->flags = flags;
1242 
1243 	// Add the endpoint to the appropriate list
1244 	ohci_endpoint_descriptor *head = NULL;
1245 	switch (pipe->Type()) {
1246 		case USB_OBJECT_CONTROL_PIPE:
1247 			head = fDummyControl;
1248 			break;
1249 		case USB_OBJECT_BULK_PIPE:
1250 			head = fDummyBulk;
1251 			break;
1252 		case USB_OBJECT_ISO_PIPE:
1253 			// Set the isochronous bit format
1254 			endpoint->flags = OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
1255 			head = fDummyIsochronous;
1256 			break;
1257 		case USB_OBJECT_INTERRUPT_PIPE:
1258 			head = _FindInterruptEndpoint(pipe->Interval());
1259 			break;
1260 		default:
1261 			TRACE_ERROR(("usb_ohci: unknown type of pipe. Wrong value!\n"));
1262 			_FreeEndpoint(endpoint);
1263 			return B_ERROR;
1264 	}
1265 
1266 	Lock();
1267 	pipe->SetControllerCookie((void *)endpoint);
1268 	endpoint->next_logical_endpoint = head->next_logical_endpoint;
1269 	endpoint->next_physical_endpoint = head->next_physical_endpoint;
1270 	head->next_logical_endpoint = (void *)endpoint;
1271 	head->next_physical_endpoint = (uint32)endpoint->physical_address;
1272 	Unlock();
1273 
1274 	return B_OK;
1275 }
1276 
1277 
1278 ohci_endpoint_descriptor*
1279 OHCI::_FindInterruptEndpoint(uint8 interval)
1280 {
1281 	return NULL;
1282 }
1283 
1284 
1285 status_t
1286 OHCI::_RemoveEndpointForPipe(Pipe *pipe)
1287 {
1288 	return B_ERROR;
1289 }
1290 
1291 
1292 inline void
1293 OHCI::_WriteReg(uint32 reg, uint32 value)
1294 {
1295 	*(volatile uint32 *)(fOperationalRegisters + reg) = value;
1296 }
1297 
1298 
1299 inline uint32
1300 OHCI::_ReadReg(uint32 reg)
1301 {
1302 	return *(volatile uint32 *)(fOperationalRegisters + reg);
1303 }
1304 
1305 
1306 status_t
1307 OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
1308 {
1309 	return B_ERROR;
1310 }
1311