* Fixed setting configurations (need to use the configuration_value instead of the index of course)
* Fixed reported power status of the UHCI Root Hub * Added preservation of the SOF_MODIFY register when doing a global reset of the UHC * Read out the actual length for outgoing transfers too * Made actual length handling for transfers a bit safer and correct in respect to NULL packets * Use short packet detect to handle short packets * First step at implementing the hub interrupt Since the devices are now configured correctly, some bulk transfers actually work. Also my hub now reports its status correctly. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18506 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -325,7 +325,7 @@ Device::SetConfigurationAt(uint8 index)
|
|||||||
status_t result = SendRequest(
|
status_t result = SendRequest(
|
||||||
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
|
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
|
||||||
USB_REQUEST_SET_CONFIGURATION, // request
|
USB_REQUEST_SET_CONFIGURATION, // request
|
||||||
index, // value
|
fConfigurations[index].descr->configuration_value, // value
|
||||||
0, // index
|
0, // index
|
||||||
0, // length
|
0, // length
|
||||||
NULL, // buffer
|
NULL, // buffer
|
||||||
|
|||||||
@@ -34,27 +34,8 @@ Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc,
|
|||||||
for (int32 i = 0; i < 8; i++)
|
for (int32 i = 0; i < 8; i++)
|
||||||
fChildren[i] = NULL;
|
fChildren[i] = NULL;
|
||||||
|
|
||||||
if (fDeviceDescriptor.device_class != 9
|
if (fDeviceDescriptor.device_class != 9) {
|
||||||
|| fDeviceDescriptor.device_subclass != 0
|
TRACE(("USB Hub: wrong class! Bailing out\n"));
|
||||||
|| fDeviceDescriptor.device_protocol != 0) {
|
|
||||||
TRACE(("USB Hub: wrong class/subclass/protocol! Bailing out\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Configuration()->descr->number_interfaces > 1) {
|
|
||||||
TRACE(("USB Hub: too many interfaces\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fInterruptInterface = Configuration()->interface->active->descr;
|
|
||||||
if (fInterruptInterface->num_endpoints > 1) {
|
|
||||||
TRACE(("USB Hub: too many endpoints\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fInterruptEndpoint = Configuration()->interface->active->endpoint[0].descr;
|
|
||||||
if (fInterruptEndpoint->attributes != 0x03) { // interrupt endpoint
|
|
||||||
TRACE(("USB Hub: Not an interrupt endpoint\n"));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +59,19 @@ Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc,
|
|||||||
TRACE(("\tdevice_removeable:...0x%02x\n", fHubDescriptor.device_removeable));
|
TRACE(("\tdevice_removeable:...0x%02x\n", fHubDescriptor.device_removeable));
|
||||||
TRACE(("\tpower_control_mask:..0x%02x\n", fHubDescriptor.power_control_mask));
|
TRACE(("\tpower_control_mask:..0x%02x\n", fHubDescriptor.power_control_mask));
|
||||||
|
|
||||||
|
Pipe *pipe = (Pipe *)Configuration()->interface->active->endpoint[0].handle;
|
||||||
|
if (!pipe || pipe->Type() != Pipe::Interrupt) {
|
||||||
|
TRACE(("USB Hub: no interrupt pipe found\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fInterruptPipe = (InterruptPipe *)pipe;
|
||||||
|
fInterruptPipe->QueueInterrupt(fInterruptStatus, sizeof(fInterruptStatus),
|
||||||
|
InterruptCallback, this);
|
||||||
|
|
||||||
|
// Wait some time before powering up the ports
|
||||||
|
snooze(USB_DELAY_HUB_POWER_UP);
|
||||||
|
|
||||||
// Enable port power on all ports
|
// Enable port power on all ports
|
||||||
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
|
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
|
||||||
status = SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
status = SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
||||||
@@ -167,6 +161,9 @@ Hub::Explore()
|
|||||||
if (result < B_OK)
|
if (result < B_OK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (DeviceAddress() > 1)
|
||||||
|
TRACE(("USB Hub (%d): port %d: status: 0x%04x; change: 0x%04x\n", DeviceAddress(), i, fPortStatus[i].status, fPortStatus[i].change));
|
||||||
|
|
||||||
if (fPortStatus[i].change & PORT_STATUS_CONNECTION) {
|
if (fPortStatus[i].change & PORT_STATUS_CONNECTION) {
|
||||||
if (fPortStatus[i].status & PORT_STATUS_CONNECTION) {
|
if (fPortStatus[i].status & PORT_STATUS_CONNECTION) {
|
||||||
// new device attached!
|
// new device attached!
|
||||||
@@ -230,6 +227,14 @@ Hub::Explore()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Hub::InterruptCallback(void *cookie, uint32 status, void *data,
|
||||||
|
uint32 actualLength)
|
||||||
|
{
|
||||||
|
TRACE(("USB Hub: interrupt callback!\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
|
Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
|
||||||
void *data, size_t dataLength, size_t *actualLength)
|
void *data, size_t dataLength, size_t *actualLength)
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ Transfer::Transfer(Pipe *pipe, bool synchronous)
|
|||||||
: fPipe(pipe),
|
: fPipe(pipe),
|
||||||
fData(NULL),
|
fData(NULL),
|
||||||
fDataLength(0),
|
fDataLength(0),
|
||||||
fActualLength(NULL),
|
fActualLengthPointer(NULL),
|
||||||
fOwnActualLength(0),
|
fActualLength(0),
|
||||||
fStatus(B_USB_STATUS_DRIVER_INTERNAL_ERROR),
|
fStatus(B_USB_STATUS_DRIVER_INTERNAL_ERROR),
|
||||||
fCallback(NULL),
|
fCallback(NULL),
|
||||||
fCallbackCookie(NULL),
|
fCallbackCookie(NULL),
|
||||||
@@ -22,7 +22,6 @@ Transfer::Transfer(Pipe *pipe, bool synchronous)
|
|||||||
fHostPrivate(NULL),
|
fHostPrivate(NULL),
|
||||||
fRequestData(NULL)
|
fRequestData(NULL)
|
||||||
{
|
{
|
||||||
fActualLength = &fOwnActualLength;
|
|
||||||
if (synchronous) {
|
if (synchronous) {
|
||||||
fSem = create_sem(0, "USB Transfer");
|
fSem = create_sem(0, "USB Transfer");
|
||||||
set_sem_owner(fSem, B_SYSTEM_TEAM);
|
set_sem_owner(fSem, B_SYSTEM_TEAM);
|
||||||
@@ -55,7 +54,7 @@ Transfer::SetData(uint8 *data, size_t dataLength)
|
|||||||
void
|
void
|
||||||
Transfer::SetActualLength(size_t *actualLength)
|
Transfer::SetActualLength(size_t *actualLength)
|
||||||
{
|
{
|
||||||
fActualLength = actualLength;
|
fActualLengthPointer = actualLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -92,13 +91,16 @@ Transfer::WaitForFinish()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Transfer::Finished(uint32 status)
|
Transfer::Finished(uint32 status, size_t actualLength)
|
||||||
{
|
{
|
||||||
fStatus = status;
|
fStatus = status;
|
||||||
|
fActualLength = actualLength;
|
||||||
|
if (fActualLengthPointer)
|
||||||
|
*fActualLengthPointer = actualLength;
|
||||||
|
|
||||||
// Call the callback function ...
|
// Call the callback function ...
|
||||||
if (fCallback) {
|
if (fCallback) {
|
||||||
fCallback(fCallbackCookie, fStatus, fData, *fActualLength);
|
fCallback(fCallbackCookie, fStatus, fData, fActualLength);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -361,6 +361,9 @@ virtual status_t GetDescriptor(uint8 descriptorType,
|
|||||||
status_t UpdatePortStatus(uint8 index);
|
status_t UpdatePortStatus(uint8 index);
|
||||||
status_t ResetPort(uint8 index);
|
status_t ResetPort(uint8 index);
|
||||||
void Explore();
|
void Explore();
|
||||||
|
static void InterruptCallback(void *cookie,
|
||||||
|
uint32 status, void *data,
|
||||||
|
uint32 actualLength);
|
||||||
|
|
||||||
virtual void ReportDevice(
|
virtual void ReportDevice(
|
||||||
usb_support_descriptor *supportDescriptors,
|
usb_support_descriptor *supportDescriptors,
|
||||||
@@ -369,10 +372,10 @@ virtual void ReportDevice(
|
|||||||
bool added);
|
bool added);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
usb_interface_descriptor *fInterruptInterface;
|
InterruptPipe *fInterruptPipe;
|
||||||
usb_endpoint_descriptor *fInterruptEndpoint;
|
|
||||||
usb_hub_descriptor fHubDescriptor;
|
usb_hub_descriptor fHubDescriptor;
|
||||||
|
|
||||||
|
usb_port_status fInterruptStatus[8];
|
||||||
usb_port_status fPortStatus[8];
|
usb_port_status fPortStatus[8];
|
||||||
Device *fChildren[8];
|
Device *fChildren[8];
|
||||||
};
|
};
|
||||||
@@ -405,7 +408,7 @@ public:
|
|||||||
size_t DataLength() { return fDataLength; };
|
size_t DataLength() { return fDataLength; };
|
||||||
|
|
||||||
void SetActualLength(size_t *actualLength);
|
void SetActualLength(size_t *actualLength);
|
||||||
size_t *ActualLength() { return fActualLength; };
|
size_t *ActualLength() { return fActualLengthPointer; };
|
||||||
|
|
||||||
void SetHostPrivate(hostcontroller_priv *priv);
|
void SetHostPrivate(hostcontroller_priv *priv);
|
||||||
hostcontroller_priv *HostPrivate() { return fHostPrivate; };
|
hostcontroller_priv *HostPrivate() { return fHostPrivate; };
|
||||||
@@ -414,15 +417,15 @@ public:
|
|||||||
void *cookie);
|
void *cookie);
|
||||||
|
|
||||||
status_t WaitForFinish();
|
status_t WaitForFinish();
|
||||||
void Finished(uint32 status);
|
void Finished(uint32 status, size_t actualLength);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Data that is related to the transfer
|
// Data that is related to the transfer
|
||||||
Pipe *fPipe;
|
Pipe *fPipe;
|
||||||
uint8 *fData;
|
uint8 *fData;
|
||||||
size_t fDataLength;
|
size_t fDataLength;
|
||||||
size_t *fActualLength;
|
size_t *fActualLengthPointer;
|
||||||
size_t fOwnActualLength;
|
size_t fActualLength;
|
||||||
uint32 fStatus;
|
uint32 fStatus;
|
||||||
|
|
||||||
usb_callback_func fCallback;
|
usb_callback_func fCallback;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#define USB_MAX_AREAS 8
|
#define USB_MAX_AREAS 8
|
||||||
|
|
||||||
#define USB_DELAY_DEVICE_POWER_UP 300000
|
#define USB_DELAY_DEVICE_POWER_UP 300000
|
||||||
|
#define USB_DELAY_HUB_POWER_UP 200000
|
||||||
#define USB_DELAY_PORT_RESET 50000
|
#define USB_DELAY_PORT_RESET 50000
|
||||||
#define USB_DELAY_PORT_RESET_RECOVERY 250000
|
#define USB_DELAY_PORT_RESET_RECOVERY 250000
|
||||||
#define USB_DELAY_SET_ADDRESS_RETRY 200000
|
#define USB_DELAY_SET_ADDRESS_RETRY 200000
|
||||||
|
|||||||
@@ -751,31 +751,37 @@ UHCI::FinishTransfers()
|
|||||||
transfer->queue->RemoveDescriptorChain(
|
transfer->queue->RemoveDescriptorChain(
|
||||||
transfer->first_descriptor,
|
transfer->first_descriptor,
|
||||||
transfer->last_descriptor);
|
transfer->last_descriptor);
|
||||||
|
|
||||||
FreeDescriptorChain(transfer->first_descriptor);
|
FreeDescriptorChain(transfer->first_descriptor);
|
||||||
transfer->transfer->Finished(callbackStatus);
|
transfer->transfer->Finished(callbackStatus, 0);
|
||||||
transferDone = true;
|
transferDone = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor == transfer->last_descriptor) {
|
// either all descriptors are done, or we have a short packet
|
||||||
|
if (descriptor == transfer->last_descriptor
|
||||||
|
|| (descriptor->status & TD_STATUS_ACTLEN_MASK)
|
||||||
|
< (descriptor->token >> TD_TOKEN_MAXLEN_SHIFT)) {
|
||||||
TRACE(("usb_uhci: td (0x%08x) ok\n", descriptor->this_phy));
|
TRACE(("usb_uhci: td (0x%08x) ok\n", descriptor->this_phy));
|
||||||
// we got through without errors so we are finished
|
// we got through without errors so we are finished
|
||||||
transfer->queue->RemoveDescriptorChain(
|
transfer->queue->RemoveDescriptorChain(
|
||||||
transfer->first_descriptor,
|
transfer->first_descriptor,
|
||||||
transfer->last_descriptor);
|
transfer->last_descriptor);
|
||||||
|
|
||||||
|
size_t length = 0;
|
||||||
if (transfer->data_descriptor && transfer->incoming) {
|
if (transfer->data_descriptor && transfer->incoming) {
|
||||||
// data to read out
|
// data to read out
|
||||||
size_t length = ReadDescriptorChain(
|
length = ReadDescriptorChain(
|
||||||
transfer->data_descriptor,
|
transfer->data_descriptor,
|
||||||
transfer->transfer->Data(),
|
transfer->transfer->Data(),
|
||||||
transfer->transfer->DataLength());
|
transfer->transfer->DataLength());
|
||||||
|
} else {
|
||||||
*(transfer->transfer->ActualLength()) = length;
|
// read the actual length that was sent
|
||||||
|
length = ReadActualLength(transfer->first_descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeDescriptorChain(transfer->first_descriptor);
|
FreeDescriptorChain(transfer->first_descriptor);
|
||||||
transfer->transfer->Finished(B_OK);
|
transfer->transfer->Finished(B_USB_STATUS_SUCCESS, length);
|
||||||
transferDone = true;
|
transferDone = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -813,10 +819,14 @@ UHCI::FinishTransfers()
|
|||||||
void
|
void
|
||||||
UHCI::GlobalReset()
|
UHCI::GlobalReset()
|
||||||
{
|
{
|
||||||
|
uint8 sofValue = ReadReg8(UHCI_SOFMOD);
|
||||||
|
|
||||||
WriteReg16(UHCI_USBCMD, UHCI_USBCMD_GRESET);
|
WriteReg16(UHCI_USBCMD, UHCI_USBCMD_GRESET);
|
||||||
snooze(100000);
|
snooze(100000);
|
||||||
WriteReg16(UHCI_USBCMD, 0);
|
WriteReg16(UHCI_USBCMD, 0);
|
||||||
snooze(10000);
|
snooze(10000);
|
||||||
|
|
||||||
|
WriteReg8(UHCI_SOFMOD, sofValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1077,7 +1087,7 @@ UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, int32 bufferSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
result->this_phy = (addr_t)physicalAddress;
|
result->this_phy = (addr_t)physicalAddress;
|
||||||
result->status = TD_STATUS_ACTIVE | TD_CONTROL_3_ERRORS;
|
result->status = TD_STATUS_ACTIVE | TD_CONTROL_3_ERRORS | TD_CONTROL_SPD;
|
||||||
if (pipe->Speed() == Pipe::LowSpeed)
|
if (pipe->Speed() == Pipe::LowSpeed)
|
||||||
result->status |= TD_CONTROL_LOWSPEED;
|
result->status |= TD_CONTROL_LOWSPEED;
|
||||||
|
|
||||||
@@ -1188,20 +1198,20 @@ UHCI::LinkDescriptors(uhci_td *first, uhci_td *second)
|
|||||||
|
|
||||||
size_t
|
size_t
|
||||||
UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer,
|
UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer,
|
||||||
int32 bufferSize)
|
size_t bufferLength)
|
||||||
{
|
{
|
||||||
size_t actualSize = 0;
|
size_t actualLength = 0;
|
||||||
uhci_td *current = topDescriptor;
|
uhci_td *current = topDescriptor;
|
||||||
|
|
||||||
while (current) {
|
while (current) {
|
||||||
if (!current->buffer_log)
|
if (!current->buffer_log)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
int32 length = min_c(current->buffer_size, bufferSize);
|
size_t length = min_c(current->buffer_size, bufferLength);
|
||||||
memcpy(current->buffer_log, buffer, length);
|
memcpy(current->buffer_log, buffer, length);
|
||||||
|
|
||||||
bufferSize -= length;
|
bufferLength -= length;
|
||||||
actualSize += length;
|
actualLength += length;
|
||||||
buffer += length;
|
buffer += length;
|
||||||
|
|
||||||
if (current->link_phy & TD_TERMINATE)
|
if (current->link_phy & TD_TERMINATE)
|
||||||
@@ -1210,31 +1220,31 @@ UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer,
|
|||||||
current = (uhci_td *)current->link_log;
|
current = (uhci_td *)current->link_log;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("usb_uhci: wrote descriptor chain (%d bytes)\n", actualSize));
|
TRACE(("usb_uhci: wrote descriptor chain (%d bytes)\n", actualLength));
|
||||||
return actualSize;
|
return actualLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
|
UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
|
||||||
int32 bufferSize)
|
size_t bufferLength)
|
||||||
{
|
{
|
||||||
size_t actualSize = 0;
|
size_t actualLength = 0;
|
||||||
uhci_td *current = topDescriptor;
|
uhci_td *current = topDescriptor;
|
||||||
|
|
||||||
while (current) {
|
while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
|
||||||
if (!current->buffer_log)
|
if (!current->buffer_log)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
int32 length = (current->status & TD_STATUS_ACTLEN_MASK) + 1;
|
size_t length = (current->status & TD_STATUS_ACTLEN_MASK) + 1;
|
||||||
if (length == TD_STATUS_ACTLEN_NULL + 1)
|
if (length == TD_STATUS_ACTLEN_NULL + 1)
|
||||||
length = 0;
|
length = 0;
|
||||||
|
|
||||||
length = min_c(length, bufferSize);
|
length = min_c(length, bufferLength);
|
||||||
memcpy(buffer, current->buffer_log, length);
|
memcpy(buffer, current->buffer_log, length);
|
||||||
|
|
||||||
bufferSize -= length;
|
bufferLength -= length;
|
||||||
actualSize += length;
|
actualLength += length;
|
||||||
buffer += length;
|
buffer += length;
|
||||||
|
|
||||||
if (current->link_phy & TD_TERMINATE)
|
if (current->link_phy & TD_TERMINATE)
|
||||||
@@ -1243,8 +1253,39 @@ UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
|
|||||||
current = (uhci_td *)current->link_log;
|
current = (uhci_td *)current->link_log;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("usb_uhci: read descriptor chain (%d bytes)\n", actualSize));
|
TRACE(("usb_uhci: read descriptor chain (%d bytes)\n", actualLength));
|
||||||
return actualSize;
|
return actualLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
UHCI::ReadActualLength(uhci_td *topDescriptor)
|
||||||
|
{
|
||||||
|
size_t actualLength = 0;
|
||||||
|
uhci_td *current = topDescriptor;
|
||||||
|
|
||||||
|
while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
|
||||||
|
TRACE(("usb_uhci: reading actual length from status 0x%08x\n", current->status));
|
||||||
|
size_t length = (current->status & TD_STATUS_ACTLEN_MASK) + 1;
|
||||||
|
if (length == TD_STATUS_ACTLEN_NULL + 1)
|
||||||
|
length = 0;
|
||||||
|
|
||||||
|
actualLength += length;
|
||||||
|
if (current->link_phy & TD_TERMINATE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
current = (uhci_td *)current->link_log;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE(("usb_uhci: read actual length (%d bytes)\n", actualLength));
|
||||||
|
return actualLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
UHCI::WriteReg8(uint32 reg, uint8 value)
|
||||||
|
{
|
||||||
|
sPCIModule->write_io_8(fRegisterBase + reg, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1262,6 +1303,13 @@ UHCI::WriteReg32(uint32 reg, uint32 value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint8
|
||||||
|
UHCI::ReadReg8(uint32 reg)
|
||||||
|
{
|
||||||
|
return sPCIModule->read_io_8(fRegisterBase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline uint16
|
inline uint16
|
||||||
UHCI::ReadReg16(uint32 reg)
|
UHCI::ReadReg16(uint32 reg)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -119,13 +119,16 @@ static int32 FinishThread(void *data);
|
|||||||
uhci_td *second);
|
uhci_td *second);
|
||||||
|
|
||||||
size_t WriteDescriptorChain(uhci_td *topDescriptor,
|
size_t WriteDescriptorChain(uhci_td *topDescriptor,
|
||||||
const uint8 *buffer, int32 bufferSize);
|
const uint8 *buffer, size_t bufferLength);
|
||||||
size_t ReadDescriptorChain(uhci_td *topDescriptor,
|
size_t ReadDescriptorChain(uhci_td *topDescriptor,
|
||||||
uint8 *buffer, int32 bufferSize);
|
uint8 *buffer, size_t bufferLength);
|
||||||
|
size_t ReadActualLength(uhci_td *topDescriptor);
|
||||||
|
|
||||||
// Register functions
|
// Register functions
|
||||||
|
inline void WriteReg8(uint32 reg, uint8 value);
|
||||||
inline void WriteReg16(uint32 reg, uint16 value);
|
inline void WriteReg16(uint32 reg, uint16 value);
|
||||||
inline void WriteReg32(uint32 reg, uint32 value);
|
inline void WriteReg32(uint32 reg, uint32 value);
|
||||||
|
inline uint8 ReadReg8(uint32 reg);
|
||||||
inline uint16 ReadReg16(uint32 reg);
|
inline uint16 ReadReg16(uint32 reg);
|
||||||
inline uint32 ReadReg32(uint32 reg);
|
inline uint32 ReadReg32(uint32 reg);
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ typedef struct
|
|||||||
} uhci_td;
|
} uhci_td;
|
||||||
|
|
||||||
// Control and Status
|
// Control and Status
|
||||||
#define TD_CONTROL_SHORT_PACKET (1 << 29)
|
#define TD_CONTROL_SPD (1 << 29)
|
||||||
#define TD_CONTROL_3_ERRORS (3 << 27)
|
#define TD_CONTROL_3_ERRORS (3 << 27)
|
||||||
#define TD_CONTROL_LOWSPEED (1 << 26)
|
#define TD_CONTROL_LOWSPEED (1 << 26)
|
||||||
#define TD_CONTROL_ISOCHRONOUS (1 << 25)
|
#define TD_CONTROL_ISOCHRONOUS (1 << 25)
|
||||||
@@ -110,7 +110,7 @@ typedef struct
|
|||||||
#define TD_STATUS_ERROR_TIMEOUT (1 << 18)
|
#define TD_STATUS_ERROR_TIMEOUT (1 << 18)
|
||||||
#define TD_STATUS_ERROR_BITSTUFF (1 << 17)
|
#define TD_STATUS_ERROR_BITSTUFF (1 << 17)
|
||||||
|
|
||||||
#define TD_STATUS_ACTLEN_MASK 0x03ff
|
#define TD_STATUS_ACTLEN_MASK 0x07ff
|
||||||
#define TD_STATUS_ACTLEN_NULL 0x07ff
|
#define TD_STATUS_ACTLEN_NULL 0x07ff
|
||||||
|
|
||||||
// Token
|
// Token
|
||||||
|
|||||||
@@ -135,9 +135,13 @@ UHCIRootHub::UHCIRootHub(UHCI *uhci, int8 devicenum)
|
|||||||
status_t
|
status_t
|
||||||
UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||||
{
|
{
|
||||||
|
if (transfer->TransferPipe()->Type() != Pipe::Control)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
usb_request_data *request = transfer->RequestData();
|
usb_request_data *request = transfer->RequestData();
|
||||||
TRACE(("usb_uhci_roothub: rh_submit_packet called. request: %u\n", request->Request));
|
TRACE(("usb_uhci_roothub: rh_submit_packet called. request: %u\n", request->Request));
|
||||||
|
|
||||||
|
size_t actualLength = 0;
|
||||||
status_t result = B_ERROR;
|
status_t result = B_ERROR;
|
||||||
switch (request->Request) {
|
switch (request->Request) {
|
||||||
case RH_GET_STATUS: {
|
case RH_GET_STATUS: {
|
||||||
@@ -155,11 +159,9 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
// Get port status
|
// Get port status
|
||||||
UpdatePortStatus();
|
UpdatePortStatus();
|
||||||
|
|
||||||
size_t length = MIN(4, transfer->DataLength());
|
actualLength = MIN(4, transfer->DataLength());
|
||||||
memcpy(transfer->Data(),
|
memcpy(transfer->Data(),
|
||||||
(void *)&fPortStatus[request->Index - 1], length);
|
(void *)&fPortStatus[request->Index - 1], actualLength);
|
||||||
|
|
||||||
*(transfer->ActualLength()) = length;
|
|
||||||
result = B_OK;
|
result = B_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -179,21 +181,19 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
|
|
||||||
switch (request->Value & 0xff00) {
|
switch (request->Value & 0xff00) {
|
||||||
case RH_DEVICE_DESCRIPTOR: {
|
case RH_DEVICE_DESCRIPTOR: {
|
||||||
size_t length = MIN(sizeof(usb_device_descriptor),
|
actualLength = MIN(sizeof(usb_device_descriptor),
|
||||||
transfer->DataLength());
|
transfer->DataLength());
|
||||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice,
|
memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice,
|
||||||
length);
|
actualLength);
|
||||||
*(transfer->ActualLength()) = length;
|
|
||||||
result = B_OK;
|
result = B_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RH_CONFIG_DESCRIPTOR: {
|
case RH_CONFIG_DESCRIPTOR: {
|
||||||
size_t length = MIN(sizeof(uhci_root_hub_configuration_s),
|
actualLength = MIN(sizeof(uhci_root_hub_configuration_s),
|
||||||
transfer->DataLength());
|
transfer->DataLength());
|
||||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig,
|
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig,
|
||||||
length);
|
actualLength);
|
||||||
*(transfer->ActualLength()) = length;
|
|
||||||
result = B_OK;
|
result = B_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -201,26 +201,23 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
case RH_STRING_DESCRIPTOR: {
|
case RH_STRING_DESCRIPTOR: {
|
||||||
uint8 index = request->Value & 0x00ff;
|
uint8 index = request->Value & 0x00ff;
|
||||||
if (index > 2) {
|
if (index > 2) {
|
||||||
*(transfer->ActualLength()) = 0;
|
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t length = MIN(sUHCIRootHubStrings[index].length,
|
actualLength = MIN(sUHCIRootHubStrings[index].length,
|
||||||
transfer->DataLength());
|
transfer->DataLength());
|
||||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index],
|
memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index],
|
||||||
length);
|
actualLength);
|
||||||
*(transfer->ActualLength()) = length;
|
|
||||||
result = B_OK;
|
result = B_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RH_HUB_DESCRIPTOR: {
|
case RH_HUB_DESCRIPTOR: {
|
||||||
size_t length = MIN(sizeof(usb_hub_descriptor),
|
actualLength = MIN(sizeof(usb_hub_descriptor),
|
||||||
transfer->DataLength());
|
transfer->DataLength());
|
||||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub,
|
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub,
|
||||||
length);
|
actualLength);
|
||||||
*(transfer->ActualLength()) = length;
|
|
||||||
result = B_OK;
|
result = B_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -304,7 +301,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer->Finished(result);
|
transfer->Finished(result, actualLength);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +337,7 @@ UHCIRootHub::UpdatePortStatus()
|
|||||||
newChange |= PORT_STATUS_RESET;
|
newChange |= PORT_STATUS_RESET;
|
||||||
|
|
||||||
//The port is automagically powered on
|
//The port is automagically powered on
|
||||||
newStatus |= PORT_POWER;
|
newStatus |= PORT_STATUS_POWER;
|
||||||
|
|
||||||
if (portStatus & UHCI_PORTSC_LOWSPEED)
|
if (portStatus & UHCI_PORTSC_LOWSPEED)
|
||||||
newStatus |= PORT_STATUS_LOW_SPEED;
|
newStatus |= PORT_STATUS_LOW_SPEED;
|
||||||
|
|||||||
Reference in New Issue
Block a user