mirror of
https://review.haiku-os.org/haiku
synced 2025-01-22 06:16:03 +01:00
* 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:
parent
bfb0aa18d3
commit
d83f3c1a45
@ -325,7 +325,7 @@ Device::SetConfigurationAt(uint8 index)
|
||||
status_t result = SendRequest(
|
||||
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
|
||||
USB_REQUEST_SET_CONFIGURATION, // request
|
||||
index, // value
|
||||
fConfigurations[index].descr->configuration_value, // value
|
||||
0, // index
|
||||
0, // length
|
||||
NULL, // buffer
|
||||
|
@ -34,27 +34,8 @@ Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc,
|
||||
for (int32 i = 0; i < 8; i++)
|
||||
fChildren[i] = NULL;
|
||||
|
||||
if (fDeviceDescriptor.device_class != 9
|
||||
|| fDeviceDescriptor.device_subclass != 0
|
||||
|| 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"));
|
||||
if (fDeviceDescriptor.device_class != 9) {
|
||||
TRACE(("USB Hub: wrong class! Bailing out\n"));
|
||||
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(("\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
|
||||
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
|
||||
status = SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
||||
@ -167,6 +161,9 @@ Hub::Explore()
|
||||
if (result < B_OK)
|
||||
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].status & PORT_STATUS_CONNECTION) {
|
||||
// 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
|
||||
Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
|
||||
void *data, size_t dataLength, size_t *actualLength)
|
||||
|
@ -13,8 +13,8 @@ Transfer::Transfer(Pipe *pipe, bool synchronous)
|
||||
: fPipe(pipe),
|
||||
fData(NULL),
|
||||
fDataLength(0),
|
||||
fActualLength(NULL),
|
||||
fOwnActualLength(0),
|
||||
fActualLengthPointer(NULL),
|
||||
fActualLength(0),
|
||||
fStatus(B_USB_STATUS_DRIVER_INTERNAL_ERROR),
|
||||
fCallback(NULL),
|
||||
fCallbackCookie(NULL),
|
||||
@ -22,7 +22,6 @@ Transfer::Transfer(Pipe *pipe, bool synchronous)
|
||||
fHostPrivate(NULL),
|
||||
fRequestData(NULL)
|
||||
{
|
||||
fActualLength = &fOwnActualLength;
|
||||
if (synchronous) {
|
||||
fSem = create_sem(0, "USB Transfer");
|
||||
set_sem_owner(fSem, B_SYSTEM_TEAM);
|
||||
@ -55,7 +54,7 @@ Transfer::SetData(uint8 *data, size_t dataLength)
|
||||
void
|
||||
Transfer::SetActualLength(size_t *actualLength)
|
||||
{
|
||||
fActualLength = actualLength;
|
||||
fActualLengthPointer = actualLength;
|
||||
}
|
||||
|
||||
|
||||
@ -92,13 +91,16 @@ Transfer::WaitForFinish()
|
||||
|
||||
|
||||
void
|
||||
Transfer::Finished(uint32 status)
|
||||
Transfer::Finished(uint32 status, size_t actualLength)
|
||||
{
|
||||
fStatus = status;
|
||||
fActualLength = actualLength;
|
||||
if (fActualLengthPointer)
|
||||
*fActualLengthPointer = actualLength;
|
||||
|
||||
// Call the callback function ...
|
||||
if (fCallback) {
|
||||
fCallback(fCallbackCookie, fStatus, fData, *fActualLength);
|
||||
fCallback(fCallbackCookie, fStatus, fData, fActualLength);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -361,6 +361,9 @@ virtual status_t GetDescriptor(uint8 descriptorType,
|
||||
status_t UpdatePortStatus(uint8 index);
|
||||
status_t ResetPort(uint8 index);
|
||||
void Explore();
|
||||
static void InterruptCallback(void *cookie,
|
||||
uint32 status, void *data,
|
||||
uint32 actualLength);
|
||||
|
||||
virtual void ReportDevice(
|
||||
usb_support_descriptor *supportDescriptors,
|
||||
@ -369,10 +372,10 @@ virtual void ReportDevice(
|
||||
bool added);
|
||||
|
||||
private:
|
||||
usb_interface_descriptor *fInterruptInterface;
|
||||
usb_endpoint_descriptor *fInterruptEndpoint;
|
||||
InterruptPipe *fInterruptPipe;
|
||||
usb_hub_descriptor fHubDescriptor;
|
||||
|
||||
usb_port_status fInterruptStatus[8];
|
||||
usb_port_status fPortStatus[8];
|
||||
Device *fChildren[8];
|
||||
};
|
||||
@ -405,7 +408,7 @@ public:
|
||||
size_t DataLength() { return fDataLength; };
|
||||
|
||||
void SetActualLength(size_t *actualLength);
|
||||
size_t *ActualLength() { return fActualLength; };
|
||||
size_t *ActualLength() { return fActualLengthPointer; };
|
||||
|
||||
void SetHostPrivate(hostcontroller_priv *priv);
|
||||
hostcontroller_priv *HostPrivate() { return fHostPrivate; };
|
||||
@ -414,15 +417,15 @@ public:
|
||||
void *cookie);
|
||||
|
||||
status_t WaitForFinish();
|
||||
void Finished(uint32 status);
|
||||
void Finished(uint32 status, size_t actualLength);
|
||||
|
||||
private:
|
||||
// Data that is related to the transfer
|
||||
Pipe *fPipe;
|
||||
uint8 *fData;
|
||||
size_t fDataLength;
|
||||
size_t *fActualLength;
|
||||
size_t fOwnActualLength;
|
||||
size_t *fActualLengthPointer;
|
||||
size_t fActualLength;
|
||||
uint32 fStatus;
|
||||
|
||||
usb_callback_func fCallback;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define USB_MAX_AREAS 8
|
||||
|
||||
#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_RECOVERY 250000
|
||||
#define USB_DELAY_SET_ADDRESS_RETRY 200000
|
||||
|
@ -751,31 +751,37 @@ UHCI::FinishTransfers()
|
||||
transfer->queue->RemoveDescriptorChain(
|
||||
transfer->first_descriptor,
|
||||
transfer->last_descriptor);
|
||||
|
||||
FreeDescriptorChain(transfer->first_descriptor);
|
||||
transfer->transfer->Finished(callbackStatus);
|
||||
transfer->transfer->Finished(callbackStatus, 0);
|
||||
transferDone = true;
|
||||
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));
|
||||
// we got through without errors so we are finished
|
||||
transfer->queue->RemoveDescriptorChain(
|
||||
transfer->first_descriptor,
|
||||
transfer->last_descriptor);
|
||||
|
||||
size_t length = 0;
|
||||
if (transfer->data_descriptor && transfer->incoming) {
|
||||
// data to read out
|
||||
size_t length = ReadDescriptorChain(
|
||||
length = ReadDescriptorChain(
|
||||
transfer->data_descriptor,
|
||||
transfer->transfer->Data(),
|
||||
transfer->transfer->DataLength());
|
||||
|
||||
*(transfer->transfer->ActualLength()) = length;
|
||||
} else {
|
||||
// read the actual length that was sent
|
||||
length = ReadActualLength(transfer->first_descriptor);
|
||||
}
|
||||
|
||||
FreeDescriptorChain(transfer->first_descriptor);
|
||||
transfer->transfer->Finished(B_OK);
|
||||
transfer->transfer->Finished(B_USB_STATUS_SUCCESS, length);
|
||||
transferDone = true;
|
||||
break;
|
||||
}
|
||||
@ -813,10 +819,14 @@ UHCI::FinishTransfers()
|
||||
void
|
||||
UHCI::GlobalReset()
|
||||
{
|
||||
uint8 sofValue = ReadReg8(UHCI_SOFMOD);
|
||||
|
||||
WriteReg16(UHCI_USBCMD, UHCI_USBCMD_GRESET);
|
||||
snooze(100000);
|
||||
WriteReg16(UHCI_USBCMD, 0);
|
||||
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->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)
|
||||
result->status |= TD_CONTROL_LOWSPEED;
|
||||
|
||||
@ -1188,20 +1198,20 @@ UHCI::LinkDescriptors(uhci_td *first, uhci_td *second)
|
||||
|
||||
size_t
|
||||
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;
|
||||
|
||||
while (current) {
|
||||
if (!current->buffer_log)
|
||||
break;
|
||||
|
||||
int32 length = min_c(current->buffer_size, bufferSize);
|
||||
size_t length = min_c(current->buffer_size, bufferLength);
|
||||
memcpy(current->buffer_log, buffer, length);
|
||||
|
||||
bufferSize -= length;
|
||||
actualSize += length;
|
||||
bufferLength -= length;
|
||||
actualLength += length;
|
||||
buffer += length;
|
||||
|
||||
if (current->link_phy & TD_TERMINATE)
|
||||
@ -1210,31 +1220,31 @@ UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer,
|
||||
current = (uhci_td *)current->link_log;
|
||||
}
|
||||
|
||||
TRACE(("usb_uhci: wrote descriptor chain (%d bytes)\n", actualSize));
|
||||
return actualSize;
|
||||
TRACE(("usb_uhci: wrote descriptor chain (%d bytes)\n", actualLength));
|
||||
return actualLength;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
|
||||
int32 bufferSize)
|
||||
size_t bufferLength)
|
||||
{
|
||||
size_t actualSize = 0;
|
||||
size_t actualLength = 0;
|
||||
uhci_td *current = topDescriptor;
|
||||
|
||||
while (current) {
|
||||
while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
|
||||
if (!current->buffer_log)
|
||||
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)
|
||||
length = 0;
|
||||
|
||||
length = min_c(length, bufferSize);
|
||||
length = min_c(length, bufferLength);
|
||||
memcpy(buffer, current->buffer_log, length);
|
||||
|
||||
bufferSize -= length;
|
||||
actualSize += length;
|
||||
bufferLength -= length;
|
||||
actualLength += length;
|
||||
buffer += length;
|
||||
|
||||
if (current->link_phy & TD_TERMINATE)
|
||||
@ -1243,8 +1253,39 @@ UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
|
||||
current = (uhci_td *)current->link_log;
|
||||
}
|
||||
|
||||
TRACE(("usb_uhci: read descriptor chain (%d bytes)\n", actualSize));
|
||||
return actualSize;
|
||||
TRACE(("usb_uhci: read descriptor chain (%d bytes)\n", actualLength));
|
||||
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
|
||||
UHCI::ReadReg16(uint32 reg)
|
||||
{
|
||||
|
@ -119,13 +119,16 @@ static int32 FinishThread(void *data);
|
||||
uhci_td *second);
|
||||
|
||||
size_t WriteDescriptorChain(uhci_td *topDescriptor,
|
||||
const uint8 *buffer, int32 bufferSize);
|
||||
const uint8 *buffer, size_t bufferLength);
|
||||
size_t ReadDescriptorChain(uhci_td *topDescriptor,
|
||||
uint8 *buffer, int32 bufferSize);
|
||||
uint8 *buffer, size_t bufferLength);
|
||||
size_t ReadActualLength(uhci_td *topDescriptor);
|
||||
|
||||
// Register functions
|
||||
inline void WriteReg8(uint32 reg, uint8 value);
|
||||
inline void WriteReg16(uint32 reg, uint16 value);
|
||||
inline void WriteReg32(uint32 reg, uint32 value);
|
||||
inline uint8 ReadReg8(uint32 reg);
|
||||
inline uint16 ReadReg16(uint32 reg);
|
||||
inline uint32 ReadReg32(uint32 reg);
|
||||
|
||||
|
@ -95,7 +95,7 @@ typedef struct
|
||||
} uhci_td;
|
||||
|
||||
// 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_LOWSPEED (1 << 26)
|
||||
#define TD_CONTROL_ISOCHRONOUS (1 << 25)
|
||||
@ -110,7 +110,7 @@ typedef struct
|
||||
#define TD_STATUS_ERROR_TIMEOUT (1 << 18)
|
||||
#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
|
||||
|
||||
// Token
|
||||
|
@ -135,9 +135,13 @@ UHCIRootHub::UHCIRootHub(UHCI *uhci, int8 devicenum)
|
||||
status_t
|
||||
UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
{
|
||||
if (transfer->TransferPipe()->Type() != Pipe::Control)
|
||||
return B_ERROR;
|
||||
|
||||
usb_request_data *request = transfer->RequestData();
|
||||
TRACE(("usb_uhci_roothub: rh_submit_packet called. request: %u\n", request->Request));
|
||||
|
||||
size_t actualLength = 0;
|
||||
status_t result = B_ERROR;
|
||||
switch (request->Request) {
|
||||
case RH_GET_STATUS: {
|
||||
@ -155,11 +159,9 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
// Get port status
|
||||
UpdatePortStatus();
|
||||
|
||||
size_t length = MIN(4, transfer->DataLength());
|
||||
actualLength = MIN(4, transfer->DataLength());
|
||||
memcpy(transfer->Data(),
|
||||
(void *)&fPortStatus[request->Index - 1], length);
|
||||
|
||||
*(transfer->ActualLength()) = length;
|
||||
(void *)&fPortStatus[request->Index - 1], actualLength);
|
||||
result = B_OK;
|
||||
break;
|
||||
}
|
||||
@ -179,21 +181,19 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
|
||||
switch (request->Value & 0xff00) {
|
||||
case RH_DEVICE_DESCRIPTOR: {
|
||||
size_t length = MIN(sizeof(usb_device_descriptor),
|
||||
actualLength = MIN(sizeof(usb_device_descriptor),
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice,
|
||||
length);
|
||||
*(transfer->ActualLength()) = length;
|
||||
actualLength);
|
||||
result = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
case RH_CONFIG_DESCRIPTOR: {
|
||||
size_t length = MIN(sizeof(uhci_root_hub_configuration_s),
|
||||
actualLength = MIN(sizeof(uhci_root_hub_configuration_s),
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig,
|
||||
length);
|
||||
*(transfer->ActualLength()) = length;
|
||||
actualLength);
|
||||
result = B_OK;
|
||||
break;
|
||||
}
|
||||
@ -201,26 +201,23 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
case RH_STRING_DESCRIPTOR: {
|
||||
uint8 index = request->Value & 0x00ff;
|
||||
if (index > 2) {
|
||||
*(transfer->ActualLength()) = 0;
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t length = MIN(sUHCIRootHubStrings[index].length,
|
||||
actualLength = MIN(sUHCIRootHubStrings[index].length,
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index],
|
||||
length);
|
||||
*(transfer->ActualLength()) = length;
|
||||
actualLength);
|
||||
result = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
case RH_HUB_DESCRIPTOR: {
|
||||
size_t length = MIN(sizeof(usb_hub_descriptor),
|
||||
actualLength = MIN(sizeof(usb_hub_descriptor),
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub,
|
||||
length);
|
||||
*(transfer->ActualLength()) = length;
|
||||
actualLength);
|
||||
result = B_OK;
|
||||
break;
|
||||
}
|
||||
@ -304,7 +301,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
break;
|
||||
}
|
||||
|
||||
transfer->Finished(result);
|
||||
transfer->Finished(result, actualLength);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -340,7 +337,7 @@ UHCIRootHub::UpdatePortStatus()
|
||||
newChange |= PORT_STATUS_RESET;
|
||||
|
||||
//The port is automagically powered on
|
||||
newStatus |= PORT_POWER;
|
||||
newStatus |= PORT_STATUS_POWER;
|
||||
|
||||
if (portStatus & UHCI_PORTSC_LOWSPEED)
|
||||
newStatus |= PORT_STATUS_LOW_SPEED;
|
||||
|
Loading…
x
Reference in New Issue
Block a user