1/*
2 * Copyright 2005-2013, 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 *		Siarzhuk Zharski <imker@gmx.li>
10 */
11
12#include <module.h>
13#include <PCI.h>
14#include <PCI_x86.h>
15#include <USB3.h>
16#include <KernelExport.h>
17#include <util/AutoLock.h>
18
19#include "ohci.h"
20
21#define USB_MODULE_NAME "ohci"
22
23pci_module_info *OHCI::sPCIModule = NULL;
24pci_x86_module_info *OHCI::sPCIx86Module = NULL;
25
26
27static int32
28ohci_std_ops(int32 op, ...)
29{
30	switch (op)	{
31		case B_MODULE_INIT:
32			TRACE_MODULE("init module\n");
33			return B_OK;
34		case B_MODULE_UNINIT:
35			TRACE_MODULE("uninit module\n");
36			return B_OK;
37	}
38
39	return EINVAL;
40}
41
42
43usb_host_controller_info ohci_module = {
44	{
45		"busses/usb/ohci",
46		0,
47		ohci_std_ops
48	},
49	NULL,
50	OHCI::AddTo
51};
52
53
54module_info *modules[] = {
55	(module_info *)&ohci_module,
56	NULL
57};
58
59
60//
61// #pragma mark -
62//
63
64
65status_t
66OHCI::AddTo(Stack *stack)
67{
68	if (!sPCIModule) {
69		status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
70		if (status < B_OK) {
71			TRACE_MODULE_ERROR("getting pci module failed! 0x%08" B_PRIx32 "\n",
72				status);
73			return status;
74		}
75	}
76
77	TRACE_MODULE("searching devices\n");
78	bool found = false;
79	pci_info *item = new(std::nothrow) pci_info;
80	if (!item) {
81		sPCIModule = NULL;
82		put_module(B_PCI_MODULE_NAME);
83		return B_NO_MEMORY;
84	}
85
86	// Try to get the PCI x86 module as well so we can enable possible MSIs.
87	if (sPCIx86Module == NULL && get_module(B_PCI_X86_MODULE_NAME,
88			(module_info **)&sPCIx86Module) != B_OK) {
89		// If it isn't there, that's not critical though.
90		TRACE_MODULE_ERROR("failed to get pci x86 module\n");
91		sPCIx86Module = NULL;
92	}
93
94	for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
95		if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
96			&& item->class_api == PCI_usb_ohci) {
97			TRACE_MODULE("found device at PCI:%d:%d:%d\n",
98				item->bus, item->device, item->function);
99			OHCI *bus = new(std::nothrow) OHCI(item, stack);
100			if (bus == NULL) {
101				delete item;
102				put_module(B_PCI_MODULE_NAME);
103				if (sPCIx86Module != NULL)
104					put_module(B_PCI_X86_MODULE_NAME);
105				return B_NO_MEMORY;
106			}
107
108			// The bus will put the PCI modules when it is destroyed, so get
109			// them again to increase their reference count.
110			get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
111			if (sPCIx86Module != NULL)
112				get_module(B_PCI_X86_MODULE_NAME, (module_info **)&sPCIx86Module);
113
114			if (bus->InitCheck() < B_OK) {
115				TRACE_MODULE_ERROR("bus failed init check\n");
116				delete bus;
117				continue;
118			}
119
120			// the bus took it away
121			item = new(std::nothrow) pci_info;
122
123			if (bus->Start() != B_OK) {
124				delete bus;
125				continue;
126			}
127			found = true;
128		}
129	}
130
131	// The modules will have been gotten again if we successfully
132	// initialized a bus, so we should put them here.
133	put_module(B_PCI_MODULE_NAME);
134	if (sPCIx86Module != NULL)
135		put_module(B_PCI_X86_MODULE_NAME);
136
137	if (!found)
138		TRACE_MODULE_ERROR("no devices found\n");
139	delete item;
140	return found ? B_OK : ENODEV;
141}
142
143
144OHCI::OHCI(pci_info *info, Stack *stack)
145	:	BusManager(stack),
146		fPCIInfo(info),
147		fStack(stack),
148		fOperationalRegisters(NULL),
149		fRegisterArea(-1),
150		fHccaArea(-1),
151		fHcca(NULL),
152		fInterruptEndpoints(NULL),
153		fDummyControl(NULL),
154		fDummyBulk(NULL),
155		fDummyIsochronous(NULL),
156		fFirstTransfer(NULL),
157		fLastTransfer(NULL),
158		fFinishTransfersSem(-1),
159		fFinishThread(-1),
160		fStopFinishThread(false),
161		fProcessingPipe(NULL),
162		fFrameBandwidth(NULL),
163		fRootHub(NULL),
164		fRootHubAddress(0),
165		fPortCount(0),
166		fIRQ(0),
167		fUseMSI(false)
168{
169	if (!fInitOK) {
170		TRACE_ERROR("bus manager failed to init\n");
171		return;
172	}
173
174	TRACE("constructing new OHCI host controller driver\n");
175	fInitOK = false;
176
177	mutex_init(&fEndpointLock, "ohci endpoint lock");
178
179	// enable busmaster and memory mapped access
180	uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
181		fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
182	command &= ~PCI_command_io;
183	command |= PCI_command_master | PCI_command_memory;
184
185	sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
186		fPCIInfo->function, PCI_command, 2, command);
187
188	// map the registers
189	uint32 offset = sPCIModule->read_pci_config(fPCIInfo->bus,
190		fPCIInfo->device, fPCIInfo->function, PCI_base_registers, 4);
191	offset &= PCI_address_memory_32_mask;
192	TRACE_ALWAYS("iospace offset: 0x%" B_PRIx32 "\n", offset);
193	fRegisterArea = map_physical_memory("OHCI memory mapped registers",
194		offset,	B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS,
195		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
196		(void **)&fOperationalRegisters);
197	if (fRegisterArea < B_OK) {
198		TRACE_ERROR("failed to map register memory\n");
199		return;
200	}
201
202	TRACE("mapped operational registers: %p\n", fOperationalRegisters);
203
204	// Check the revision of the controller, which should be 10h
205	uint32 revision = _ReadReg(OHCI_REVISION) & 0xff;
206	TRACE("version %" B_PRId32 ".%" B_PRId32 "%s\n",
207		OHCI_REVISION_HIGH(revision), OHCI_REVISION_LOW(revision),
208		OHCI_REVISION_LEGACY(revision) ? ", legacy support" : "");
209
210	if (OHCI_REVISION_HIGH(revision) != 1 || OHCI_REVISION_LOW(revision) != 0) {
211		TRACE_ERROR("unsupported OHCI revision\n");
212		return;
213	}
214
215	phys_addr_t hccaPhysicalAddress;
216	fHccaArea = fStack->AllocateArea((void **)&fHcca, &hccaPhysicalAddress,
217		sizeof(ohci_hcca), "USB OHCI Host Controller Communication Area");
218
219	if (fHccaArea < B_OK) {
220		TRACE_ERROR("unable to create the HCCA block area\n");
221		return;
222	}
223
224	memset(fHcca, 0, sizeof(ohci_hcca));
225
226	// Set Up Host controller
227	// Dummy endpoints
228	fDummyControl = _AllocateEndpoint();
229	if (!fDummyControl)
230		return;
231
232	fDummyBulk = _AllocateEndpoint();
233	if (!fDummyBulk) {
234		_FreeEndpoint(fDummyControl);
235		return;
236	}
237
238	fDummyIsochronous = _AllocateEndpoint();
239	if (!fDummyIsochronous) {
240		_FreeEndpoint(fDummyControl);
241		_FreeEndpoint(fDummyBulk);
242		return;
243	}
244
245	// Static endpoints that get linked in the HCCA
246	fInterruptEndpoints = new(std::nothrow)
247		ohci_endpoint_descriptor *[OHCI_STATIC_ENDPOINT_COUNT];
248	if (!fInterruptEndpoints) {
249		TRACE_ERROR("failed to allocate memory for interrupt endpoints\n");
250		_FreeEndpoint(fDummyControl);
251		_FreeEndpoint(fDummyBulk);
252		_FreeEndpoint(fDummyIsochronous);
253		return;
254	}
255
256	for (int32 i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
257		fInterruptEndpoints[i] = _AllocateEndpoint();
258		if (!fInterruptEndpoints[i]) {
259			TRACE_ERROR("failed to allocate interrupt endpoint %" B_PRId32 "\n",
260				i);
261			while (--i >= 0)
262				_FreeEndpoint(fInterruptEndpoints[i]);
263			_FreeEndpoint(fDummyBulk);
264			_FreeEndpoint(fDummyControl);
265			_FreeEndpoint(fDummyIsochronous);
266			return;
267		}
268	}
269
270	// build flat tree so that at each of the static interrupt endpoints
271	// fInterruptEndpoints[i] == interrupt endpoint for interval 2^i
272	uint32 interval = OHCI_BIGGEST_INTERVAL;
273	uint32 intervalIndex = OHCI_STATIC_ENDPOINT_COUNT - 1;
274	while (interval > 1) {
275		uint32 insertIndex = interval / 2;
276		while (insertIndex < OHCI_BIGGEST_INTERVAL) {
277			fHcca->interrupt_table[insertIndex]
278				= fInterruptEndpoints[intervalIndex]->physical_address;
279			insertIndex += interval;
280		}
281
282		intervalIndex--;
283		interval /= 2;
284	}
285
286	// setup the empty slot in the list and linking of all -> first
287	fHcca->interrupt_table[0] = fInterruptEndpoints[0]->physical_address;
288	for (int32 i = 1; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
289		fInterruptEndpoints[i]->next_physical_endpoint
290			= fInterruptEndpoints[0]->physical_address;
291		fInterruptEndpoints[i]->next_logical_endpoint
292			= fInterruptEndpoints[0];
293	}
294
295	// Now link the first endpoint to the isochronous endpoint
296	fInterruptEndpoints[0]->next_physical_endpoint
297		= fDummyIsochronous->physical_address;
298
299	// When the handover from SMM takes place, all interrupts are routed to the
300	// OS. As we don't yet have an interrupt handler installed at this point,
301	// this may cause interrupt storms if the firmware does not disable the
302	// interrupts during handover. Therefore we disable interrupts before
303	// requesting ownership. We have to keep the ownership change interrupt
304	// enabled though, as otherwise the SMM will not be notified of the
305	// ownership change request we trigger below.
306	_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS &
307		~OHCI_OWNERSHIP_CHANGE) ;
308
309	// Determine in what context we are running (Kindly copied from FreeBSD)
310	uint32 control = _ReadReg(OHCI_CONTROL);
311	if (control & OHCI_INTERRUPT_ROUTING) {
312		TRACE_ALWAYS("smm is in control of the host controller\n");
313		uint32 status = _ReadReg(OHCI_COMMAND_STATUS);
314		_WriteReg(OHCI_COMMAND_STATUS, status | OHCI_OWNERSHIP_CHANGE_REQUEST);
315		for (uint32 i = 0; i < 100 && (control & OHCI_INTERRUPT_ROUTING); i++) {
316			snooze(1000);
317			control = _ReadReg(OHCI_CONTROL);
318		}
319
320		if ((control & OHCI_INTERRUPT_ROUTING) != 0) {
321			TRACE_ERROR("smm does not respond.\n");
322
323			// TODO: Enable this reset as soon as the non-specified
324			// reset a few lines later is replaced by a better solution.
325			//_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
326			//snooze(USB_DELAY_BUS_RESET);
327		} else
328			TRACE_ALWAYS("ownership change successful\n");
329	} else {
330		TRACE("cold started\n");
331		snooze(USB_DELAY_BUS_RESET);
332	}
333
334	// TODO: This reset delays system boot time. It should not be necessary
335	// according to the OHCI spec, but without it some controllers don't start.
336	_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
337	snooze(USB_DELAY_BUS_RESET);
338
339	// We now own the host controller and the bus has been reset
340	uint32 frameInterval = _ReadReg(OHCI_FRAME_INTERVAL);
341	uint32 intervalValue = OHCI_GET_INTERVAL_VALUE(frameInterval);
342
343	_WriteReg(OHCI_COMMAND_STATUS, OHCI_HOST_CONTROLLER_RESET);
344	// Nominal time for a reset is 10 us
345	uint32 reset = 0;
346	for (uint32 i = 0; i < 10; i++) {
347		spin(10);
348		reset = _ReadReg(OHCI_COMMAND_STATUS) & OHCI_HOST_CONTROLLER_RESET;
349		if (reset == 0)
350			break;
351	}
352
353	if (reset) {
354		TRACE_ERROR("error resetting the host controller (timeout)\n");
355		return;
356	}
357
358	// The controller is now in SUSPEND state, we have 2ms to go OPERATIONAL.
359
360	// Set up host controller register
361	_WriteReg(OHCI_HCCA, (uint32)hccaPhysicalAddress);
362	_WriteReg(OHCI_CONTROL_HEAD_ED, (uint32)fDummyControl->physical_address);
363	_WriteReg(OHCI_BULK_HEAD_ED, (uint32)fDummyBulk->physical_address);
364	// Switch on desired functional features
365	control = _ReadReg(OHCI_CONTROL);
366	control &= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK | OHCI_ENABLE_LIST
367		| OHCI_HC_FUNCTIONAL_STATE_MASK | OHCI_INTERRUPT_ROUTING);
368	control |= OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4
369		| OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL;
370	// And finally start the controller
371	_WriteReg(OHCI_CONTROL, control);
372
373	// The controller is now OPERATIONAL.
374	frameInterval = (_ReadReg(OHCI_FRAME_INTERVAL) & OHCI_FRAME_INTERVAL_TOGGLE)
375		^ OHCI_FRAME_INTERVAL_TOGGLE;
376	frameInterval |= OHCI_FSMPS(intervalValue) | intervalValue;
377	_WriteReg(OHCI_FRAME_INTERVAL, frameInterval);
378	// 90% periodic
379	uint32 periodic = OHCI_PERIODIC(intervalValue);
380	_WriteReg(OHCI_PERIODIC_START, periodic);
381
382	// Fiddle the No Over Current Protection bit to avoid chip bug
383	uint32 desca = _ReadReg(OHCI_RH_DESCRIPTOR_A);
384	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca | OHCI_RH_NO_OVER_CURRENT_PROTECTION);
385	_WriteReg(OHCI_RH_STATUS, OHCI_RH_LOCAL_POWER_STATUS_CHANGE);
386	snooze(OHCI_ENABLE_POWER_DELAY);
387	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca);
388
389	// The AMD756 requires a delay before re-reading the register,
390	// otherwise it will occasionally report 0 ports.
391	uint32 numberOfPorts = 0;
392	for (uint32 i = 0; i < 10 && numberOfPorts == 0; i++) {
393		snooze(OHCI_READ_DESC_DELAY);
394		uint32 descriptor = _ReadReg(OHCI_RH_DESCRIPTOR_A);
395		numberOfPorts = OHCI_RH_GET_PORT_COUNT(descriptor);
396	}
397	if (numberOfPorts > OHCI_MAX_PORT_COUNT)
398		numberOfPorts = OHCI_MAX_PORT_COUNT;
399	fPortCount = numberOfPorts;
400	TRACE("port count is %d\n", fPortCount);
401
402	// Create the array that will keep bandwidth information
403	fFrameBandwidth = new(std::nothrow) uint16[NUMBER_OF_FRAMES];
404
405	for (int32 i = 0; i < NUMBER_OF_FRAMES; i++)
406		fFrameBandwidth[i] = MAX_AVAILABLE_BANDWIDTH;
407
408	// Create semaphore the finisher thread will wait for
409	fFinishTransfersSem = create_sem(0, "OHCI Finish Transfers");
410	if (fFinishTransfersSem < B_OK) {
411		TRACE_ERROR("failed to create semaphore\n");
412		return;
413	}
414
415	// Create the finisher service thread
416	fFinishThread = spawn_kernel_thread(_FinishThread, "ohci finish thread",
417		B_URGENT_DISPLAY_PRIORITY, (void *)this);
418	resume_thread(fFinishThread);
419
420	// Find the right interrupt vector, using MSIs if available.
421	fIRQ = fPCIInfo->u.h0.interrupt_line;
422	if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus,
423			fPCIInfo->device, fPCIInfo->function) >= 1) {
424		uint8 msiVector = 0;
425		if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device,
426				fPCIInfo->function, 1, &msiVector) == B_OK
427			&& sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device,
428				fPCIInfo->function) == B_OK) {
429			TRACE_ALWAYS("using message signaled interrupts\n");
430			fIRQ = msiVector;
431			fUseMSI = true;
432		}
433	}
434
435	if (fIRQ == 0 || fIRQ == 0xFF) {
436		TRACE_MODULE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n",
437			fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function);
438		return;
439	}
440
441	// Install the interrupt handler
442	TRACE("installing interrupt handler\n");
443	install_io_interrupt_handler(fIRQ, _InterruptHandler, (void *)this, 0);
444
445	// Enable interesting interrupts now that the handler is in place
446	_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS
447		| OHCI_MASTER_INTERRUPT_ENABLE);
448
449	TRACE("OHCI host controller driver constructed\n");
450	fInitOK = true;
451}
452
453
454OHCI::~OHCI()
455{
456	int32 result = 0;
457	fStopFinishThread = true;
458	delete_sem(fFinishTransfersSem);
459	wait_for_thread(fFinishThread, &result);
460
461	remove_io_interrupt_handler(fIRQ, _InterruptHandler, (void *)this);
462
463	_LockEndpoints();
464	mutex_destroy(&fEndpointLock);
465
466	if (fHccaArea >= B_OK)
467		delete_area(fHccaArea);
468	if (fRegisterArea >= B_OK)
469		delete_area(fRegisterArea);
470
471	_FreeEndpoint(fDummyControl);
472	_FreeEndpoint(fDummyBulk);
473	_FreeEndpoint(fDummyIsochronous);
474
475	if (fInterruptEndpoints != NULL) {
476		for (int i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++)
477			_FreeEndpoint(fInterruptEndpoints[i]);
478	}
479
480	delete [] fFrameBandwidth;
481	delete [] fInterruptEndpoints;
482	delete fRootHub;
483
484	if (fUseMSI && sPCIx86Module != NULL) {
485		sPCIx86Module->disable_msi(fPCIInfo->bus,
486			fPCIInfo->device, fPCIInfo->function);
487		sPCIx86Module->unconfigure_msi(fPCIInfo->bus,
488			fPCIInfo->device, fPCIInfo->function);
489	}
490
491	put_module(B_PCI_MODULE_NAME);
492	if (sPCIx86Module != NULL)
493		put_module(B_PCI_X86_MODULE_NAME);
494}
495
496
497status_t
498OHCI::Start()
499{
500	TRACE("starting OHCI host controller\n");
501
502	uint32 control = _ReadReg(OHCI_CONTROL);
503	if ((control & OHCI_HC_FUNCTIONAL_STATE_MASK)
504		!= OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL) {
505		TRACE_ERROR("controller not started (0x%08" B_PRIx32 ")!\n", control);
506		return B_ERROR;
507	} else
508		TRACE("controller is operational!\n");
509
510	fRootHubAddress = AllocateAddress();
511	fRootHub = new(std::nothrow) OHCIRootHub(RootObject(), fRootHubAddress);
512	if (!fRootHub) {
513		TRACE_ERROR("no memory to allocate root hub\n");
514		return B_NO_MEMORY;
515	}
516
517	if (fRootHub->InitCheck() < B_OK) {
518		TRACE_ERROR("root hub failed init check\n");
519		return B_ERROR;
520	}
521
522	SetRootHub(fRootHub);
523	TRACE_ALWAYS("successfully started the controller\n");
524	return BusManager::Start();
525}
526
527
528status_t
529OHCI::SubmitTransfer(Transfer *transfer)
530{
531	// short circuit the root hub
532	if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
533		return fRootHub->ProcessTransfer(this, transfer);
534
535	uint32 type = transfer->TransferPipe()->Type();
536	if (type & USB_OBJECT_CONTROL_PIPE) {
537		TRACE("submitting request\n");
538		return _SubmitRequest(transfer);
539	}
540
541	if ((type & USB_OBJECT_BULK_PIPE) || (type & USB_OBJECT_INTERRUPT_PIPE)) {
542		TRACE("submitting %s transfer\n",
543			(type & USB_OBJECT_BULK_PIPE) ? "bulk" : "interrupt");
544		return _SubmitTransfer(transfer);
545	}
546
547	if (type & USB_OBJECT_ISO_PIPE) {
548		TRACE("submitting isochronous transfer\n");
549		return _SubmitIsochronousTransfer(transfer);
550	}
551
552	TRACE_ERROR("tried to submit transfer for unknown pipe type %" B_PRIu32 "\n",
553		type);
554	return B_ERROR;
555}
556
557
558status_t
559OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
560{
561	if (!Lock())
562		return B_ERROR;
563
564	struct transfer_entry {
565		Transfer *			transfer;
566		transfer_entry *	next;
567	};
568
569	transfer_entry *list = NULL;
570	transfer_data *current = fFirstTransfer;
571	while (current) {
572		if (current->transfer && current->transfer->TransferPipe() == pipe) {
573			// Check if the skip bit is already set
574			if (!(current->endpoint->flags & OHCI_ENDPOINT_SKIP)) {
575				current->endpoint->flags |= OHCI_ENDPOINT_SKIP;
576				// In case the controller is processing
577				// this endpoint, wait for it to finish
578				snooze(1000);
579			}
580
581			// Clear the endpoint
582			current->endpoint->head_physical_descriptor
583				= current->endpoint->tail_physical_descriptor;
584
585			if (!force) {
586				if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
587					ohci_isochronous_td *descriptor
588						= (ohci_isochronous_td *)current->first_descriptor;
589					while (descriptor) {
590						uint16 frame = OHCI_ITD_GET_STARTING_FRAME(
591							descriptor->flags);
592						_ReleaseIsochronousBandwidth(frame,
593							OHCI_ITD_GET_FRAME_COUNT(descriptor->flags));
594						if (descriptor
595								== (ohci_isochronous_td*)current->last_descriptor)
596							// this is the last ITD of the transfer
597							break;
598
599						descriptor
600							= (ohci_isochronous_td *)
601							descriptor->next_done_descriptor;
602					}
603				}
604
605				// If the transfer is canceled by force, the one causing the
606				// cancel is probably not the one who initiated the transfer
607				// and the callback is likely not safe anymore
608				transfer_entry *entry
609					= (transfer_entry *)malloc(sizeof(transfer_entry));
610				if (entry != NULL) {
611					entry->transfer = current->transfer;
612					current->transfer = NULL;
613					entry->next = list;
614					list = entry;
615				}
616			}
617			current->canceled = true;
618		}
619		current = current->link;
620	}
621
622	Unlock();
623
624	while (list != NULL) {
625		transfer_entry *next = list->next;
626		list->transfer->Finished(B_CANCELED, 0);
627		delete list->transfer;
628		free(list);
629		list = next;
630	}
631
632	// wait for any transfers that might have made it before canceling
633	while (fProcessingPipe == pipe)
634		snooze(1000);
635
636	// notify the finisher so it can clean up the canceled transfers
637	release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
638	return B_OK;
639}
640
641
642status_t
643OHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
644{
645	TRACE("pipe change %d for pipe %p\n", change, pipe);
646	if (pipe->DeviceAddress() == fRootHubAddress) {
647		// no need to insert/remove endpoint descriptors for the root hub
648		return B_OK;
649	}
650
651	switch (change) {
652		case USB_CHANGE_CREATED:
653			return _InsertEndpointForPipe(pipe);
654
655		case USB_CHANGE_DESTROYED:
656			return _RemoveEndpointForPipe(pipe);
657
658		case USB_CHANGE_PIPE_POLICY_CHANGED:
659			TRACE("pipe policy changing unhandled!\n");
660			break;
661
662		default:
663			TRACE_ERROR("unknown pipe change!\n");
664			return B_ERROR;
665	}
666
667	return B_OK;
668}
669
670
671status_t
672OHCI::GetPortStatus(uint8 index, usb_port_status *status)
673{
674	if (index >= fPortCount) {
675		TRACE_ERROR("get port status for invalid port %u\n", index);
676		return B_BAD_INDEX;
677	}
678
679	status->status = status->change = 0;
680	uint32 portStatus = _ReadReg(OHCI_RH_PORT_STATUS(index));
681
682	// status
683	if (portStatus & OHCI_RH_PORTSTATUS_CCS)
684		status->status |= PORT_STATUS_CONNECTION;
685	if (portStatus & OHCI_RH_PORTSTATUS_PES)
686		status->status |= PORT_STATUS_ENABLE;
687	if (portStatus & OHCI_RH_PORTSTATUS_PSS)
688		status->status |= PORT_STATUS_SUSPEND;
689	if (portStatus & OHCI_RH_PORTSTATUS_POCI)
690		status->status |= PORT_STATUS_OVER_CURRENT;
691	if (portStatus & OHCI_RH_PORTSTATUS_PRS)
692		status->status |= PORT_STATUS_RESET;
693	if (portStatus & OHCI_RH_PORTSTATUS_PPS)
694		status->status |= PORT_STATUS_POWER;
695	if (portStatus & OHCI_RH_PORTSTATUS_LSDA)
696		status->status |= PORT_STATUS_LOW_SPEED;
697
698	// change
699	if (portStatus & OHCI_RH_PORTSTATUS_CSC)
700		status->change |= PORT_STATUS_CONNECTION;
701	if (portStatus & OHCI_RH_PORTSTATUS_PESC)
702		status->change |= PORT_STATUS_ENABLE;
703	if (portStatus & OHCI_RH_PORTSTATUS_PSSC)
704		status->change |= PORT_STATUS_SUSPEND;
705	if (portStatus & OHCI_RH_PORTSTATUS_OCIC)
706		status->change |= PORT_STATUS_OVER_CURRENT;
707	if (portStatus & OHCI_RH_PORTSTATUS_PRSC)
708		status->change |= PORT_STATUS_RESET;
709
710	TRACE("port %u status 0x%04x change 0x%04x\n", index,
711		status->status, status->change);
712	return B_OK;
713}
714
715
716status_t
717OHCI::SetPortFeature(uint8 index, uint16 feature)
718{
719	TRACE("set port feature index %u feature %u\n", index, feature);
720	if (index > fPortCount)
721		return B_BAD_INDEX;
722
723	switch (feature) {
724		case PORT_ENABLE:
725			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PES);
726			return B_OK;
727
728		case PORT_SUSPEND:
729			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSS);
730			return B_OK;
731
732		case PORT_RESET:
733			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRS);
734			return B_OK;
735
736		case PORT_POWER:
737			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PPS);
738			return B_OK;
739	}
740
741	return B_BAD_VALUE;
742}
743
744
745status_t
746OHCI::ClearPortFeature(uint8 index, uint16 feature)
747{
748	TRACE("clear port feature index %u feature %u\n", index, feature);
749	if (index > fPortCount)
750		return B_BAD_INDEX;
751
752	switch (feature) {
753		case PORT_ENABLE:
754			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CCS);
755			return B_OK;
756
757		case PORT_SUSPEND:
758			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_POCI);
759			return B_OK;
760
761		case PORT_POWER:
762			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_LSDA);
763			return B_OK;
764
765		case C_PORT_CONNECTION:
766			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CSC);
767			return B_OK;
768
769		case C_PORT_ENABLE:
770			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PESC);
771			return B_OK;
772
773		case C_PORT_SUSPEND:
774			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSSC);
775			return B_OK;
776
777		case C_PORT_OVER_CURRENT:
778			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_OCIC);
779			return B_OK;
780
781		case C_PORT_RESET:
782			_WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRSC);
783			return B_OK;
784	}
785
786	return B_BAD_VALUE;
787}
788
789
790int32
791OHCI::_InterruptHandler(void *data)
792{
793	return ((OHCI *)data)->_Interrupt();
794}
795
796
797int32
798OHCI::_Interrupt()
799{
800	static spinlock lock = B_SPINLOCK_INITIALIZER;
801	acquire_spinlock(&lock);
802
803	uint32 status = 0;
804	uint32 acknowledge = 0;
805	bool finishTransfers = false;
806	int32 result = B_HANDLED_INTERRUPT;
807
808	// The LSb of done_head is used to inform the HCD that an interrupt
809	// condition exists for both the done list and for another event recorded in
810	// the HcInterruptStatus register. If done_head is 0, then the interrupt
811	// was caused by other than the HccaDoneHead update and the
812	// HcInterruptStatus register needs to be accessed to determine that exact
813	// interrupt cause. If HccDoneHead is nonzero, then a done list update
814	// interrupt is indicated and if the LSb of the Dword is nonzero, then an
815	// additional interrupt event is indicated and HcInterruptStatus should be
816	// checked to determine its cause.
817	uint32 doneHead = fHcca->done_head;
818	if (doneHead != 0) {
819		status = OHCI_WRITEBACK_DONE_HEAD;
820		if (doneHead & OHCI_DONE_INTERRUPTS)
821			status |= _ReadReg(OHCI_INTERRUPT_STATUS)
822				& _ReadReg(OHCI_INTERRUPT_ENABLE);
823	} else {
824		status = _ReadReg(OHCI_INTERRUPT_STATUS) & _ReadReg(OHCI_INTERRUPT_ENABLE)
825			& ~OHCI_WRITEBACK_DONE_HEAD;
826		if (status == 0) {
827			// Nothing to be done (PCI shared interrupt)
828			release_spinlock(&lock);
829			return B_UNHANDLED_INTERRUPT;
830		}
831	}
832
833	if (status & OHCI_SCHEDULING_OVERRUN) {
834		TRACE_MODULE("scheduling overrun occured\n");
835		acknowledge |= OHCI_SCHEDULING_OVERRUN;
836	}
837
838	if (status & OHCI_WRITEBACK_DONE_HEAD) {
839		TRACE_MODULE("transfer descriptors processed\n");
840		fHcca->done_head = 0;
841		acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
842		result = B_INVOKE_SCHEDULER;
843		finishTransfers = true;
844	}
845
846	if (status & OHCI_RESUME_DETECTED) {
847		TRACE_MODULE("resume detected\n");
848		acknowledge |= OHCI_RESUME_DETECTED;
849	}
850
851	if (status & OHCI_UNRECOVERABLE_ERROR) {
852		TRACE_MODULE_ERROR("unrecoverable error - controller halted\n");
853		_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
854		// TODO: clear all pending transfers, reset and resetup the controller
855	}
856
857	if (status & OHCI_ROOT_HUB_STATUS_CHANGE) {
858		TRACE_MODULE("root hub status change\n");
859		// Disable the interrupt as it will otherwise be retriggered until the
860		// port has been reset and the change is cleared explicitly.
861		// TODO: renable it once we use status changes instead of polling
862		_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ROOT_HUB_STATUS_CHANGE);
863		acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE;
864	}
865
866	if (acknowledge != 0)
867		_WriteReg(OHCI_INTERRUPT_STATUS, acknowledge);
868
869	release_spinlock(&lock);
870
871	if (finishTransfers)
872		release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
873
874	return result;
875}
876
877
878status_t
879OHCI::_AddPendingTransfer(Transfer *transfer,
880	ohci_endpoint_descriptor *endpoint, ohci_general_td *firstDescriptor,
881	ohci_general_td *dataDescriptor, ohci_general_td *lastDescriptor,
882	bool directionIn)
883{
884	if (!transfer || !endpoint || !lastDescriptor)
885		return B_BAD_VALUE;
886
887	transfer_data *data = new(std::nothrow) transfer_data;
888	if (!data)
889		return B_NO_MEMORY;
890
891	status_t result = transfer->InitKernelAccess();
892	if (result < B_OK) {
893		delete data;
894		return result;
895	}
896
897	data->transfer = transfer;
898	data->endpoint = endpoint;
899	data->incoming = directionIn;
900	data->canceled = false;
901	data->link = NULL;
902
903	// the current tail will become the first descriptor
904	data->first_descriptor = (ohci_general_td *)endpoint->tail_logical_descriptor;
905
906	// the data and first descriptors might be the same
907	if (dataDescriptor == firstDescriptor)
908		data->data_descriptor = data->first_descriptor;
909	else
910		data->data_descriptor = dataDescriptor;
911
912	// even the last and the first descriptor might be the same
913	if (lastDescriptor == firstDescriptor)
914		data->last_descriptor = data->first_descriptor;
915	else
916		data->last_descriptor = lastDescriptor;
917
918	if (!Lock()) {
919		delete data;
920		return B_ERROR;
921	}
922
923	if (fLastTransfer)
924		fLastTransfer->link = data;
925	else
926		fFirstTransfer = data;
927
928	fLastTransfer = data;
929	Unlock();
930
931	return B_OK;
932}
933
934
935status_t
936OHCI::_AddPendingIsochronousTransfer(Transfer *transfer,
937	ohci_endpoint_descriptor *endpoint, ohci_isochronous_td *firstDescriptor,
938	ohci_isochronous_td *lastDescriptor, bool directionIn)
939{
940	if (!transfer || !endpoint || !lastDescriptor)
941		return B_BAD_VALUE;
942
943	transfer_data *data = new(std::nothrow) transfer_data;
944	if (!data)
945		return B_NO_MEMORY;
946
947	status_t result = transfer->InitKernelAccess();
948	if (result < B_OK) {
949		delete data;
950		return result;
951	}
952
953	data->transfer = transfer;
954	data->endpoint = endpoint;
955	data->incoming = directionIn;
956	data->canceled = false;
957	data->link = NULL;
958
959	// the current tail will become the first descriptor
960	data->first_descriptor = (ohci_general_td*)endpoint->tail_logical_descriptor;
961
962	// the data and first descriptors are the same
963	data->data_descriptor = data->first_descriptor;
964
965	// the last and the first descriptor might be the same
966	if (lastDescriptor == firstDescriptor)
967		data->last_descriptor = data->first_descriptor;
968	else
969		data->last_descriptor = (ohci_general_td*)lastDescriptor;
970
971	if (!Lock()) {
972		delete data;
973		return B_ERROR;
974	}
975
976	if (fLastTransfer)
977		fLastTransfer->link = data;
978	else
979		fFirstTransfer = data;
980
981	fLastTransfer = data;
982	Unlock();
983
984	return B_OK;
985}
986
987
988int32
989OHCI::_FinishThread(void *data)
990{
991	((OHCI *)data)->_FinishTransfers();
992	return B_OK;
993}
994
995
996void
997OHCI::_FinishTransfers()
998{
999	while (!fStopFinishThread) {
1000		if (acquire_sem(fFinishTransfersSem) < B_OK)
1001			continue;
1002
1003		// eat up sems that have been released by multiple interrupts
1004		int32 semCount = 0;
1005		get_sem_count(fFinishTransfersSem, &semCount);
1006		if (semCount > 0)
1007			acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
1008
1009		if (!Lock())
1010			continue;
1011
1012		TRACE("finishing transfers (first transfer: %p; last"
1013			" transfer: %p)\n", fFirstTransfer, fLastTransfer);
1014		transfer_data *lastTransfer = NULL;
1015		transfer_data *transfer = fFirstTransfer;
1016		Unlock();
1017
1018		while (transfer) {
1019			bool transferDone = false;
1020			ohci_general_td *descriptor = transfer->first_descriptor;
1021			ohci_endpoint_descriptor *endpoint = transfer->endpoint;
1022			status_t callbackStatus = B_OK;
1023
1024			if (endpoint->flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT) {
1025				transfer_data *next = transfer->link;
1026				if (_FinishIsochronousTransfer(transfer, &lastTransfer)) {
1027					delete transfer->transfer;
1028					delete transfer;
1029				}
1030				transfer = next;
1031				continue;
1032			}
1033
1034			MutexLocker endpointLocker(endpoint->lock);
1035
1036			if ((endpoint->head_physical_descriptor & OHCI_ENDPOINT_HEAD_MASK)
1037					!= endpoint->tail_physical_descriptor
1038						&& (endpoint->head_physical_descriptor
1039							& OHCI_ENDPOINT_HALTED) == 0) {
1040				// there are still active transfers on this endpoint, we need
1041				// to wait for all of them to complete, otherwise we'd read
1042				// a potentially bogus data toggle value below
1043				TRACE("endpoint %p still has active tds\n", endpoint);
1044				lastTransfer = transfer;
1045				transfer = transfer->link;
1046				continue;
1047			}
1048
1049			endpointLocker.Unlock();
1050
1051			while (descriptor && !transfer->canceled) {
1052				uint32 status = OHCI_TD_GET_CONDITION_CODE(descriptor->flags);
1053				if (status == OHCI_TD_CONDITION_NOT_ACCESSED) {
1054					// td is still active
1055					TRACE("td %p still active\n", descriptor);
1056					break;
1057				}
1058
1059				if (status != OHCI_TD_CONDITION_NO_ERROR) {
1060					// an error occured, but we must ensure that the td
1061					// was actually done
1062					if (endpoint->head_physical_descriptor & OHCI_ENDPOINT_HALTED) {
1063						// the endpoint is halted, this guaratees us that this
1064						// descriptor has passed (we don't know if the endpoint
1065						// was halted because of this td, but we do not need
1066						// to know, as when it was halted by another td this
1067						// still ensures that this td was handled before).
1068						TRACE_ERROR("td error: 0x%08" B_PRIx32 "\n", status);
1069
1070						callbackStatus = _GetStatusOfConditionCode(status);
1071
1072						transferDone = true;
1073						break;
1074					} else {
1075						// an error occured but the endpoint is not halted so
1076						// the td is in fact still active
1077						TRACE("td %p active with error\n", descriptor);
1078						break;
1079					}
1080				}
1081
1082				// the td has completed without an error
1083				TRACE("td %p done\n", descriptor);
1084
1085				if (descriptor == transfer->last_descriptor
1086					|| descriptor->buffer_physical != 0) {
1087					// this is the last td of the transfer or a short packet
1088					callbackStatus = B_OK;
1089					transferDone = true;
1090					break;
1091				}
1092
1093				descriptor
1094					= (ohci_general_td *)descriptor->next_logical_descriptor;
1095			}
1096
1097			if (transfer->canceled) {
1098				// when a transfer is canceled, all transfers to that endpoint
1099				// are canceled by setting the head pointer to the tail pointer
1100				// which causes all of the tds to become "free" (as they are
1101				// inaccessible and not accessed anymore (as setting the head
1102				// pointer required disabling the endpoint))
1103				callbackStatus = B_OK;
1104				transferDone = true;
1105			}
1106
1107			if (!transferDone) {
1108				lastTransfer = transfer;
1109				transfer = transfer->link;
1110				continue;
1111			}
1112
1113			// remove the transfer from the list first so we are sure
1114			// it doesn't get canceled while we still process it
1115			transfer_data *next = transfer->link;
1116			if (Lock()) {
1117				if (lastTransfer)
1118					lastTransfer->link = transfer->link;
1119
1120				if (transfer == fFirstTransfer)
1121					fFirstTransfer = transfer->link;
1122				if (transfer == fLastTransfer)
1123					fLastTransfer = lastTransfer;
1124
1125				// store the currently processing pipe here so we can wait
1126				// in cancel if we are processing something on the target pipe
1127				if (!transfer->canceled)
1128					fProcessingPipe = transfer->transfer->TransferPipe();
1129
1130				transfer->link = NULL;
1131				Unlock();
1132			}
1133
1134			// break the descriptor chain on the last descriptor
1135			transfer->last_descriptor->next_logical_descriptor = NULL;
1136			TRACE("transfer %p done with status 0x%08" B_PRIx32 "\n",
1137				transfer, callbackStatus);
1138
1139			// if canceled the callback has already been called
1140			if (!transfer->canceled) {
1141				size_t actualLength = 0;
1142				if (callbackStatus == B_OK) {
1143					if (transfer->data_descriptor && transfer->incoming) {
1144						// data to read out
1145						iovec *vector = transfer->transfer->Vector();
1146						size_t vectorCount = transfer->transfer->VectorCount();
1147
1148						transfer->transfer->PrepareKernelAccess();
1149						actualLength = _ReadDescriptorChain(
1150							transfer->data_descriptor,
1151							vector, vectorCount);
1152					} else if (transfer->data_descriptor) {
1153						// read the actual length that was sent
1154						actualLength = _ReadActualLength(
1155							transfer->data_descriptor);
1156					}
1157
1158					// get the last data toggle and store it for next time
1159					transfer->transfer->TransferPipe()->SetDataToggle(
1160						(endpoint->head_physical_descriptor
1161							& OHCI_ENDPOINT_TOGGLE_CARRY) != 0);
1162
1163					if (transfer->transfer->IsFragmented()) {
1164						// this transfer may still have data left
1165						TRACE("advancing fragmented transfer\n");
1166						transfer->transfer->AdvanceByFragment(actualLength);
1167						if (transfer->transfer->VectorLength() > 0) {
1168							TRACE("still %ld bytes left on transfer\n",
1169								transfer->transfer->VectorLength());
1170							// TODO actually resubmit the transfer
1171						}
1172
1173						// the transfer is done, but we already set the
1174						// actualLength with AdvanceByFragment()
1175						actualLength = 0;
1176					}
1177				}
1178
1179				transfer->transfer->Finished(callbackStatus, actualLength);
1180				fProcessingPipe = NULL;
1181			}
1182
1183			if (callbackStatus != B_OK) {
1184				// remove the transfer and make the head pointer valid again
1185				// (including clearing the halt state)
1186				_RemoveTransferFromEndpoint(transfer);
1187			}
1188
1189			// free the descriptors
1190			_FreeDescriptorChain(transfer->first_descriptor);
1191
1192			delete transfer->transfer;
1193			delete transfer;
1194			transfer = next;
1195		}
1196	}
1197}
1198
1199
1200bool
1201OHCI::_FinishIsochronousTransfer(transfer_data *transfer,
1202	transfer_data **_lastTransfer)
1203{
1204	status_t callbackStatus = B_OK;
1205	size_t actualLength = 0;
1206	uint32 packet = 0;
1207
1208	if (transfer->canceled)
1209		callbackStatus = B_CANCELED;
1210	else {
1211		// at first check if ALL ITDs are retired by HC
1212		ohci_isochronous_td *descriptor
1213			= (ohci_isochronous_td *)transfer->first_descriptor;
1214		while (descriptor) {
1215			if (OHCI_TD_GET_CONDITION_CODE(descriptor->flags)
1216				== OHCI_TD_CONDITION_NOT_ACCESSED) {
1217				TRACE("ITD %p still active\n", descriptor);
1218				*_lastTransfer = transfer;
1219				return false;
1220			}
1221
1222			if (descriptor == (ohci_isochronous_td*)transfer->last_descriptor) {
1223				// this is the last ITD of the transfer
1224				descriptor = (ohci_isochronous_td *)transfer->first_descriptor;
1225				break;
1226			}
1227
1228			descriptor
1229				= (ohci_isochronous_td *)descriptor->next_done_descriptor;
1230		}
1231
1232		while (descriptor) {
1233			uint32 status = OHCI_TD_GET_CONDITION_CODE(descriptor->flags);
1234			if (status != OHCI_TD_CONDITION_NO_ERROR) {
1235				TRACE_ERROR("ITD error: 0x%08" B_PRIx32 "\n", status);
1236				// spec says that in most cases condition code
1237				// of retired ITDs is set to NoError, but for the
1238				// time overrun it can be DataOverrun. We assume
1239				// the _first_ occurience of such error as status
1240				// reported to the callback
1241				if (callbackStatus == B_OK)
1242					callbackStatus = _GetStatusOfConditionCode(status);
1243			}
1244
1245			usb_isochronous_data *isochronousData
1246				= transfer->transfer->IsochronousData();
1247
1248			uint32 frameCount = OHCI_ITD_GET_FRAME_COUNT(descriptor->flags);
1249			for (size_t i = 0; i < frameCount; i++, packet++) {
1250				usb_iso_packet_descriptor* packet_descriptor
1251					= &isochronousData->packet_descriptors[packet];
1252
1253				uint16 offset = descriptor->offset[OHCI_ITD_OFFSET_IDX(i)];
1254				uint8 code = OHCI_ITD_GET_BUFFER_CONDITION_CODE(offset);
1255				packet_descriptor->status = _GetStatusOfConditionCode(code);
1256
1257				// not touched by HC - sheduled too late to be processed
1258				// in the requested frame - so we ignore it too
1259				if (packet_descriptor->status == B_DEV_TOO_LATE)
1260					continue;
1261
1262				size_t len = OHCI_ITD_GET_BUFFER_LENGTH(offset);
1263				if (!transfer->incoming)
1264					len = packet_descriptor->request_length - len;
1265
1266				packet_descriptor->actual_length = len;
1267				actualLength += len;
1268			}
1269
1270			uint16 frame = OHCI_ITD_GET_STARTING_FRAME(descriptor->flags);
1271			_ReleaseIsochronousBandwidth(frame,
1272				OHCI_ITD_GET_FRAME_COUNT(descriptor->flags));
1273
1274			TRACE("ITD %p done\n", descriptor);
1275
1276			if (descriptor == (ohci_isochronous_td*)transfer->last_descriptor)
1277				break;
1278
1279			descriptor
1280				= (ohci_isochronous_td *)descriptor->next_done_descriptor;
1281		}
1282	}
1283
1284	// remove the transfer from the list first so we are sure
1285	// it doesn't get canceled while we still process it
1286	if (Lock()) {
1287		if (*_lastTransfer)
1288			(*_lastTransfer)->link = transfer->link;
1289
1290		if (transfer == fFirstTransfer)
1291			fFirstTransfer = transfer->link;
1292		if (transfer == fLastTransfer)
1293			fLastTransfer = *_lastTransfer;
1294
1295		// store the currently processing pipe here so we can wait
1296		// in cancel if we are processing something on the target pipe
1297		if (!transfer->canceled)
1298			fProcessingPipe = transfer->transfer->TransferPipe();
1299
1300		transfer->link = NULL;
1301		Unlock();
1302	}
1303
1304	// break the descriptor chain on the last descriptor
1305	transfer->last_descriptor->next_logical_descriptor = NULL;
1306	TRACE("iso.transfer %p done with status 0x%08" B_PRIx32 " len:%ld\n",
1307		transfer, callbackStatus, actualLength);
1308
1309	// if canceled the callback has already been called
1310	if (!transfer->canceled) {
1311		if (callbackStatus == B_OK && actualLength > 0) {
1312			if (transfer->data_descriptor && transfer->incoming) {
1313				// data to read out
1314				iovec *vector = transfer->transfer->Vector();
1315				size_t vectorCount = transfer->transfer->VectorCount();
1316
1317				transfer->transfer->PrepareKernelAccess();
1318				_ReadIsochronousDescriptorChain(
1319					(ohci_isochronous_td*)transfer->data_descriptor,
1320					vector, vectorCount);
1321			}
1322		}
1323
1324		transfer->transfer->Finished(callbackStatus, actualLength);
1325		fProcessingPipe = NULL;
1326	}
1327
1328	_FreeIsochronousDescriptorChain(
1329		(ohci_isochronous_td*)transfer->first_descriptor);
1330
1331	return true;
1332}
1333
1334
1335status_t
1336OHCI::_SubmitRequest(Transfer *transfer)
1337{
1338	usb_request_data *requestData = transfer->RequestData();
1339	bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) != 0;
1340
1341	ohci_general_td *setupDescriptor
1342		= _CreateGeneralDescriptor(sizeof(usb_request_data));
1343	if (!setupDescriptor) {
1344		TRACE_ERROR("failed to allocate setup descriptor\n");
1345		return B_NO_MEMORY;
1346	}
1347
1348	setupDescriptor->flags = OHCI_TD_DIRECTION_PID_SETUP
1349		| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1350		| OHCI_TD_TOGGLE_0
1351		| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
1352
1353	ohci_general_td *statusDescriptor = _CreateGeneralDescriptor(0);
1354	if (!statusDescriptor) {
1355		TRACE_ERROR("failed to allocate status descriptor\n");
1356		_FreeGeneralDescriptor(setupDescriptor);
1357		return B_NO_MEMORY;
1358	}
1359
1360	statusDescriptor->flags
1361		= (directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN)
1362		| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1363		| OHCI_TD_TOGGLE_1
1364		| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1365
1366	iovec vector;
1367	vector.iov_base = requestData;
1368	vector.iov_len = sizeof(usb_request_data);
1369	_WriteDescriptorChain(setupDescriptor, &vector, 1);
1370
1371	status_t result;
1372	ohci_general_td *dataDescriptor = NULL;
1373	if (transfer->VectorCount() > 0) {
1374		ohci_general_td *lastDescriptor = NULL;
1375		result = _CreateDescriptorChain(&dataDescriptor, &lastDescriptor,
1376			directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT,
1377			transfer->VectorLength());
1378		if (result < B_OK) {
1379			_FreeGeneralDescriptor(setupDescriptor);
1380			_FreeGeneralDescriptor(statusDescriptor);
1381			return result;
1382		}
1383
1384		if (!directionIn) {
1385			_WriteDescriptorChain(dataDescriptor, transfer->Vector(),
1386				transfer->VectorCount());
1387		}
1388
1389		_LinkDescriptors(setupDescriptor, dataDescriptor);
1390		_LinkDescriptors(lastDescriptor, statusDescriptor);
1391	} else {
1392		_LinkDescriptors(setupDescriptor, statusDescriptor);
1393	}
1394
1395	// Add to the transfer list
1396	ohci_endpoint_descriptor *endpoint
1397		= (ohci_endpoint_descriptor *)transfer->TransferPipe()->ControllerCookie();
1398
1399	MutexLocker endpointLocker(endpoint->lock);
1400	result = _AddPendingTransfer(transfer, endpoint, setupDescriptor,
1401		dataDescriptor, statusDescriptor, directionIn);
1402	if (result < B_OK) {
1403		TRACE_ERROR("failed to add pending transfer\n");
1404		_FreeDescriptorChain(setupDescriptor);
1405		return result;
1406	}
1407
1408	// Add the descriptor chain to the endpoint
1409	_SwitchEndpointTail(endpoint, setupDescriptor, statusDescriptor);
1410	endpointLocker.Unlock();
1411
1412	// Tell the controller to process the control list
1413	endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1414	_WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED);
1415	return B_OK;
1416}
1417
1418
1419status_t
1420OHCI::_SubmitTransfer(Transfer *transfer)
1421{
1422	Pipe *pipe = transfer->TransferPipe();
1423	bool directionIn = (pipe->Direction() == Pipe::In);
1424
1425	ohci_general_td *firstDescriptor = NULL;
1426	ohci_general_td *lastDescriptor = NULL;
1427	status_t result = _CreateDescriptorChain(&firstDescriptor, &lastDescriptor,
1428		directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT,
1429		transfer->VectorLength());
1430
1431	if (result < B_OK)
1432		return result;
1433
1434	// Apply data toggle to the first descriptor (the others will use the carry)
1435	firstDescriptor->flags &= ~OHCI_TD_TOGGLE_CARRY;
1436	firstDescriptor->flags |= pipe->DataToggle() ? OHCI_TD_TOGGLE_1
1437		: OHCI_TD_TOGGLE_0;
1438
1439	// Set the last descriptor to generate an interrupt
1440	lastDescriptor->flags &= ~OHCI_TD_INTERRUPT_MASK;
1441	lastDescriptor->flags |=
1442		OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
1443
1444	if (!directionIn) {
1445		_WriteDescriptorChain(firstDescriptor, transfer->Vector(),
1446			transfer->VectorCount());
1447	}
1448
1449	// Add to the transfer list
1450	ohci_endpoint_descriptor *endpoint
1451		= (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1452
1453	MutexLocker endpointLocker(endpoint->lock);
1454	result = _AddPendingTransfer(transfer, endpoint, firstDescriptor,
1455		firstDescriptor, lastDescriptor, directionIn);
1456	if (result < B_OK) {
1457		TRACE_ERROR("failed to add pending transfer\n");
1458		_FreeDescriptorChain(firstDescriptor);
1459		return result;
1460	}
1461
1462	// Add the descriptor chain to the endpoint
1463	_SwitchEndpointTail(endpoint, firstDescriptor, lastDescriptor);
1464	endpointLocker.Unlock();
1465
1466	endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1467	if (pipe->Type() & USB_OBJECT_BULK_PIPE) {
1468		// Tell the controller to process the bulk list
1469		_WriteReg(OHCI_COMMAND_STATUS, OHCI_BULK_LIST_FILLED);
1470	}
1471
1472	return B_OK;
1473}
1474
1475
1476status_t
1477OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
1478{
1479	Pipe *pipe = transfer->TransferPipe();
1480	bool directionIn = (pipe->Direction() == Pipe::In);
1481	usb_isochronous_data *isochronousData = transfer->IsochronousData();
1482
1483	ohci_isochronous_td *firstDescriptor = NULL;
1484	ohci_isochronous_td *lastDescriptor = NULL;
1485	status_t result = _CreateIsochronousDescriptorChain(&firstDescriptor,
1486		&lastDescriptor, transfer);
1487
1488	if (firstDescriptor == 0 || lastDescriptor == 0)
1489		return B_ERROR;
1490
1491	if (result < B_OK)
1492		return result;
1493
1494	// Set the last descriptor to generate an interrupt
1495	lastDescriptor->flags &= ~OHCI_ITD_INTERRUPT_MASK;
1496	// let the controller retire last ITD
1497	lastDescriptor->flags |= OHCI_ITD_SET_DELAY_INTERRUPT(1);
1498
1499	// If direction is out set every descriptor data
1500	if (pipe->Direction() == Pipe::Out)
1501		_WriteIsochronousDescriptorChain(firstDescriptor,
1502			transfer->Vector(), transfer->VectorCount());
1503	else
1504		// Initialize the packet descriptors
1505		for (uint32 i = 0; i < isochronousData->packet_count; i++) {
1506			isochronousData->packet_descriptors[i].actual_length = 0;
1507			isochronousData->packet_descriptors[i].status = B_NO_INIT;
1508		}
1509
1510	// Add to the transfer list
1511	ohci_endpoint_descriptor *endpoint
1512		= (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1513
1514	MutexLocker endpointLocker(endpoint->lock);
1515	result = _AddPendingIsochronousTransfer(transfer, endpoint,
1516		firstDescriptor, lastDescriptor, directionIn);
1517	if (result < B_OK) {
1518		TRACE_ERROR("failed to add pending iso.transfer:"
1519			"0x%08" B_PRIx32 "\n", result);
1520		_FreeIsochronousDescriptorChain(firstDescriptor);
1521		return result;
1522	}
1523
1524	// Add the descriptor chain to the endpoint
1525	_SwitchIsochronousEndpointTail(endpoint, firstDescriptor, lastDescriptor);
1526	endpointLocker.Unlock();
1527
1528	endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
1529
1530	return B_OK;
1531}
1532
1533
1534void
1535OHCI::_SwitchEndpointTail(ohci_endpoint_descriptor *endpoint,
1536	ohci_general_td *first, ohci_general_td *last)
1537{
1538	// fill in the information of the first descriptor into the current tail
1539	ohci_general_td *tail = (ohci_general_td *)endpoint->tail_logical_descriptor;
1540	tail->flags = first->flags;
1541	tail->buffer_physical = first->buffer_physical;
1542	tail->next_physical_descriptor = first->next_physical_descriptor;
1543	tail->last_physical_byte_address = first->last_physical_byte_address;
1544	tail->buffer_size = first->buffer_size;
1545	tail->buffer_logical = first->buffer_logical;
1546	tail->next_logical_descriptor = first->next_logical_descriptor;
1547
1548	// the first descriptor becomes the new tail
1549	first->flags = 0;
1550	first->buffer_physical = 0;
1551	first->next_physical_descriptor = 0;
1552	first->last_physical_byte_address = 0;
1553	first->buffer_size = 0;
1554	first->buffer_logical = NULL;
1555	first->next_logical_descriptor = NULL;
1556
1557	if (first == last)
1558		_LinkDescriptors(tail, first);
1559	else
1560		_LinkDescriptors(last, first);
1561
1562	// update the endpoint tail pointer to reflect the change
1563	endpoint->tail_logical_descriptor = first;
1564	endpoint->tail_physical_descriptor = (uint32)first->physical_address;
1565	TRACE("switched tail from %p to %p\n", tail, first);
1566
1567#if 0
1568	_PrintEndpoint(endpoint);
1569	_PrintDescriptorChain(tail);
1570#endif
1571}
1572
1573
1574void
1575OHCI::_SwitchIsochronousEndpointTail(ohci_endpoint_descriptor *endpoint,
1576	ohci_isochronous_td *first, ohci_isochronous_td *last)
1577{
1578	// fill in the information of the first descriptor into the current tail
1579	ohci_isochronous_td *tail
1580		= (ohci_isochronous_td*)endpoint->tail_logical_descriptor;
1581	tail->flags = first->flags;
1582	tail->buffer_page_byte_0 = first->buffer_page_byte_0;
1583	tail->next_physical_descriptor = first->next_physical_descriptor;
1584	tail->last_byte_address = first->last_byte_address;
1585	tail->buffer_size = first->buffer_size;
1586	tail->buffer_logical = first->buffer_logical;
1587	tail->next_logical_descriptor = first->next_logical_descriptor;
1588	tail->next_done_descriptor = first->next_done_descriptor;
1589
1590	// the first descriptor becomes the new tail
1591	first->flags = 0;
1592	first->buffer_page_byte_0 = 0;
1593	first->next_physical_descriptor = 0;
1594	first->last_byte_address = 0;
1595	first->buffer_size = 0;
1596	first->buffer_logical = NULL;
1597	first->next_logical_descriptor = NULL;
1598	first->next_done_descriptor = NULL;
1599
1600	for (int i = 0; i < OHCI_ITD_NOFFSET; i++) {
1601		tail->offset[i] = first->offset[i];
1602		first->offset[i] = 0;
1603	}
1604
1605	if (first == last)
1606		_LinkIsochronousDescriptors(tail, first, NULL);
1607	else
1608		_LinkIsochronousDescriptors(last, first, NULL);
1609
1610	// update the endpoint tail pointer to reflect the change
1611	endpoint->tail_logical_descriptor = first;
1612	endpoint->tail_physical_descriptor = (uint32)first->physical_address;
1613	TRACE("switched tail from %p to %p\n", tail, first);
1614
1615#if 0
1616	_PrintEndpoint(endpoint);
1617	_PrintDescriptorChain(tail);
1618#endif
1619}
1620
1621
1622void
1623OHCI::_RemoveTransferFromEndpoint(transfer_data *transfer)
1624{
1625	// The transfer failed and the endpoint was halted. This means that the
1626	// endpoint head pointer might point somewhere into the descriptor chain
1627	// of this transfer. As we do not know if this transfer actually caused
1628	// the halt on the endpoint we have to make sure this is the case. If we
1629	// find the head to point to somewhere into the descriptor chain then
1630	// simply advancing the head pointer to the link of the last transfer
1631	// will bring the endpoint into a valid state again. This operation is
1632	// safe as the endpoint is currently halted and we therefore can change
1633	// the head pointer.
1634	ohci_endpoint_descriptor *endpoint = transfer->endpoint;
1635	ohci_general_td *descriptor = transfer->first_descriptor;
1636	while (descriptor) {
1637		if ((endpoint->head_physical_descriptor & OHCI_ENDPOINT_HEAD_MASK)
1638			== descriptor->physical_address) {
1639			// This descriptor caused the halt. Advance the head pointer. This
1640			// will either move the head to the next valid transfer that can
1641			// then be restarted, or it will move the head to the tail when
1642			// there are no more transfer descriptors. Setting the head will
1643			// also clear the halt state as it is stored in the first bit of
1644			// the head pointer.
1645			endpoint->head_physical_descriptor
1646				= transfer->last_descriptor->next_physical_descriptor;
1647			return;
1648		}
1649
1650		descriptor = (ohci_general_td *)descriptor->next_logical_descriptor;
1651	}
1652}
1653
1654
1655ohci_endpoint_descriptor *
1656OHCI::_AllocateEndpoint()
1657{
1658	ohci_endpoint_descriptor *endpoint;
1659	phys_addr_t physicalAddress;
1660
1661	mutex *lock = (mutex *)malloc(sizeof(mutex));
1662	if (lock == NULL) {
1663		TRACE_ERROR("no memory to allocate endpoint lock\n");
1664		return NULL;
1665	}
1666
1667	// Allocate memory chunk
1668	if (fStack->AllocateChunk((void **)&endpoint, &physicalAddress,
1669		sizeof(ohci_endpoint_descriptor)) < B_OK) {
1670		TRACE_ERROR("failed to allocate endpoint descriptor\n");
1671		free(lock);
1672		return NULL;
1673	}
1674
1675	mutex_init(lock, "ohci endpoint lock");
1676
1677	endpoint->flags = OHCI_ENDPOINT_SKIP;
1678	endpoint->physical_address = (uint32)physicalAddress;
1679	endpoint->head_physical_descriptor = 0;
1680	endpoint->tail_logical_descriptor = NULL;
1681	endpoint->tail_physical_descriptor = 0;
1682	endpoint->next_logical_endpoint = NULL;
1683	endpoint->next_physical_endpoint = 0;
1684	endpoint->lock = lock;
1685	return endpoint;
1686}
1687
1688
1689void
1690OHCI::_FreeEndpoint(ohci_endpoint_descriptor *endpoint)
1691{
1692	if (!endpoint)
1693		return;
1694
1695	mutex_destroy(endpoint->lock);
1696	free(endpoint->lock);
1697
1698	fStack->FreeChunk((void *)endpoint, endpoint->physical_address,
1699		sizeof(ohci_endpoint_descriptor));
1700}
1701
1702
1703status_t
1704OHCI::_InsertEndpointForPipe(Pipe *pipe)
1705{
1706	TRACE("inserting endpoint for device %u endpoint %u\n",
1707		pipe->DeviceAddress(), pipe->EndpointAddress());
1708
1709	ohci_endpoint_descriptor *endpoint = _AllocateEndpoint();
1710	if (!endpoint) {
1711		TRACE_ERROR("cannot allocate memory for endpoint\n");
1712		return B_NO_MEMORY;
1713	}
1714
1715	uint32 flags = OHCI_ENDPOINT_SKIP;
1716
1717	// Set up device and endpoint address
1718	flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(pipe->DeviceAddress())
1719		| OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(pipe->EndpointAddress());
1720
1721	// Set the direction
1722	switch (pipe->Direction()) {
1723		case Pipe::In:
1724			flags |= OHCI_ENDPOINT_DIRECTION_IN;
1725			break;
1726
1727		case Pipe::Out:
1728			flags |= OHCI_ENDPOINT_DIRECTION_OUT;
1729			break;
1730
1731		case Pipe::Default:
1732			flags |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR;
1733			break;
1734
1735		default:
1736			TRACE_ERROR("direction unknown\n");
1737			_FreeEndpoint(endpoint);
1738			return B_ERROR;
1739	}
1740
1741	// Set up the speed
1742	switch (pipe->Speed()) {
1743		case USB_SPEED_LOWSPEED:
1744			flags |= OHCI_ENDPOINT_LOW_SPEED;
1745			break;
1746
1747		case USB_SPEED_FULLSPEED:
1748			flags |= OHCI_ENDPOINT_FULL_SPEED;
1749			break;
1750
1751		default:
1752			TRACE_ERROR("unacceptable speed\n");
1753			_FreeEndpoint(endpoint);
1754			return B_ERROR;
1755	}
1756
1757	// Set the maximum packet size
1758	flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(pipe->MaxPacketSize());
1759	endpoint->flags = flags;
1760
1761	// Add the endpoint to the appropriate list
1762	uint32 type = pipe->Type();
1763	ohci_endpoint_descriptor *head = NULL;
1764	if (type & USB_OBJECT_CONTROL_PIPE)
1765		head = fDummyControl;
1766	else if (type & USB_OBJECT_BULK_PIPE)
1767		head = fDummyBulk;
1768	else if (type & USB_OBJECT_INTERRUPT_PIPE)
1769		head = _FindInterruptEndpoint(pipe->Interval());
1770	else if (type & USB_OBJECT_ISO_PIPE)
1771		head = fDummyIsochronous;
1772	else
1773		TRACE_ERROR("unknown pipe type\n");
1774
1775	if (head == NULL) {
1776		TRACE_ERROR("no list found for endpoint\n");
1777		_FreeEndpoint(endpoint);
1778		return B_ERROR;
1779	}
1780
1781	// Create (necessary) tail descriptor
1782	if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
1783		// Set the isochronous bit format
1784		endpoint->flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
1785		ohci_isochronous_td *tail = _CreateIsochronousDescriptor(0);
1786		tail->flags = 0;
1787		endpoint->tail_logical_descriptor = tail;
1788		endpoint->head_physical_descriptor = tail->physical_address;
1789		endpoint->tail_physical_descriptor = tail->physical_address;
1790	} else {
1791		ohci_general_td *tail = _CreateGeneralDescriptor(0);
1792		tail->flags = 0;
1793		endpoint->tail_logical_descriptor = tail;
1794		endpoint->head_physical_descriptor = tail->physical_address;
1795		endpoint->tail_physical_descriptor = tail->physical_address;
1796	}
1797
1798	if (!_LockEndpoints()) {
1799		if (endpoint->tail_logical_descriptor) {
1800			_FreeGeneralDescriptor(
1801				(ohci_general_td *)endpoint->tail_logical_descriptor);
1802		}
1803
1804		_FreeEndpoint(endpoint);
1805		return B_ERROR;
1806	}
1807
1808	pipe->SetControllerCookie((void *)endpoint);
1809	endpoint->next_logical_endpoint = head->next_logical_endpoint;
1810	endpoint->next_physical_endpoint = head->next_physical_endpoint;
1811	head->next_logical_endpoint = (void *)endpoint;
1812	head->next_physical_endpoint = (uint32)endpoint->physical_address;
1813
1814	_UnlockEndpoints();
1815	return B_OK;
1816}
1817
1818
1819status_t
1820OHCI::_RemoveEndpointForPipe(Pipe *pipe)
1821{
1822	TRACE("removing endpoint for device %u endpoint %u\n",
1823		pipe->DeviceAddress(), pipe->EndpointAddress());
1824
1825	ohci_endpoint_descriptor *endpoint
1826		= (ohci_endpoint_descriptor *)pipe->ControllerCookie();
1827	if (endpoint == NULL)
1828		return B_OK;
1829
1830	// TODO implement properly, but at least disable it for now
1831	endpoint->flags |= OHCI_ENDPOINT_SKIP;
1832	return B_OK;
1833}
1834
1835
1836ohci_endpoint_descriptor *
1837OHCI::_FindInterruptEndpoint(uint8 interval)
1838{
1839	uint32 index = 0;
1840	uint32 power = 1;
1841	while (power <= OHCI_BIGGEST_INTERVAL / 2) {
1842		if (power * 2 > interval)
1843			break;
1844
1845		power *= 2;
1846		index++;
1847	}
1848
1849	return fInterruptEndpoints[index];
1850}
1851
1852
1853ohci_general_td *
1854OHCI::_CreateGeneralDescriptor(size_t bufferSize)
1855{
1856	ohci_general_td *descriptor;
1857	phys_addr_t physicalAddress;
1858
1859	if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
1860		sizeof(ohci_general_td)) != B_OK) {
1861		TRACE_ERROR("failed to allocate general descriptor\n");
1862		return NULL;
1863	}
1864
1865	descriptor->physical_address = (uint32)physicalAddress;
1866	descriptor->next_physical_descriptor = 0;
1867	descriptor->next_logical_descriptor = NULL;
1868	descriptor->buffer_size = bufferSize;
1869	if (bufferSize == 0) {
1870		descriptor->buffer_physical = 0;
1871		descriptor->buffer_logical = NULL;
1872		descriptor->last_physical_byte_address = 0;
1873		return descriptor;
1874	}
1875
1876	if (fStack->AllocateChunk(&descriptor->buffer_logical,
1877		&physicalAddress, bufferSize) != B_OK) {
1878		TRACE_ERROR("failed to allocate space for buffer\n");
1879		fStack->FreeChunk(descriptor, descriptor->physical_address,
1880			sizeof(ohci_general_td));
1881		return NULL;
1882	}
1883	descriptor->buffer_physical = physicalAddress;
1884
1885	descriptor->last_physical_byte_address
1886		= descriptor->buffer_physical + bufferSize - 1;
1887	return descriptor;
1888}
1889
1890
1891void
1892OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor)
1893{
1894	if (!descriptor)
1895		return;
1896
1897	if (descriptor->buffer_logical) {
1898		fStack->FreeChunk(descriptor->buffer_logical,
1899			descriptor->buffer_physical, descriptor->buffer_size);
1900	}
1901
1902	fStack->FreeChunk((void *)descriptor, descriptor->physical_address,
1903		sizeof(ohci_general_td));
1904}
1905
1906
1907status_t
1908OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor,
1909	ohci_general_td **_lastDescriptor, uint32 direction, size_t bufferSize)
1910{
1911	size_t blockSize = 8192;
1912	int32 descriptorCount = (bufferSize + blockSize - 1) / blockSize;
1913	if (descriptorCount == 0)
1914		descriptorCount = 1;
1915
1916	ohci_general_td *firstDescriptor = NULL;
1917	ohci_general_td *lastDescriptor = *_firstDescriptor;
1918	for (int32 i = 0; i < descriptorCount; i++) {
1919		ohci_general_td *descriptor = _CreateGeneralDescriptor(
1920			min_c(blockSize, bufferSize));
1921
1922		if (!descriptor) {
1923			_FreeDescriptorChain(firstDescriptor);
1924			return B_NO_MEMORY;
1925		}
1926
1927		descriptor->flags = direction
1928			| OHCI_TD_BUFFER_ROUNDING
1929			| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED)
1930			| OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE)
1931			| OHCI_TD_TOGGLE_CARRY;
1932
1933		// link to previous
1934		if (lastDescriptor)
1935			_LinkDescriptors(lastDescriptor, descriptor);
1936
1937		bufferSize -= blockSize;
1938		lastDescriptor = descriptor;
1939		if (!firstDescriptor)
1940			firstDescriptor = descriptor;
1941	}
1942
1943	*_firstDescriptor = firstDescriptor;
1944	*_lastDescriptor = lastDescriptor;
1945	return B_OK;
1946}
1947
1948
1949void
1950OHCI::_FreeDescriptorChain(ohci_general_td *topDescriptor)
1951{
1952	ohci_general_td *current = topDescriptor;
1953	ohci_general_td *next = NULL;
1954
1955	while (current) {
1956		next = (ohci_general_td *)current->next_logical_descriptor;
1957		_FreeGeneralDescriptor(current);
1958		current = next;
1959	}
1960}
1961
1962
1963ohci_isochronous_td *
1964OHCI::_CreateIsochronousDescriptor(size_t bufferSize)
1965{
1966	ohci_isochronous_td *descriptor = NULL;
1967	phys_addr_t physicalAddress;
1968
1969	if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
1970		sizeof(ohci_isochronous_td)) != B_OK) {
1971		TRACE_ERROR("failed to allocate isochronous descriptor\n");
1972		return NULL;
1973	}
1974
1975	descriptor->physical_address = (uint32)physicalAddress;
1976	descriptor->next_physical_descriptor = 0;
1977	descriptor->next_logical_descriptor = NULL;
1978	descriptor->next_done_descriptor = NULL;
1979	descriptor->buffer_size = bufferSize;
1980	if (bufferSize == 0) {
1981		descriptor->buffer_page_byte_0 = 0;
1982		descriptor->buffer_logical = NULL;
1983		descriptor->last_byte_address = 0;
1984		return descriptor;
1985	}
1986
1987	if (fStack->AllocateChunk(&descriptor->buffer_logical,
1988		&physicalAddress, bufferSize) != B_OK) {
1989		TRACE_ERROR("failed to allocate space for iso.buffer\n");
1990		fStack->FreeChunk(descriptor, descriptor->physical_address,
1991			sizeof(ohci_isochronous_td));
1992		return NULL;
1993	}
1994	descriptor->buffer_page_byte_0 = (uint32)physicalAddress;
1995	descriptor->last_byte_address
1996		= descriptor->buffer_page_byte_0 + bufferSize - 1;
1997
1998	return descriptor;
1999}
2000
2001
2002void
2003OHCI::_FreeIsochronousDescriptor(ohci_isochronous_td *descriptor)
2004{
2005	if (!descriptor)
2006		return;
2007
2008	if (descriptor->buffer_logical) {
2009		fStack->FreeChunk(descriptor->buffer_logical,
2010			descriptor->buffer_page_byte_0, descriptor->buffer_size);
2011	}
2012
2013	fStack->FreeChunk((void *)descriptor, descriptor->physical_address,
2014		sizeof(ohci_general_td));
2015}
2016
2017
2018status_t
2019OHCI::_CreateIsochronousDescriptorChain(ohci_isochronous_td **_firstDescriptor,
2020	ohci_isochronous_td **_lastDescriptor, Transfer *transfer)
2021{
2022	Pipe *pipe = transfer->TransferPipe();
2023	usb_isochronous_data *isochronousData = transfer->IsochronousData();
2024
2025	size_t dataLength = transfer->VectorLength();
2026	size_t packet_count = isochronousData->packet_count;
2027
2028	if (packet_count == 0) {
2029		TRACE_ERROR("isochronous packet_count should not be equal to zero.");
2030		return B_BAD_VALUE;
2031	}
2032
2033	size_t packetSize = dataLength / packet_count;
2034	if (dataLength % packet_count != 0)
2035		packetSize++;
2036
2037	if (packetSize > pipe->MaxPacketSize()) {
2038		TRACE_ERROR("isochronous packetSize %ld is bigger"
2039			" than pipe MaxPacketSize %ld.", packetSize, pipe->MaxPacketSize());
2040		return B_BAD_VALUE;
2041	}
2042
2043	uint16 bandwidth = transfer->Bandwidth() / packet_count;
2044	if (transfer->Bandwidth() % packet_count != 0)
2045		bandwidth++;
2046
2047	ohci_isochronous_td *firstDescriptor = NULL;
2048	ohci_isochronous_td *lastDescriptor = *_firstDescriptor;
2049
2050	// the frame number currently processed by the host controller
2051	uint16 currentFrame = fHcca->current_frame_number & 0xFFFF;
2052	uint16 safeFrames = 5;
2053
2054	// The entry where to start inserting the first Isochronous descriptor
2055	// real frame number may differ in case provided one has not bandwidth
2056	if (isochronousData->flags & USB_ISO_ASAP ||
2057		isochronousData->starting_frame_number == NULL)
2058		// We should stay about 5-10 ms ahead of the controller
2059		// USB1 frame is equal to 1 ms
2060		currentFrame += safeFrames;
2061	else
2062		currentFrame = *isochronousData->starting_frame_number;
2063
2064	uint16 packets = packet_count;
2065	uint16 frameOffset = 0;
2066	while (packets > 0) {
2067		// look for up to 8 continous frames with available bandwidth
2068		uint16 frameCount = 0;
2069		while (frameCount < min_c(OHCI_ITD_NOFFSET, packets)
2070				&& _AllocateIsochronousBandwidth(frameOffset + currentFrame
2071					+ frameCount, bandwidth))
2072			frameCount++;
2073
2074		if (frameCount == 0) {
2075			// starting frame has no bandwidth for our transaction - try next
2076			if (++frameOffset >= 0xFFFF) {
2077				TRACE_ERROR("failed to allocate bandwidth\n");
2078				_FreeIsochronousDescriptorChain(firstDescriptor);
2079				return B_NO_MEMORY;
2080			}
2081			continue;
2082		}
2083
2084		ohci_isochronous_td *descriptor = _CreateIsochronousDescriptor(
2085				packetSize * frameCount);
2086
2087		if (!descriptor) {
2088			TRACE_ERROR("failed to allocate ITD\n");
2089			_ReleaseIsochronousBandwidth(currentFrame + frameOffset, frameCount);
2090			_FreeIsochronousDescriptorChain(firstDescriptor);
2091			return B_NO_MEMORY;
2092		}
2093
2094		uint16 pageOffset = descriptor->buffer_page_byte_0 & 0xfff;
2095		descriptor->buffer_page_byte_0 &= ~0xfff;
2096		for (uint16 i = 0; i < frameCount; i++) {
2097			descriptor->offset[OHCI_ITD_OFFSET_IDX(i)]
2098				= OHCI_ITD_MK_OFFS(pageOffset + packetSize * i);
2099		}
2100
2101		descriptor->flags = OHCI_ITD_SET_FRAME_COUNT(frameCount)
2102				| OHCI_ITD_SET_CONDITION_CODE(OHCI_ITD_CONDITION_NOT_ACCESSED)
2103				| OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_ITD_INTERRUPT_NONE)
2104				| OHCI_ITD_SET_STARTING_FRAME(currentFrame + frameOffset);
2105
2106		// the last packet may be shorter than other ones in this transfer
2107		if (packets <= OHCI_ITD_NOFFSET)
2108			descriptor->last_byte_address
2109				+= dataLength - packetSize * (packet_count);
2110
2111		// link to previous
2112		if (lastDescriptor)
2113			_LinkIsochronousDescriptors(lastDescriptor, descriptor, descriptor);
2114
2115		lastDescriptor = descriptor;
2116		if (!firstDescriptor)
2117			firstDescriptor = descriptor;
2118
2119		packets -= frameCount;
2120
2121		frameOffset += frameCount;
2122
2123		if (packets == 0 && isochronousData->starting_frame_number)
2124			*isochronousData->starting_frame_number = currentFrame + frameOffset;
2125	}
2126
2127	*_firstDescriptor = firstDescriptor;
2128	*_lastDescriptor = lastDescriptor;
2129
2130	return B_OK;
2131}
2132
2133
2134void
2135OHCI::_FreeIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor)
2136{
2137	ohci_isochronous_td *current = topDescriptor;
2138	ohci_isochronous_td *next = NULL;
2139
2140	while (current) {
2141		next = (ohci_isochronous_td *)current->next_done_descriptor;
2142		_FreeIsochronousDescriptor(current);
2143		current = next;
2144	}
2145}
2146
2147
2148size_t
2149OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
2150	size_t vectorCount)
2151{
2152	ohci_general_td *current = topDescriptor;
2153	size_t actualLength = 0;
2154	size_t vectorIndex = 0;
2155	size_t vectorOffset = 0;
2156	size_t bufferOffset = 0;
2157
2158	while (current) {
2159		if (!current->buffer_logical)
2160			break;
2161
2162		while (true) {
2163			size_t length = min_c(current->buffer_size - bufferOffset,
2164				vector[vectorIndex].iov_len - vectorOffset);
2165
2166			TRACE("copying %ld bytes to bufferOffset %ld from"
2167				" vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
2168				vectorOffset, vectorIndex, vectorCount);
2169			memcpy((uint8 *)current->buffer_logical + bufferOffset,
2170				(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
2171
2172			actualLength += length;
2173			vectorOffset += length;
2174			bufferOffset += length;
2175
2176			if (vectorOffset >= vector[vectorIndex].iov_len) {
2177				if (++vectorIndex >= vectorCount) {
2178					TRACE("wrote descriptor chain (%ld bytes, no"
2179						" more vectors)\n", actualLength);
2180					return actualLength;
2181				}
2182
2183				vectorOffset = 0;
2184			}
2185
2186			if (bufferOffset >= current->buffer_size) {
2187				bufferOffset = 0;
2188				break;
2189			}
2190		}
2191
2192		if (!current->next_logical_descriptor)
2193			break;
2194
2195		current = (ohci_general_td *)current->next_logical_descriptor;
2196	}
2197
2198	TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
2199	return actualLength;
2200}
2201
2202
2203size_t
2204OHCI::_WriteIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor,
2205	iovec *vector, size_t vectorCount)
2206{
2207	ohci_isochronous_td *current = topDescriptor;
2208	size_t actualLength = 0;
2209	size_t vectorIndex = 0;
2210	size_t vectorOffset = 0;
2211	size_t bufferOffset = 0;
2212
2213	while (current) {
2214		if (!current->buffer_logical)
2215			break;
2216
2217		while (true) {
2218			size_t length = min_c(current->buffer_size - bufferOffset,
2219				vector[vectorIndex].iov_len - vectorOffset);
2220
2221			TRACE("copying %ld bytes to bufferOffset %ld from"
2222				" vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
2223				vectorOffset, vectorIndex, vectorCount);
2224			memcpy((uint8 *)current->buffer_logical + bufferOffset,
2225				(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
2226
2227			actualLength += length;
2228			vectorOffset += length;
2229			bufferOffset += length;
2230
2231			if (vectorOffset >= vector[vectorIndex].iov_len) {
2232				if (++vectorIndex >= vectorCount) {
2233					TRACE("wrote descriptor chain (%ld bytes, no"
2234						" more vectors)\n", actualLength);
2235					return actualLength;
2236				}
2237
2238				vectorOffset = 0;
2239			}
2240
2241			if (bufferOffset >= current->buffer_size) {
2242				bufferOffset = 0;
2243				break;
2244			}
2245		}
2246
2247		if (!current->next_logical_descriptor)
2248			break;
2249
2250		current = (ohci_isochronous_td *)current->next_logical_descriptor;
2251	}
2252
2253	TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
2254	return actualLength;
2255}
2256
2257
2258size_t
2259OHCI::_ReadDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
2260	size_t vectorCount)
2261{
2262	ohci_general_td *current = topDescriptor;
2263	size_t actualLength = 0;
2264	size_t vectorIndex = 0;
2265	size_t vectorOffset = 0;
2266	size_t bufferOffset = 0;
2267
2268	while (current && OHCI_TD_GET_CONDITION_CODE(current->flags)
2269		!= OHCI_TD_CONDITION_NOT_ACCESSED) {
2270		if (!current->buffer_logical)
2271			break;
2272
2273		size_t bufferSize = current->buffer_size;
2274		if (current->buffer_physical != 0) {
2275			bufferSize -= current->last_physical_byte_address
2276				- current->buffer_physical + 1;
2277		}
2278
2279		while (true) {
2280			size_t length = min_c(bufferSize - bufferOffset,
2281				vector[vectorIndex].iov_len - vectorOffset);
2282
2283			TRACE("copying %ld bytes to vectorOffset %ld from"
2284				" bufferOffset %ld at index %ld of %ld\n", length, vectorOffset,
2285				bufferOffset, vectorIndex, vectorCount);
2286			memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
2287				(uint8 *)current->buffer_logical + bufferOffset, length);
2288
2289			actualLength += length;
2290			vectorOffset += length;
2291			bufferOffset += length;
2292
2293			if (vectorOffset >= vector[vectorIndex].iov_len) {
2294				if (++vectorIndex >= vectorCount) {
2295					TRACE("read descriptor chain (%ld bytes, no more vectors)\n",
2296						actualLength);
2297					return actualLength;
2298				}
2299
2300				vectorOffset = 0;
2301			}
2302
2303			if (bufferOffset >= bufferSize) {
2304				bufferOffset = 0;
2305				break;
2306			}
2307		}
2308
2309		current = (ohci_general_td *)current->next_logical_descriptor;
2310	}
2311
2312	TRACE("read descriptor chain (%ld bytes)\n", actualLength);
2313	return actualLength;
2314}
2315
2316
2317void
2318OHCI::_ReadIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor,
2319	iovec *vector, size_t vectorCount)
2320{
2321	ohci_isochronous_td *current = topDescriptor;
2322	size_t actualLength = 0;
2323	size_t vectorIndex = 0;
2324	size_t vectorOffset = 0;
2325	size_t bufferOffset = 0;
2326
2327	while (current && OHCI_ITD_GET_CONDITION_CODE(current->flags)
2328			!= OHCI_ITD_CONDITION_NOT_ACCESSED) {
2329		size_t bufferSize = current->buffer_size;
2330		if (current->buffer_logical != NULL && bufferSize > 0) {
2331			while (true) {
2332				size_t length = min_c(bufferSize - bufferOffset,
2333					vector[vectorIndex].iov_len - vectorOffset);
2334
2335				TRACE("copying %ld bytes to vectorOffset %ld from bufferOffset"
2336					" %ld at index %ld of %ld\n", length, vectorOffset,
2337					bufferOffset, vectorIndex, vectorCount);
2338				memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
2339					(uint8 *)current->buffer_logical + bufferOffset, length);
2340
2341				actualLength += length;
2342				vectorOffset += length;
2343				bufferOffset += length;
2344
2345				if (vectorOffset >= vector[vectorIndex].iov_len) {
2346					if (++vectorIndex >= vectorCount) {
2347						TRACE("read descriptor chain (%ld bytes, "
2348							"no more vectors)\n", actualLength);
2349						return;
2350					}
2351
2352					vectorOffset = 0;
2353				}
2354
2355				if (bufferOffset >= bufferSize) {
2356					bufferOffset = 0;
2357					break;
2358				}
2359			}
2360		}
2361
2362		current = (ohci_isochronous_td *)current->next_done_descriptor;
2363	}
2364
2365	TRACE("read descriptor chain (%ld bytes)\n", actualLength);
2366	return;
2367}
2368
2369
2370size_t
2371OHCI::_ReadActualLength(ohci_general_td *topDescriptor)
2372{
2373	ohci_general_td *current = topDescriptor;
2374	size_t actualLength = 0;
2375
2376	while (current && OHCI_TD_GET_CONDITION_CODE(current->flags)
2377		!= OHCI_TD_CONDITION_NOT_ACCESSED) {
2378		size_t length = current->buffer_size;
2379		if (current->buffer_physical != 0) {
2380			length -= current->last_physical_byte_address
2381				- current->buffer_physical + 1;
2382		}
2383
2384		actualLength += length;
2385		current = (ohci_general_td *)current->next_logical_descriptor;
2386	}
2387
2388	TRACE("read actual length (%ld bytes)\n", actualLength);
2389	return actualLength;
2390}
2391
2392
2393void
2394OHCI::_LinkDescriptors(ohci_general_td *first, ohci_general_td *second)
2395{
2396	first->next_physical_descriptor = second->physical_address;
2397	first->next_logical_descriptor = second;
2398}
2399
2400
2401void
2402OHCI::_LinkIsochronousDescriptors(ohci_isochronous_td *first,
2403	ohci_isochronous_td *second, ohci_isochronous_td *nextDone)
2404{
2405	first->next_physical_descriptor = second->physical_address;
2406	first->next_logical_descriptor = second;
2407	first->next_done_descriptor = nextDone;
2408}
2409
2410
2411bool
2412OHCI::_AllocateIsochronousBandwidth(uint16 frame, uint16 size)
2413{
2414	frame %= NUMBER_OF_FRAMES;
2415	if (size > fFrameBandwidth[frame])
2416		return false;
2417
2418	fFrameBandwidth[frame]-= size;
2419	return true;
2420}
2421
2422
2423void
2424OHCI::_ReleaseIsochronousBandwidth(uint16 startFrame, uint16 frameCount)
2425{
2426	for (size_t index = 0; index < frameCount; index++) {
2427		uint16 frame = (startFrame + index) % NUMBER_OF_FRAMES;
2428		fFrameBandwidth[frame] = MAX_AVAILABLE_BANDWIDTH;
2429	}
2430}
2431
2432
2433status_t
2434OHCI::_GetStatusOfConditionCode(uint8 conditionCode)
2435{
2436	switch (conditionCode) {
2437		case OHCI_TD_CONDITION_NO_ERROR:
2438			return B_OK;
2439
2440		case OHCI_TD_CONDITION_CRC_ERROR:
2441		case OHCI_TD_CONDITION_BIT_STUFFING:
2442		case OHCI_TD_CONDITION_TOGGLE_MISMATCH:
2443			return B_DEV_CRC_ERROR;
2444
2445		case OHCI_TD_CONDITION_STALL:
2446			return B_DEV_STALLED;
2447
2448		case OHCI_TD_CONDITION_NO_RESPONSE:
2449			return B_TIMED_OUT;
2450
2451		case OHCI_TD_CONDITION_PID_CHECK_FAILURE:
2452			return B_DEV_BAD_PID;
2453
2454		case OHCI_TD_CONDITION_UNEXPECTED_PID:
2455			return B_DEV_UNEXPECTED_PID;
2456
2457		case OHCI_TD_CONDITION_DATA_OVERRUN:
2458			return B_DEV_DATA_OVERRUN;
2459
2460		case OHCI_TD_CONDITION_DATA_UNDERRUN:
2461			return B_DEV_DATA_UNDERRUN;
2462
2463		case OHCI_TD_CONDITION_BUFFER_OVERRUN:
2464			return B_DEV_FIFO_OVERRUN;
2465
2466		case OHCI_TD_CONDITION_BUFFER_UNDERRUN:
2467			return B_DEV_FIFO_UNDERRUN;
2468
2469		case OHCI_TD_CONDITION_NOT_ACCESSED:
2470			return B_DEV_PENDING;
2471
2472		case 0x0E:
2473			return B_DEV_TOO_LATE; // PSW: _NOT_ACCESSED
2474
2475		default:
2476			break;
2477	}
2478
2479	return B_ERROR;
2480}
2481
2482
2483bool
2484OHCI::_LockEndpoints()
2485{
2486	return (mutex_lock(&fEndpointLock) == B_OK);
2487}
2488
2489
2490void
2491OHCI::_UnlockEndpoints()
2492{
2493	mutex_unlock(&fEndpointLock);
2494}
2495
2496
2497inline void
2498OHCI::_WriteReg(uint32 reg, uint32 value)
2499{
2500	*(volatile uint32 *)(fOperationalRegisters + reg) = value;
2501}
2502
2503
2504inline uint32
2505OHCI::_ReadReg(uint32 reg)
2506{
2507	return *(volatile uint32 *)(fOperationalRegisters + reg);
2508}
2509
2510
2511void
2512OHCI::_PrintEndpoint(ohci_endpoint_descriptor *endpoint)
2513{
2514	dprintf("endpoint %p\n", endpoint);
2515	dprintf("\tflags........... 0x%08" B_PRIx32 "\n", endpoint->flags);
2516	dprintf("\ttail_physical... 0x%08" B_PRIx32 "\n", endpoint->tail_physical_descriptor);
2517	dprintf("\thead_physical... 0x%08" B_PRIx32 "\n", endpoint->head_physical_descriptor);
2518	dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", endpoint->next_physical_endpoint);
2519	dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", endpoint->physical_address);
2520	dprintf("\ttail_logical.... %p\n", endpoint->tail_logical_descriptor);
2521	dprintf("\tnext_logical.... %p\n", endpoint->next_logical_endpoint);
2522}
2523
2524
2525void
2526OHCI::_PrintDescriptorChain(ohci_general_td *topDescriptor)
2527{
2528	while (topDescriptor) {
2529		dprintf("descriptor %p\n", topDescriptor);
2530		dprintf("\tflags........... 0x%08" B_PRIx32 "\n", topDescriptor->flags);
2531		dprintf("\tbuffer_physical. 0x%08" B_PRIx32 "\n", topDescriptor->buffer_physical);
2532		dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", topDescriptor->next_physical_descriptor);
2533		dprintf("\tlast_byte....... 0x%08" B_PRIx32 "\n", topDescriptor->last_physical_byte_address);
2534		dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", topDescriptor->physical_address);
2535		dprintf("\tbuffer_size..... %lu\n", topDescriptor->buffer_size);
2536		dprintf("\tbuffer_logical.. %p\n", topDescriptor->buffer_logical);
2537		dprintf("\tnext_logical.... %p\n", topDescriptor->next_logical_descriptor);
2538
2539		topDescriptor = (ohci_general_td *)topDescriptor->next_logical_descriptor;
2540	}
2541}
2542
2543
2544void
2545OHCI::_PrintDescriptorChain(ohci_isochronous_td *topDescriptor)
2546{
2547	while (topDescriptor) {
2548		dprintf("iso.descriptor %p\n", topDescriptor);
2549		dprintf("\tflags........... 0x%08" B_PRIx32 "\n", topDescriptor->flags);
2550		dprintf("\tbuffer_pagebyte0 0x%08" B_PRIx32 "\n", topDescriptor->buffer_page_byte_0);
2551		dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", topDescriptor->next_physical_descriptor);
2552		dprintf("\tlast_byte....... 0x%08" B_PRIx32 "\n", topDescriptor->last_byte_address);
2553		dprintf("\toffset:\n\t0x%04x 0x%04x 0x%04x 0x%04x\n"
2554							"\t0x%04x 0x%04x 0x%04x 0x%04x\n",
2555				topDescriptor->offset[0], topDescriptor->offset[1],
2556				topDescriptor->offset[2], topDescriptor->offset[3],
2557				topDescriptor->offset[4], topDescriptor->offset[5],
2558				topDescriptor->offset[6], topDescriptor->offset[7]);
2559		dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", topDescriptor->physical_address);
2560		dprintf("\tbuffer_size..... %lu\n", topDescriptor->buffer_size);
2561		dprintf("\tbuffer_logical.. %p\n", topDescriptor->buffer_logical);
2562		dprintf("\tnext_logical.... %p\n", topDescriptor->next_logical_descriptor);
2563		dprintf("\tnext_done....... %p\n", topDescriptor->next_done_descriptor);
2564
2565		topDescriptor = (ohci_isochronous_td *)topDescriptor->next_done_descriptor;
2566	}
2567}
2568
2569