* Remove SubmitAsyncTransfer and SubmitPeriodicTransfer

* Added _SubmitControlRequest (almost implemented), _LinkDescriptors, _WriteDescriptorChain (basically copied from EHCI, and UHCI)
* Renamed ohci_general_descriptor to ohci_general_td, and ohci_isochronous_descriptor to ohci_isochronous_td
* Finished _CreateGeneralDescriptor and _FreeGeneralDescriptor
* Added buffer_size member to ohci_general_td instead and removed last_logical_byte_address as it looked unnecessary
* minor clean up


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22968 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Salvatore Benedetto 2007-11-20 22:16:42 +00:00
parent 1dec1e5786
commit 01489ae060
3 changed files with 208 additions and 33 deletions

View File

@ -410,14 +410,19 @@ OHCI::SubmitTransfer(Transfer *transfer)
return fRootHub->ProcessTransfer(this, transfer); return fRootHub->ProcessTransfer(this, transfer);
uint32 type = transfer->TransferPipe()->Type(); uint32 type = transfer->TransferPipe()->Type();
if ((type & USB_OBJECT_CONTROL_PIPE) || (type & USB_OBJECT_BULK_PIPE)) { if ((type & USB_OBJECT_CONTROL_PIPE)) {
TRACE(("usb_ohci: submitting async transfer\n")); TRACE(("usb_ohci: submitting control request\n"));
return _SubmitAsyncTransfer(transfer); return _SubmitControlRequest(transfer);
} }
if ((type & USB_OBJECT_INTERRUPT_PIPE) || (type & USB_OBJECT_ISO_PIPE)) { if ((type & USB_OBJECT_INTERRUPT_PIPE) || (type & USB_OBJECT_BULK_PIPE)) {
TRACE(("usb_ohci: submitting periodic transfer\n")); // TODO
return _SubmitPeriodicTransfer(transfer); return B_OK;
}
if ((type & USB_OBJECT_ISO_PIPE)) {
TRACE(("usb_ohci: submitting isochronous transfer\n"));
return _SubmitIsochronousTransfer(transfer);
} }
TRACE_ERROR(("usb_ohci: tried to submit transfer for unknown pipe" TRACE_ERROR(("usb_ohci: tried to submit transfer for unknown pipe"
@ -427,19 +432,152 @@ OHCI::SubmitTransfer(Transfer *transfer)
status_t status_t
OHCI::_SubmitAsyncTransfer(Transfer *transfer) OHCI::_SubmitControlRequest(Transfer *transfer)
{
usb_request_data *requestData = transfer->RequestData();
bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0;
ohci_general_td *setupDescriptor
= _CreateGeneralDescriptor(sizeof(usb_request_data));
if (!setupDescriptor) {
TRACE_ERROR(("usb_ohci: failed to allocate setup descriptor\n"));
return B_NO_MEMORY;
}
// Flags set up could be moved into _CreateGeneralDescriptor
setupDescriptor->flags |= OHCI_TD_DIRECTION_PID_SETUP
| OHCI_TD_NO_CONDITION_CODE
| OHCI_TD_TOGGLE_0
| OHCI_TD_SET_DELAY_INTERRUPT(6); // Not sure about this.
ohci_general_td *statusDescriptor
= _CreateGeneralDescriptor(0);
if (!statusDescriptor) {
TRACE_ERROR(("usb_ohci: failed to allocate status descriptor\n"));
_FreeGeneralDescriptor(setupDescriptor);
return B_NO_MEMORY;
}
statusDescriptor->flags
|= (directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN)
| OHCI_TD_NO_CONDITION_CODE
| OHCI_TD_TOGGLE_1
| OHCI_TD_SET_DELAY_INTERRUPT(1);
iovec vector;
vector.iov_base = requestData;
vector.iov_len = sizeof(usb_request_data);
_WriteDescriptorChain(setupDescriptor, &vector, 1);
if (transfer->VectorCount() > 0) {
ohci_general_td *dataDescriptor = NULL;
ohci_general_td *lastDescriptor = NULL;
status_t result = _CreateDescriptorChain(&dataDescriptor,
&lastDescriptor,
directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN,
transfer->VectorLength());
if (result < B_OK) {
_FreeGeneralDescriptor(setupDescriptor);
_FreeGeneralDescriptor(statusDescriptor);
return result;
}
if (!directionIn) {
_WriteDescriptorChain(dataDescriptor, transfer->Vector(),
transfer->VectorCount());
}
_LinkDescriptors(setupDescriptor, dataDescriptor);
_LinkDescriptors(lastDescriptor, statusDescriptor);
} else {
_LinkDescriptors(setupDescriptor, statusDescriptor);
}
// TODO
// 1. Insert the chain descriptors to the endpoint
// 2. Clear the Skip bit in the enpoint
_WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED);
return B_OK;
}
status_t
OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
{ {
return B_ERROR; return B_ERROR;
} }
void
OHCI::_LinkDescriptors(ohci_general_td *first, ohci_general_td *second)
{
first->next_physical_descriptor = second->physical_address;
first->next_logical_descriptor = second;
}
status_t status_t
OHCI::_SubmitPeriodicTransfer(Transfer *transfer) OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor,
ohci_general_td **_lastDescriptor, uint8 direction, size_t bufferSize)
{ {
return B_ERROR; return B_ERROR;
} }
size_t
OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
size_t vectorCount)
{
ohci_general_td *current = topDescriptor;
size_t actualLength = 0;
size_t vectorIndex = 0;
size_t vectorOffset = 0;
size_t bufferOffset = 0;
while (current) {
if (!current->buffer_logical)
break;
while (true) {
size_t length = min_c(current->buffer_size - bufferOffset,
vector[vectorIndex].iov_len - vectorOffset);
TRACE(("usb_ohci: copying %ld bytes to bufferOffset %ld from"
" vectorOffset %ld at index %ld of %ld\n", length, bufferOffset,
vectorOffset, vectorIndex, vectorCount));
memcpy((uint8 *)current->buffer_logical + bufferOffset,
(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
actualLength += length;
vectorOffset += length;
bufferOffset += length;
if (vectorOffset >= vector[vectorIndex].iov_len) {
if (++vectorIndex >= vectorCount) {
TRACE(("usb_ohci: wrote descriptor chain (%ld bytes, no"
" more vectors)\n", actualLength));
return actualLength;
}
vectorOffset = 0;
}
if (bufferOffset >= current->buffer_size) {
bufferOffset = 0;
break;
}
}
if (!current->next_logical_descriptor)
break;
current = (ohci_general_td *)current->next_logical_descriptor;
}
TRACE(("usb_ohci: wrote descriptor chain (%ld bytes)\n", actualLength));
return actualLength;
}
status_t status_t
OHCI::NotifyPipeChange(Pipe *pipe, usb_change change) OHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
{ {
@ -665,34 +803,54 @@ OHCI::_FreeEndpoint(ohci_endpoint_descriptor *endpoint)
} }
ohci_general_descriptor* ohci_general_td*
OHCI::_CreateGeneralDescriptor() OHCI::_CreateGeneralDescriptor(size_t bufferSize)
{ {
ohci_general_descriptor *descriptor; ohci_general_td *descriptor;
void *physicalAddress; void *physicalAddress;
if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress, if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
sizeof(ohci_general_descriptor)) != B_OK) { sizeof(ohci_general_td)) != B_OK) {
TRACE_ERROR(("usb_ohci: failed to allocate general descriptor\n")); TRACE_ERROR(("usb_ohci: failed to allocate general descriptor\n"));
return NULL; return NULL;
} }
memset((void *)descriptor, 0, sizeof(ohci_general_td));
// TODO: Finish methods
memset((void *)descriptor, 0, sizeof(ohci_general_descriptor));
descriptor->physical_address = (addr_t)physicalAddress; descriptor->physical_address = (addr_t)physicalAddress;
if (!bufferSize) {
descriptor->buffer_physical = 0;
descriptor->buffer_logical = NULL;
descriptor->last_physical_byte_address = 0;
return descriptor;
}
if (fStack->AllocateChunk(&descriptor->buffer_logical,
(void **)&descriptor->buffer_physical, bufferSize) != B_OK) {
TRACE_ERROR(("usb_ohci: failed to allocate space for buffer\n"));
fStack->FreeChunk(descriptor, (void *)descriptor->physical_address,
sizeof(ohci_general_td));
return NULL;
}
descriptor->last_physical_byte_address
= descriptor->buffer_physical + bufferSize - 1;
return descriptor; return descriptor;
} }
void void
OHCI::_FreeGeneralDescriptor(ohci_general_descriptor *descriptor) OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor)
{ {
if (!descriptor) if (!descriptor)
return; return;
if (descriptor->buffer_logical) {
fStack->FreeChunk(descriptor->buffer_logical,
(void *)descriptor->buffer_physical, descriptor->buffer_size);
}
fStack->FreeChunk((void *)descriptor, (void *)descriptor->physical_address, fStack->FreeChunk((void *)descriptor, (void *)descriptor->physical_address,
sizeof(ohci_general_descriptor)); sizeof(ohci_general_td));
} }

View File

@ -31,7 +31,7 @@ typedef struct transfer_data_s {
// -------------------------------------- // --------------------------------------
typedef struct hcd_soft_itransfer typedef struct hcd_soft_itransfer
{ {
ohci_isochronous_descriptor itd; ohci_isochronous_td itd;
struct hcd_soft_itransfer *nextitd; // mirrors nexttd in ITD struct hcd_soft_itransfer *nextitd; // mirrors nexttd in ITD
struct hcd_soft_itransfer *dnext; // next in done list struct hcd_soft_itransfer *dnext; // next in done list
addr_t physaddr; // physical address to the host controller isonchronous transfer addr_t physaddr; // physical address to the host controller isonchronous transfer
@ -83,26 +83,43 @@ static int32 _InterruptHandler(void *data);
static int32 _FinishThread(void *data); static int32 _FinishThread(void *data);
void _FinishTransfer(); void _FinishTransfer();
status_t _SubmitAsyncTransfer(Transfer *transfer); status_t _SubmitControlRequest(Transfer *transfer);
status_t _SubmitPeriodicTransfer(Transfer *transfer); status_t _SubmitIsochronousTransfer(
Transfer *transfer);
// Endpoint related methods // Endpoint related methods
status_t _InsertEndpointForPipe(Pipe *pipe);
status_t _RemoveEndpointForPipe(Pipe *pipe);
status_t _CreateEndpoint(Pipe *pipe,
bool isIsochronous);
ohci_endpoint_descriptor *_FindInterruptEndpoint(uint8 interval);
ohci_endpoint_descriptor *_AllocateEndpoint(); ohci_endpoint_descriptor *_AllocateEndpoint();
void _FreeEndpoint( void _FreeEndpoint(
ohci_endpoint_descriptor *endpoint); ohci_endpoint_descriptor *endpoint);
status_t _InsertEndpointForPipe(Pipe *pipe);
status_t _RemoveEndpointForPipe(Pipe *pipe);
ohci_endpoint_descriptor *_FindInterruptEndpoint(uint8 interval);
// Transfer descriptor related methods // Transfer descriptor related methods
ohci_general_descriptor *_CreateGeneralDescriptor(); ohci_general_td *_CreateGeneralDescriptor(
size_t bufferSize);
status_t _CreateDescriptorChain(
ohci_general_td **firstDescriptor,
ohci_general_td **lastDescriptor,
uint8 direction,
size_t bufferSize);
void _FreeGeneralDescriptor( void _FreeGeneralDescriptor(
ohci_general_descriptor *descriptor); ohci_general_td *descriptor);
ohci_isochronous_descriptor *_CreateIsochronousDescriptor(); void _FreeDescriptorChain(
ohci_general_td *topDescriptor);
void _LinkDescriptors(ohci_general_td *first,
ohci_general_td *second);
ohci_isochronous_td *_CreateIsochronousDescriptor();
void _FreeIsochronousDescriptor( void _FreeIsochronousDescriptor(
ohci_isochronous_descriptor *descriptor); ohci_isochronous_td *descriptor);
size_t _WriteDescriptorChain(
ohci_general_td *topDescriptor,
iovec *vector,
size_t vectorCount);
// Register functions // Register functions
inline void _WriteReg(uint32 reg, uint32 value); inline void _WriteReg(uint32 reg, uint32 value);

View File

@ -333,7 +333,7 @@ typedef struct ohci_endpoint_descriptor
// General transfer descriptor structure (section 4.3.1) // General transfer descriptor structure (section 4.3.1)
// -------------------------------- // --------------------------------
typedef struct ohci_general_descriptor typedef struct ohci_general_td
{ {
// Hardware part // Hardware part
uint32 flags; // Flags field uint32 flags; // Flags field
@ -344,7 +344,7 @@ typedef struct ohci_general_descriptor
addr_t physical_address; // Physical pointer to this address addr_t physical_address; // Physical pointer to this address
void *buffer_logical; // Logical pointer to the buffer void *buffer_logical; // Logical pointer to the buffer
void *next_logical_descriptor; // Logical pointer next descriptor void *next_logical_descriptor; // Logical pointer next descriptor
void *last_logical_byte_address; // Logical pointer buffer end size_t buffer_size; // Size of the buffer
}; };
#define OHCI_BUFFER_ROUNDING 0x00040000 #define OHCI_BUFFER_ROUNDING 0x00040000
@ -371,7 +371,7 @@ typedef struct ohci_general_descriptor
// -------------------------------- // --------------------------------
#define OHCI_ITD_NOFFSET 8 #define OHCI_ITD_NOFFSET 8
typedef struct ohci_isochronous_descriptor typedef struct ohci_isochronous_td
{ {
uint32 flags; uint32 flags;
uint32 buffer_page_byte_0; // Physical page number of byte 0 uint32 buffer_page_byte_0; // Physical page number of byte 0