* Changed the Stack lock to a benaphore

* Removed some debug output from UHCI
* Added some debug output to the usb module instead ;)
* Rewrote the way new devices are attached and ports are handled (now more similar to FreeBSD)
* Corrected handling of port resets so that they should work on hubs too
* Cleaned up some headers

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18499 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2006-08-12 21:07:34 +00:00
parent 8be9a75c4e
commit f1020a6c49
12 changed files with 380 additions and 249 deletions
@@ -74,10 +74,10 @@ BusManager::ExploreThread(void *data)
if (!rootHub)
return B_ERROR;
snooze(3000000);
snooze(USB_DELAY_FIRST_EXPLORE);
while (true) {
rootHub->Explore();
snooze(1000000);
snooze(USB_DELAY_HUB_EXPLORE);
}
return B_OK;
@@ -98,16 +98,24 @@ BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
ControlPipe *defaultPipe = (lowSpeed ? fDefaultPipeLowSpeed : fDefaultPipe);
// Set the address of the device USB 1.1 spec p202
status_t result = defaultPipe->SendRequest(
USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT, // type
USB_REQUEST_SET_ADDRESS, // request
deviceAddress, // value
0, // index
0, // length
NULL, // buffer
0, // buffer length
NULL); // actual length
status_t result = B_ERROR;
for (int32 i = 0; i < 15; i++) {
// Set the address of the device USB 1.1 spec p202
result = defaultPipe->SendRequest(
USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT, // type
USB_REQUEST_SET_ADDRESS, // request
deviceAddress, // value
0, // index
0, // length
NULL, // buffer
0, // buffer length
NULL); // actual length
if (result >= B_OK)
break;
snooze(USB_DELAY_SET_ADDRESS_RETRY);
}
if (result < B_OK) {
TRACE(("usb BusManager::AllocateNewDevice(): error while setting device address\n"));
@@ -115,7 +123,7 @@ BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
}
// Wait a bit for the device to complete addressing
snooze(10000);
snooze(USB_DELAY_SET_ADDRESS);
// Create a temporary pipe with the new address
ControlPipe pipe(this, deviceAddress,
@@ -339,7 +339,7 @@ Device::SetConfigurationAt(uint8 index)
fCurrentConfiguration = &fConfigurations[index];
// Wait some for the configuration being finished
snooze(10000);
snooze(USB_DELAY_SET_CONFIGURATION);
return B_OK;
}
+124 -66
View File
@@ -62,91 +62,146 @@ Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc,
size_t actualLength;
status_t status = GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0,
(void *)&fHubDescriptor, sizeof(usb_hub_descriptor), &actualLength);
if (status < B_OK || actualLength != sizeof(usb_hub_descriptor)) {
// we need at least 8 bytes
if (status < B_OK || actualLength < 8) {
TRACE(("USB Hub: Error getting hub descriptor\n"));
return;
}
TRACE(("USB Hub: Hub descriptor (%d bytes):\n", actualLength));
TRACE(("\tlength:..............%d\n", fHubDescriptor.length));
TRACE(("\tdescriptor_type:.....0x%02x\n", fHubDescriptor.descriptor_type));
TRACE(("\tnum_ports:...........%d\n", fHubDescriptor.num_ports));
TRACE(("\tcharacteristics:.....0x%04x\n", fHubDescriptor.characteristics));
TRACE(("\tpower_on_to_power_g:.%d\n", fHubDescriptor.power_on_to_power_good));
TRACE(("\tdevice_removeable:...0x%02x\n", fHubDescriptor.device_removeable));
TRACE(("\tpower_control_mask:..0x%02x\n", fHubDescriptor.power_control_mask));
// Enable port power on all ports
for (int32 i = 0; i < fHubDescriptor.bNbrPorts; i++) {
SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_SET_FEATURE,
PORT_POWER,
i + 1,
0,
NULL,
0,
&actualLength);
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
status = SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_SET_FEATURE, PORT_POWER, i + 1, 0, NULL, 0, NULL);
if (status < B_OK)
TRACE(("USB Hub: power up failed on port %d\n", i));
}
// Wait for power to stabilize
snooze(fHubDescriptor.bPwrOn2PwrGood * 2000);
snooze(fHubDescriptor.power_on_to_power_good * 2000);
fInitOK = true;
TRACE(("USB Hub: initialised ok\n"));
}
status_t
Hub::UpdatePortStatus(uint8 index)
{
// get the current port status
size_t actualLength = 0;
status_t result = SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN,
USB_REQUEST_GET_STATUS, 0, index + 1, 4, (void *)&fPortStatus[index],
4, &actualLength);
if (result < B_OK || actualLength < 4) {
TRACE(("USB Hub: error updating port status\n"));
return B_ERROR;
}
return B_OK;
}
status_t
Hub::ResetPort(uint8 index)
{
status_t result = SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_SET_FEATURE, PORT_RESET, index + 1, 0, NULL, 0, NULL);
if (result < B_OK)
return result;
for (int32 i = 0; i < 10; i++) {
snooze(USB_DELAY_PORT_RESET);
result = UpdatePortStatus(index);
if (result < B_OK)
return result;
if ((fPortStatus[index].status & PORT_STATUS_CONNECTION) == 0) {
// device disappeared, this is no error
TRACE(("USB Hub: device disappeared on reset\n"));
return B_OK;
}
if (fPortStatus[index].change & C_PORT_RESET) {
// reset is done
break;
}
}
if ((fPortStatus[index].change & C_PORT_RESET) == 0) {
TRACE(("USB Hub: port %d won't reset\n", index));
return B_ERROR;
}
// clear the reset change
result = SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, index + 1, 0, NULL, 0, NULL);
if (result < B_OK)
return result;
// wait for reset recovery
snooze(USB_DELAY_PORT_RESET_RECOVERY);
TRACE(("USB Hub: port %d was reset successfully\n", index));
return B_OK;
}
void
Hub::Explore()
{
for (int32 i = 0; i < fHubDescriptor.bNbrPorts; i++) {
size_t actualLength;
// Get the current port status
SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN,
USB_REQUEST_GET_STATUS,
0,
i + 1,
4,
(void *)&fPortStatus[i],
4,
&actualLength);
if (actualLength < 4) {
TRACE(("USB Hub: error getting port status\n"));
return;
}
//TRACE(("status: 0x%04x; change: 0x%04x\n", fPortStatus[i].status, fPortStatus[i].change));
// We need to test the port change against a number of things
if (fPortStatus[i].status & PORT_RESET) {
SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_CLEAR_FEATURE,
PORT_RESET,
i + 1,
0,
NULL,
0,
&actualLength);
}
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
status_t result = UpdatePortStatus(i);
if (result < B_OK)
continue;
if (fPortStatus[i].change & PORT_STATUS_CONNECTION) {
if (fPortStatus[i].status & PORT_STATUS_CONNECTION) {
// New device attached!
if ((fPortStatus[i].status & PORT_STATUS_ENABLE) == 0) {
// enable the port if it isn't
SendRequest(
USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_SET_FEATURE,
PORT_ENABLE,
i + 1,
0,
NULL,
0,
NULL);
}
// new device attached!
TRACE(("USB Hub: Explore(): New device connected\n"));
// wait some time for the device to power up
snooze(USB_DELAY_DEVICE_POWER_UP);
// reset the port, this will also enable it
result = ResetPort(i);
if (result < B_OK)
continue;
result = UpdatePortStatus(i);
if (result < B_OK)
continue;
if ((fPortStatus[i].status & PORT_STATUS_CONNECTION) == 0) {
// device has vanished after reset, ignore
continue;
}
Device *newDevice = fBus->AllocateNewDevice(this,
(fPortStatus[i].status & PORT_STATUS_LOW_SPEED) > 0);
if (newDevice) {
fChildren[i] = newDevice;
Manager()->GetStack()->NotifyDeviceChange(fChildren[i], true);
} else {
// the device failed to setup correctly, disable the port
// so that the device doesn't get in the way of future
// addressing.
SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_CLEAR_FEATURE, PORT_ENABLE, i + 1,
0, NULL, 0, NULL);
}
} else {
// Device removed...
@@ -158,17 +213,20 @@ Hub::Explore()
}
}
// Clear status change
// clear status change
SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_CLEAR_FEATURE,
C_PORT_CONNECTION,
i + 1,
0,
NULL,
0,
NULL);
USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, i + 1,
0, NULL, 0, NULL);
}
}
// explore down the tree if we have hubs connected
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
if (!fChildren[i] || !fChildren[i]->IsHub())
continue;
((Hub *)fChildren[i])->Explore();
}
}
@@ -198,7 +256,7 @@ Hub::ReportDevice(usb_support_descriptor *supportDescriptors,
Device::ReportDevice(supportDescriptors, supportDescriptorCount, hooks, added);
// Then report all of our children
for (int32 i = 0; i < fHubDescriptor.bNbrPorts; i++) {
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
if (!fChildren[i])
continue;
@@ -24,13 +24,10 @@ Stack::Stack()
{
TRACE(("usb stack: stack init\n"));
// Create the master lock
fMasterLock = create_sem(1, "usb master lock");
set_sem_owner(fMasterLock, B_SYSTEM_TEAM);
// Create the data lock
fDataLock = create_sem(1, "usb data lock");
set_sem_owner(fDataLock, B_SYSTEM_TEAM);
if (benaphore_init(&fLock, "USB Stack Master Lock") < B_OK) {
TRACE(("usb stack: failed to create benaphore lock\n"));
return;
}
// Initialise the memory chunks: create 8, 16 and 32 byte-heaps
// NOTE: This is probably the most ugly code you will see in the
@@ -149,6 +146,9 @@ Stack::Stack()
Stack::~Stack()
{
Lock();
benaphore_destroy(&fLock);
//Release the bus modules
for (Vector<BusManager *>::Iterator i = fBusManagers.Begin();
i != fBusManagers.End(); i++) {
@@ -174,14 +174,14 @@ Stack::InitCheck()
bool
Stack::Lock()
{
return (acquire_sem(fMasterLock) == B_OK);
return (benaphore_lock(&fLock) == B_OK);
}
void
Stack::Unlock()
{
release_sem(fMasterLock);
benaphore_unlock(&fLock);
}
@@ -15,7 +15,7 @@ Transfer::Transfer(Pipe *pipe, bool synchronous)
fDataLength(0),
fActualLength(NULL),
fOwnActualLength(0),
fStatus(B_NO_INIT),
fStatus(B_USB_STATUS_DRIVER_INTERNAL_ERROR),
fCallback(NULL),
fCallbackCookie(NULL),
fSem(-1),
@@ -78,22 +78,23 @@ status_t
Transfer::WaitForFinish()
{
if (fSem < B_OK)
return fStatus;
status_t result = B_OK;
result = acquire_sem(fSem);
return fSem;
status_t result = acquire_sem(fSem);
if (result < B_OK)
return result;
return fStatus;
if (fStatus == B_USB_STATUS_SUCCESS)
return B_OK;
return B_ERROR;
}
void
Transfer::Finished(status_t result)
Transfer::Finished(uint32 status)
{
fStatus = result;
fStatus = status;
// Call the callback function ...
if (fCallback) {
@@ -87,6 +87,7 @@ uninstall_notify(const char *driverName)
const usb_device_descriptor *
get_device_descriptor(const usb_device *device)
{
TRACE(("usb_module: get_device_descriptor(0x%08x)\n", device));
if (!device)
return NULL;
@@ -97,6 +98,7 @@ get_device_descriptor(const usb_device *device)
const usb_configuration_info *
get_nth_configuration(const usb_device *device, uint index)
{
TRACE(("usb_module: get_nth_configuration(0x%08x, %d)\n", device, index));
if (!device)
return NULL;
@@ -108,6 +110,7 @@ get_nth_configuration(const usb_device *device, uint index)
const usb_configuration_info *
get_configuration(const usb_device *device)
{
TRACE(("usb_module: get_configuration(0x%08x)\n", device));
if (!device)
return NULL;
@@ -119,6 +122,7 @@ status_t
set_configuration(const usb_device *device,
const usb_configuration_info *configuration)
{
TRACE(("usb_module: set_configuration(0x%08x, 0x%08x)\n", device, configuration));
if (!device)
return B_BAD_VALUE;
@@ -130,6 +134,7 @@ status_t
set_alt_interface(const usb_device *device,
const usb_interface_info *interface)
{
TRACE(("usb_module: set_alt_interface(0x%08x, 0x%08x)\n", device, interface));
return B_ERROR;
}
@@ -137,6 +142,7 @@ set_alt_interface(const usb_device *device,
status_t
set_feature(const void *object, uint16 selector)
{
TRACE(("usb_module: set_feature(0x%08x, %d)\n", object, selector));
if (!object)
return B_BAD_VALUE;
@@ -147,6 +153,7 @@ set_feature(const void *object, uint16 selector)
status_t
clear_feature(const void *object, uint16 selector)
{
TRACE(("usb_module: clear_feature(0x%08x, %d)\n", object, selector));
if (!object)
return B_BAD_VALUE;
@@ -157,6 +164,7 @@ clear_feature(const void *object, uint16 selector)
status_t
get_status(const void *object, uint16 *status)
{
TRACE(("usb_module: get_status(0x%08x, 0x%08x)\n", object, status));
if (!object || !status)
return B_BAD_VALUE;
@@ -168,6 +176,7 @@ status_t
get_descriptor(const usb_device *device, uint8 type, uint8 index,
uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
{
TRACE(("usb_module: get_descriptor(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%08x, %d, 0x%08x)\n", device, type, index, languageID, data, dataLength, actualLength));
if (!device || !data)
return B_BAD_VALUE;
@@ -181,6 +190,7 @@ send_request(const usb_device *device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data, size_t dataLength,
size_t *actualLength)
{
TRACE(("usb_module: send_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, %d, 0x%08x)\n", device, requestType, request, value, index, length, data, dataLength, actualLength));
if (!device)
return B_BAD_VALUE;
@@ -194,6 +204,7 @@ queue_request(const usb_device *device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data, size_t dataLength,
usb_callback_func callback, void *callbackCookie)
{
TRACE(("usb_module: queue_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, %d, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, dataLength, callback, callbackCookie));
if (!device)
return B_BAD_VALUE;
@@ -206,6 +217,7 @@ status_t
queue_interrupt(const usb_pipe *pipe, void *data, size_t dataLength,
usb_callback_func callback, void *callbackCookie)
{
TRACE(("usb_module: queue_interrupt(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie));
if (((Pipe *)pipe)->Type() != Pipe::Interrupt)
return B_BAD_VALUE;
@@ -218,6 +230,7 @@ status_t
queue_bulk(const usb_pipe *pipe, void *data, size_t dataLength,
usb_callback_func callback, void *callbackCookie)
{
TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie));
if (((Pipe *)pipe)->Type() != Pipe::Bulk)
return B_BAD_VALUE;
@@ -231,6 +244,7 @@ queue_isochronous(const usb_pipe *pipe, void *data, size_t dataLength,
rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
void *callbackCookie)
{
TRACE(("usb_module: queue_isochronous(0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, rleArray, bufferDurationMS, callback, callbackCookie));
if (((Pipe *)pipe)->Type() != Pipe::Isochronous)
return B_BAD_VALUE;
@@ -243,6 +257,7 @@ status_t
set_pipe_policy(const usb_pipe *pipe, uint8 maxQueuedPackets,
uint16 maxBufferDurationMS, uint16 sampleSize)
{
TRACE(("usb_module: set_pipe_policy(0x%08x, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize));
return B_ERROR;
}
@@ -250,6 +265,7 @@ set_pipe_policy(const usb_pipe *pipe, uint8 maxQueuedPackets,
status_t
cancel_queued_transfers(const usb_pipe *pipe)
{
TRACE(("usb_module: cancel_queued_transfers(0x%08x)\n", pipe));
return ((Pipe *)pipe)->CancelQueuedTransfers();
}
@@ -257,6 +273,7 @@ cancel_queued_transfers(const usb_pipe *pipe)
status_t
usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
{
TRACE(("usb_module: usb_ioctl(0x%08x, 0x%08x, %d)\n", opcode, buffer, bufferSize));
return B_ERROR;
}
+6 -5
View File
@@ -10,6 +10,7 @@
#ifndef _USB_P_
#define _USB_P_
#include <lock.h>
#include "usbspec_p.h"
@@ -76,9 +77,7 @@ public:
private:
Vector<BusManager *> fBusManagers;
sem_id fMasterLock;
sem_id fDataLock;
benaphore fLock;
area_id fAreas[USB_MAX_AREAS];
void *fLogical[USB_MAX_AREAS];
void *fPhysical[USB_MAX_AREAS];
@@ -359,6 +358,8 @@ virtual status_t GetDescriptor(uint8 descriptorType,
void *data, size_t dataLength,
size_t *actualLength);
status_t UpdatePortStatus(uint8 index);
status_t ResetPort(uint8 index);
void Explore();
virtual void ReportDevice(
@@ -413,7 +414,7 @@ public:
void *cookie);
status_t WaitForFinish();
void Finished(status_t result);
void Finished(uint32 status);
private:
// Data that is related to the transfer
@@ -422,7 +423,7 @@ private:
size_t fDataLength;
size_t *fActualLength;
size_t fOwnActualLength;
status_t fStatus;
uint32 fStatus;
usb_callback_func fCallback;
void *fCallbackCookie;
+18 -11
View File
@@ -14,9 +14,16 @@
#include <USB.h>
#include <util/kernel_cpp.h>
#define USB_MAX_AREAS 8
#define POWER_DELAY
#define USB_MAX_AREAS 8
#define USB_DELAY_DEVICE_POWER_UP 300000
#define USB_DELAY_PORT_RESET 50000
#define USB_DELAY_PORT_RESET_RECOVERY 250000
#define USB_DELAY_SET_ADDRESS_RETRY 200000
#define USB_DELAY_SET_ADDRESS 10000
#define USB_DELAY_SET_CONFIGURATION 50000
#define USB_DELAY_FIRST_EXPLORE 5000000
#define USB_DELAY_HUB_EXPLORE 1000000
/*
Important data from the USB spec (not interesting for drivers)
@@ -41,15 +48,15 @@ struct usb_request_data
struct usb_hub_descriptor
{
uint8 bDescLength;
uint8 bDescriptorType;
uint8 bNbrPorts;
uint16 wHubCharacteristics;
uint8 bPwrOn2PwrGood;
uint8 bHucContrCurrent;
uint8 DeviceRemovable; //Should be variable!!!
uint8 PortPwrCtrlMask; //Deprecated
};
uint8 length;
uint8 descriptor_type;
uint8 num_ports;
uint16 characteristics;
uint8 power_on_to_power_good;
uint8 max_power;
uint8 device_removeable; //Should be variable!!!
uint8 power_control_mask; //Deprecated
} _PACKED;
#define USB_DESCRIPTOR_HUB 0x29
+90 -70
View File
@@ -104,7 +104,7 @@ Queue::Queue(Stack *stack)
fStack = stack;
if (benaphore_init(&fLock, "uhci queue lock") < B_OK) {
TRACE(("usb_uhci: failed to create queue lock\n"));
TRACE_ERROR(("usb_uhci: failed to create queue lock\n"));
return;
}
@@ -180,7 +180,7 @@ Queue::TerminateByStrayDescriptor()
status_t result = fStack->AllocateChunk((void **)&fStrayDescriptor,
&physicalAddress, 32);
if (result < B_OK) {
TRACE(("usb_uhci: failed to allocate a stray transfer descriptor\n"));
TRACE_ERROR(("usb_uhci: failed to allocate a stray transfer descriptor\n"));
return result;
}
@@ -191,8 +191,8 @@ Queue::TerminateByStrayDescriptor()
fStrayDescriptor->buffer_phy = 0;
fStrayDescriptor->buffer_log = 0;
fStrayDescriptor->buffer_size = 0;
fStrayDescriptor->token = TD_TOKEN_NULL | (0x7f << TD_TOKEN_DEVADDR_SHIFT)
| TD_TOKEN_IN;
fStrayDescriptor->token = TD_TOKEN_NULL_DATA
| (0x7f << TD_TOKEN_DEVADDR_SHIFT) | TD_TOKEN_IN;
if (!Lock()) {
fStack->FreeChunk(fStrayDescriptor, (void *)fStrayDescriptor->this_phy,
@@ -210,9 +210,9 @@ Queue::TerminateByStrayDescriptor()
status_t
Queue::AppendDescriptor(uhci_td *descriptor)
Queue::AppendDescriptorChain(uhci_td *descriptor)
{
TRACE(("usb_uhci: appending descriptors\n"));
TRACE(("usb_uhci: appending descriptor chain\n"));
if (!Lock())
return B_ERROR;
@@ -221,7 +221,7 @@ Queue::AppendDescriptor(uhci_td *descriptor)
print_descriptor_chain(descriptor);
#endif
if (fQueueHead->element_phy & QH_TERMINATE) {
if (fQueueTop == NULL) {
// the queue is empty, make this the first element
fQueueTop = descriptor;
fQueueHead->element_phy = descriptor->this_phy;
@@ -243,17 +243,17 @@ Queue::AppendDescriptor(uhci_td *descriptor)
status_t
Queue::RemoveDescriptors(uhci_td *firstDescriptor, uhci_td *lastDescriptor)
Queue::RemoveDescriptorChain(uhci_td *firstDescriptor, uhci_td *lastDescriptor)
{
TRACE(("usb_uhci: removing descriptors\n"));
TRACE(("usb_uhci: removing descriptor chain\n"));
if (!Lock())
return B_ERROR;
if (fQueueTop == firstDescriptor) {
// it was the first chain in this queue
// it is the first chain in this queue
if ((lastDescriptor->link_phy & TD_TERMINATE) > 0) {
// it was the only transfer
// it is the only chain in this queue
fQueueTop = NULL;
fQueueHead->element_phy = QH_TERMINATE;
} else {
@@ -262,30 +262,26 @@ Queue::RemoveDescriptors(uhci_td *firstDescriptor, uhci_td *lastDescriptor)
fQueueHead->element_phy = fQueueTop->this_phy & TD_LINK_MASK;
}
} else {
uhci_td *descriptor = fQueueTop;
while (descriptor) {
if (descriptor->link_log == firstDescriptor) {
descriptor->link_log = lastDescriptor->link_log;
descriptor->link_phy = lastDescriptor->link_phy;
// unlink the chain
uhci_td *element = fQueueTop;
while (element) {
if (element->link_log == firstDescriptor) {
element->link_log = lastDescriptor->link_log;
element->link_phy = lastDescriptor->link_phy;
break;
}
descriptor = (uhci_td *)descriptor->link_log;
element = (uhci_td *)element->link_log;
}
descriptor = firstDescriptor;
while (descriptor) {
if ((fQueueHead->element_phy & TD_LINK_MASK)
== (descriptor->this_phy & TD_LINK_MASK)) {
if ((lastDescriptor->link_phy) & TD_TERMINATE > 0)
fQueueHead->element_phy = QH_TERMINATE;
else
fQueueHead->element_phy = lastDescriptor->link_phy & TD_LINK_MASK;
element = firstDescriptor;
while (element && element != lastDescriptor) {
if ((fQueueHead->element_phy & TD_LINK_MASK) == element->this_phy) {
fQueueHead->element_phy = lastDescriptor->link_phy;
break;
}
descriptor = (uhci_td *)descriptor->link_log;
element = (uhci_td *)element->link_log;
}
}
@@ -346,7 +342,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
fInitOK = false;
if (benaphore_init(&fUHCILock, "usb uhci lock") < B_OK) {
TRACE(("usb_uhci: failed to create busmanager lock\n"));
TRACE_ERROR(("usb_uhci: failed to create busmanager lock\n"));
return;
}
@@ -376,7 +372,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
// do a global and host reset
GlobalReset();
if (ControllerReset() < B_OK) {
TRACE(("usb_uhci: host failed to reset\n"));
TRACE_ERROR(("usb_uhci: host failed to reset\n"));
return;
}
@@ -386,7 +382,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
(void **)&physicalAddress, 4096, "USB UHCI framelist");
if (fFrameArea < B_OK) {
TRACE(("usb_uhci: unable to create an area for the frame pointer list\n"));
TRACE_ERROR(("usb_uhci: unable to create an area for the frame pointer list\n"));
return;
}
@@ -404,7 +400,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
for (int32 i = 0; i < fQueueCount; i++) {
fQueues[i] = new(std::nothrow) Queue(fStack);
if (!fQueues[i] || fQueues[i]->InitCheck() < B_OK) {
TRACE(("usb_uhci: cannot create queues\n"));
TRACE_ERROR(("usb_uhci: cannot create queues\n"));
delete_area(fFrameArea);
return;
}
@@ -503,19 +499,20 @@ UHCI::Start()
}
if (!running) {
TRACE(("usb_uhci: controller won't start running\n"));
TRACE_ERROR(("usb_uhci: controller won't start running\n"));
return B_ERROR;
}
fPortResetChange[0] = fPortResetChange[1] = false;
fRootHubAddress = AllocateAddress();
fRootHub = new(std::nothrow) UHCIRootHub(this, fRootHubAddress);
if (!fRootHub) {
TRACE(("usb_uhci: no memory to allocate root hub\n"));
TRACE_ERROR(("usb_uhci: no memory to allocate root hub\n"));
return B_NO_MEMORY;
}
if (fRootHub->InitCheck() < B_OK) {
TRACE(("usb_uhci: root hub could not be created\n"));
TRACE_ERROR(("usb_uhci: root hub failed init check\n"));
delete fRootHub;
return B_ERROR;
}
@@ -558,7 +555,7 @@ UHCI::SubmitTransfer(Transfer *transfer)
if (!firstDescriptor || !lastDescriptor)
return B_NO_MEMORY;
lastDescriptor->status |= TD_STATUS_IOC;
lastDescriptor->status |= TD_CONTROL_IOC;
lastDescriptor->link_phy = TD_TERMINATE;
lastDescriptor->link_log = 0;
@@ -574,14 +571,14 @@ UHCI::SubmitTransfer(Transfer *transfer)
result = AddPendingTransfer(transfer, queue, firstDescriptor,
firstDescriptor, lastDescriptor, directionIn);
if (result < B_OK) {
TRACE(("usb_uhci: failed to add pending transfer\n"));
TRACE_ERROR(("usb_uhci: failed to add pending transfer\n"));
FreeDescriptorChain(firstDescriptor);
return result;
}
result = queue->AppendDescriptor(firstDescriptor);
result = queue->AppendDescriptorChain(firstDescriptor);
if (result < B_OK) {
TRACE(("usb_uhci: failed to append descriptors\n"));
TRACE_ERROR(("usb_uhci: failed to append descriptor chain\n"));
FreeDescriptorChain(firstDescriptor);
return result;
}
@@ -604,7 +601,7 @@ UHCI::SubmitRequest(Transfer *transfer)
directionIn ? TD_TOKEN_OUT : TD_TOKEN_IN, 0);
if (!setupDescriptor || !statusDescriptor) {
TRACE(("usb_uhci: failed to allocate descriptors\n"));
TRACE_ERROR(("usb_uhci: failed to allocate descriptors\n"));
FreeDescriptor(setupDescriptor);
FreeDescriptor(statusDescriptor);
return B_NO_MEMORY;
@@ -613,10 +610,10 @@ UHCI::SubmitRequest(Transfer *transfer)
WriteDescriptorChain(setupDescriptor, (const uint8 *)requestData,
sizeof(usb_request_data));
statusDescriptor->status |= TD_STATUS_IOC;
statusDescriptor->status |= TD_CONTROL_IOC;
statusDescriptor->token |= TD_TOKEN_DATA1;
statusDescriptor->link_phy = TD_TERMINATE;
statusDescriptor->link_log = 0;
statusDescriptor->link_log = NULL;
uhci_td *dataDescriptor = NULL;
if (transfer->Data() && transfer->DataLength() > 0) {
@@ -646,14 +643,14 @@ UHCI::SubmitRequest(Transfer *transfer)
status_t result = AddPendingTransfer(transfer, fQueues[1], setupDescriptor,
dataDescriptor, statusDescriptor, directionIn);
if (result < B_OK) {
TRACE(("usb_uhci: failed to add pending transfer\n"));
TRACE_ERROR(("usb_uhci: failed to add pending transfer\n"));
FreeDescriptorChain(setupDescriptor);
return result;
}
result = fQueues[1]->AppendDescriptor(setupDescriptor);
result = fQueues[1]->AppendDescriptorChain(setupDescriptor);
if (result < B_OK) {
TRACE(("usb_uhci: failed to append descriptors\n"));
TRACE_ERROR(("usb_uhci: failed to append descriptor chain\n"));
FreeDescriptorChain(setupDescriptor);
return result;
}
@@ -667,7 +664,6 @@ UHCI::AddPendingTransfer(Transfer *transfer, Queue *queue,
uhci_td *firstDescriptor, uhci_td *dataDescriptor, uhci_td *lastDescriptor,
bool directionIn)
{
TRACE(("usb_uhci: add pending transfer\n"));
transfer_data *data = new(std::nothrow) transfer_data();
if (!data)
return B_NO_MEMORY;
@@ -741,11 +737,22 @@ UHCI::FinishTransfers()
TRACE_ERROR(("usb_uhci: td (0x%08x) error: 0x%08x\n", descriptor->this_phy, status));
// an error occured. we have to remove the
// transfer from the queue and clean up
transfer->queue->RemoveDescriptors(transfer->first_descriptor,
uint32 callbackStatus = 0;
if (status & TD_STATUS_ERROR_STALLED)
callbackStatus |= B_USB_STATUS_DEVICE_STALLED;
if (status & TD_STATUS_ERROR_TIMEOUT) {
if (transfer->incoming)
callbackStatus |= B_USB_STATUS_DEVICE_CRC_ERROR;
else
callbackStatus |= B_USB_STATUS_DEVICE_TIMEOUT;
}
transfer->queue->RemoveDescriptorChain(
transfer->first_descriptor,
transfer->last_descriptor);
FreeDescriptorChain(transfer->first_descriptor);
TRACE(("usb_uhci: notify transfer 0x%08x\n", transfer));
transfer->transfer->Finished(B_ERROR);
transfer->transfer->Finished(callbackStatus);
transferDone = true;
break;
}
@@ -753,13 +760,14 @@ UHCI::FinishTransfers()
if (descriptor == transfer->last_descriptor) {
TRACE(("usb_uhci: td (0x%08x) ok\n", descriptor->this_phy));
// we got through without errors so we are finished
transfer->queue->RemoveDescriptors(transfer->first_descriptor,
transfer->queue->RemoveDescriptorChain(
transfer->first_descriptor,
transfer->last_descriptor);
if (transfer->data_descriptor && transfer->incoming) {
// data to read out
TRACE(("usb_uhci: reading incoming data buffer to transfer 0x%08x\n", transfer));
size_t length = ReadDescriptorChain(transfer->data_descriptor,
size_t length = ReadDescriptorChain(
transfer->data_descriptor,
transfer->transfer->Data(),
transfer->transfer->DataLength());
@@ -767,7 +775,6 @@ UHCI::FinishTransfers()
}
FreeDescriptorChain(transfer->first_descriptor);
TRACE(("usb_uhci: notify transfer 0x%08x\n", transfer));
transfer->transfer->Finished(B_OK);
transferDone = true;
break;
@@ -777,7 +784,6 @@ UHCI::FinishTransfers()
}
if (transferDone) {
TRACE(("usb_uhci: transfer (0x%08x) done\n", transfer));
if (Lock()) {
if (lastTransfer)
lastTransfer->link = transfer->link;
@@ -794,7 +800,6 @@ UHCI::FinishTransfers()
Unlock();
}
} else {
TRACE(("usb_uhci: transfer (0x%08x) not done\n", transfer));
lastTransfer = transfer;
transfer = transfer->link;
}
@@ -837,7 +842,6 @@ UHCI::PortStatus(int32 index)
if (index > 1)
return B_BAD_VALUE;
//TRACE(("usb_uhci: read port status of port: %d\n", index));
return ReadReg16(UHCI_PORTSC1 + index * 2);
}
@@ -903,11 +907,32 @@ UHCI::ResetPort(int32 index)
}
}
SetPortResetChange(index, true);
TRACE(("usb_uhci: port was reset: 0x%04x\n", ReadReg16(port)));
return B_OK;
}
bool
UHCI::PortResetChange(int32 index)
{
if (index > 1)
return false;
return fPortResetChange[index];
}
void
UHCI::SetPortResetChange(int32 index, bool value)
{
if (index > 1)
return;
fPortResetChange[index] = value;
}
int32
UHCI::InterruptHandler(void *data)
{
@@ -931,9 +956,6 @@ UHCI::Interrupt()
if ((status & UHCI_INTERRUPT_MASK) == 0)
return B_UNHANDLED_INTERRUPT;
TRACE(("usb_uhci: Interrupt()\n"));
TRACE(("usb_uhci: status: 0x%04x\n", status));
uint16 acknowledge = 0;
if (status & UHCI_USBSTS_USBINT) {
TRACE(("usb_uhci: transfer finished\n"));
@@ -984,7 +1006,7 @@ UHCI::AddTo(Stack &stack)
if (!sPCIModule) {
status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
if (status < B_OK) {
TRACE(("usb_uhci: AddTo(): getting pci module failed! 0x%08x\n",
TRACE_ERROR(("usb_uhci: AddTo(): getting pci module failed! 0x%08x\n",
status));
return status;
}
@@ -1006,7 +1028,7 @@ UHCI::AddTo(Stack &stack)
&& item->class_api == 0x00) {
if (item->u.h0.interrupt_line == 0
|| item->u.h0.interrupt_line == 0xFF) {
TRACE(("usb_uhci: AddTo(): found with invalid IRQ - check IRQ assignement\n"));
TRACE_ERROR(("usb_uhci: AddTo(): found with invalid IRQ - check IRQ assignement\n"));
continue;
}
@@ -1020,7 +1042,7 @@ UHCI::AddTo(Stack &stack)
}
if (bus->InitCheck() < B_OK) {
TRACE(("usb_uhci: AddTo(): InitCheck() failed 0x%08x\n", bus->InitCheck()));
TRACE_ERROR(("usb_uhci: AddTo(): InitCheck() failed 0x%08x\n", bus->InitCheck()));
delete bus;
continue;
}
@@ -1050,22 +1072,22 @@ UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, int32 bufferSize)
void *physicalAddress;
if (fStack->AllocateChunk((void **)&result, &physicalAddress, 32) < B_OK) {
TRACE(("usb_uhci: failed to allocate a transfer descriptor\n"));
TRACE_ERROR(("usb_uhci: failed to allocate a transfer descriptor\n"));
return NULL;
}
result->this_phy = (addr_t)physicalAddress;
result->status = TD_STATUS_ACTIVE | TD_STATUS_3_ERRORS;
result->status = TD_STATUS_ACTIVE | TD_CONTROL_3_ERRORS;
if (pipe->Speed() == Pipe::LowSpeed)
result->status |= TD_STATUS_LOWSPEED;
result->status |= TD_CONTROL_LOWSPEED;
result->buffer_size = bufferSize;
if (bufferSize == 0)
result->token = TD_TOKEN_NULL;
result->token = TD_TOKEN_NULL_DATA;
else
result->token = (bufferSize - 1) << 21;
result->token = (bufferSize - 1) << TD_TOKEN_MAXLEN_SHIFT;
result->token |= (pipe->EndpointAddress() << 15)
result->token |= (pipe->EndpointAddress() << TD_TOKEN_ENDPTADDR_SHIFT)
| (pipe->DeviceAddress() << 8) | direction;
result->link_phy = 0;
@@ -1078,7 +1100,7 @@ UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, int32 bufferSize)
if (fStack->AllocateChunk(&result->buffer_log, &result->buffer_phy,
bufferSize) < B_OK) {
TRACE(("usb_uhci: unable to allocate space for the buffer\n"));
TRACE_ERROR(("usb_uhci: unable to allocate space for the buffer\n"));
fStack->FreeChunk(result, (void *)result->this_phy, 32);
return NULL;
}
@@ -1168,7 +1190,6 @@ size_t
UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer,
int32 bufferSize)
{
TRACE(("usb_uhci: writing descriptor chain from buffer 0x%08x\n", buffer));
size_t actualSize = 0;
uhci_td *current = topDescriptor;
@@ -1198,7 +1219,6 @@ size_t
UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
int32 bufferSize)
{
TRACE(("usb_uhci: reading descriptor chain to buffer 0x%08x\n", buffer));
size_t actualSize = 0;
uhci_td *current = topDescriptor;
+6 -2
View File
@@ -32,8 +32,9 @@ public:
status_t LinkTo(Queue *other);
status_t TerminateByStrayDescriptor();
status_t AppendDescriptor(uhci_td *descriptor);
status_t RemoveDescriptors(uhci_td *firstDescriptor,
status_t AppendDescriptorChain(uhci_td *descriptor);
status_t RemoveDescriptorChain(
uhci_td *firstDescriptor,
uhci_td *lastDescriptor);
addr_t PhysicalAddress();
@@ -79,6 +80,8 @@ static bool AddTo(Stack &stack);
uint16 PortStatus(int32 index);
status_t SetPortStatus(int32 index, uint16 status);
status_t ResetPort(int32 index);
bool PortResetChange(int32 index);
void SetPortResetChange(int32 index, bool value);
private:
// Controller resets
@@ -151,6 +154,7 @@ static pci_module_info *sPCIModule;
// Root hub
UHCIRootHub *fRootHub;
uint8 fRootHubAddress;
bool fPortResetChange[2];
};
+59 -44
View File
@@ -14,7 +14,6 @@
* The Registers *
************************************************************/
// R/W -- Read/Write
// R/WC -- Read/Write Clear
// ** -- Only writable with words!
@@ -80,75 +79,91 @@
#define FRAMELIST_NEXT_IS_QH 0x2
//Represents a Transfer Descriptor (TD)
// Represents a Transfer Descriptor (TD)
typedef struct
{
//Hardware part
addr_t link_phy; // Link to the next TD/QH
uint32 status; // Status field
uint32 token; // Contains the packet header (where it needs to be sent)
void * buffer_phy; // A pointer to the buffer with the actual packet
addr_t link_phy; // Link to the next TD/QH
uint32 status; // Status field
uint32 token; // Contains the packet header (where it needs to be sent)
void *buffer_phy; // A pointer to the buffer with the actual packet
// Software part
addr_t this_phy; // A physical pointer to this address
void * link_log; // Link to the next logical TD/QT
void * buffer_log; // Link to the buffer
int32 buffer_size; // Size of the buffer
addr_t this_phy; // A physical pointer to this address
void *link_log; // Pointer to the next logical TD/QT
void *buffer_log; // Pointer to the logical buffer
int32 buffer_size; // Size of the buffer
} uhci_td;
#define TD_STATUS_3_ERRORS (3 << 27)
#define TD_STATUS_LOWSPEED (1 << 26)
#define TD_STATUS_IOS (1 << 25)
#define TD_STATUS_IOC (1 << 24)
#define TD_STATUS_ACTIVE (1 << 23)
#define TD_STATUS_ACTLEN_MASK 0x3ff
#define TD_STATUS_ACTLEN_NULL 0x7ff
// Control and Status
#define TD_CONTROL_SHORT_PACKET (1 << 29)
#define TD_CONTROL_3_ERRORS (3 << 27)
#define TD_CONTROL_LOWSPEED (1 << 26)
#define TD_CONTROL_ISOCHRONOUS (1 << 25)
#define TD_CONTROL_IOC (1 << 24)
#define TD_TOKEN_DATA1 (1 << 19)
#define TD_TOKEN_NULL (0x7ff << 21)
#define TD_STATUS_ACTIVE (1 << 23)
#define TD_STATUS_ERROR_STALLED (1 << 22)
#define TD_STATUS_ERROR_BUFFER (1 << 21)
#define TD_STATUS_ERROR_BABBLE (1 << 20)
#define TD_STATUS_ERROR_NAK (1 << 19)
#define TD_STATUS_ERROR_CRC (1 << 18)
#define TD_STATUS_ERROR_TIMEOUT (1 << 18)
#define TD_STATUS_ERROR_BITSTUFF (1 << 17)
#define TD_TOKEN_SETUP 0x2d
#define TD_TOKEN_IN 0x69
#define TD_TOKEN_OUT 0xe1
#define TD_STATUS_ACTLEN_MASK 0x03ff
#define TD_STATUS_ACTLEN_NULL 0x07ff
#define TD_TOKEN_DEVADDR_SHIFT 8
#define TD_DEPTH_FIRST 0x4
#define TD_TERMINATE 0x1
#define TD_ERROR_MASK 0x7e0000
#define TD_LINK_MASK 0xfffffff0
// Token
#define TD_TOKEN_MAXLEN_SHIFT 21
#define TD_TOKEN_NULL_DATA (0x07ff << TD_TOKEN_MAXLEN_SHIFT)
#define TD_TOKEN_DATA1 (1 << 19)
//Represents a Queue Head (QH)
#define TD_TOKEN_SETUP 0x2d
#define TD_TOKEN_IN 0x69
#define TD_TOKEN_OUT 0xe1
#define TD_TOKEN_ENDPTADDR_SHIFT 15
#define TD_TOKEN_DEVADDR_SHIFT 8
#define TD_DEPTH_FIRST 0x04
#define TD_TERMINATE 0x01
#define TD_ERROR_MASK 0x7e0000
#define TD_LINK_MASK 0xfffffff0
// Represents a Queue Head (QH)
typedef struct
{
// Hardware part
addr_t link_phy; //Link to the next TD/QH
addr_t element_phy; //Link to the first element pointer in the queue
addr_t link_phy; // Link to the next TD/QH
addr_t element_phy; // Pointer to the first element in the queue
// Software part
addr_t this_phy; //The physical pointer to this address
void * link_log; //Link to the next TD/QH logical
addr_t this_phy; // The physical pointer to this address
void *link_log; // Pointer to the next logical TD/QH
} uhci_qh;
#define QH_TERMINATE 0x1
#define QH_NEXT_IS_QH 0x2
#define QH_TERMINATE 0x01
#define QH_NEXT_IS_QH 0x02
#define QH_LINK_MASK 0xfffffff0
/************************************************************
* Roothub Emulation *
************************************************************/
#define RH_GET_STATUS 0
#define RH_CLEAR_FEATURE 1
#define RH_SET_FEATURE 3
#define RH_SET_ADDRESS 5
#define RH_GET_DESCRIPTOR 6
#define RH_SET_CONFIG 9
#define RH_GET_STATUS 0
#define RH_CLEAR_FEATURE 1
#define RH_SET_FEATURE 3
#define RH_SET_ADDRESS 5
#define RH_GET_DESCRIPTOR 6
#define RH_SET_CONFIG 9
//Descriptors (in usb_request_data->Value)
// Descriptors (in usb_request_data->Value)
#define RH_DEVICE_DESCRIPTOR (0x01 << 8)
#define RH_CONFIG_DESCRIPTOR (0x02 << 8)
#define RH_STRING_DESCRIPTOR (0x03 << 8)
#define RH_STRING_DESCRIPTOR (0x03 << 8)
#define RH_HUB_DESCRIPTOR (0x29 << 8)
//Hub/Portstatus buffer
// Hub/Portstatus buffer
typedef struct
{
uint16 status;
+20 -20
View File
@@ -140,13 +140,13 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
status_t result = B_ERROR;
switch (request->Request) {
case RH_GET_STATUS:
case RH_GET_STATUS: {
if (request->Index == 0) {
// Get the hub status -- everything as 0 means all-right
memset(transfer->Data(), 0, sizeof(get_status_buffer));
result = B_OK;
break;
} else if (request->Index > sUHCIRootHubConfig.hub.bNbrPorts) {
} else if (request->Index > sUHCIRootHubConfig.hub.num_ports) {
// This port doesn't exist
result = EINVAL;
break;
@@ -154,13 +154,15 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
// Get port status
UpdatePortStatus();
memcpy(transfer->Data(),
(void *)&fPortStatus[request->Index - 1],
transfer->DataLength());
*(transfer->ActualLength()) = transfer->DataLength();
size_t length = MIN(4, transfer->DataLength());
memcpy(transfer->Data(),
(void *)&fPortStatus[request->Index - 1], length);
*(transfer->ActualLength()) = length;
result = B_OK;
break;
}
case RH_SET_ADDRESS:
if (request->Value >= 128) {
@@ -239,7 +241,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE no hub changes!\n"));
result = EINVAL;
break;
} else if (request->Index > sUHCIRootHubConfig.hub.bNbrPorts) {
} else if (request->Index > sUHCIRootHubConfig.hub.num_ports) {
// Invalid port number
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE invalid port!\n"));
result = EINVAL;
@@ -249,10 +251,9 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE called. Feature: %u!\n", request->Value));
uint16 status;
switch(request->Value) {
case PORT_RESET:
status = fUHCI->PortStatus(request->Index - 1);
result = fUHCI->SetPortStatus(request->Index - 1,
status & UHCI_PORTSC_DATAMASK & ~UHCI_PORTSC_RESET);
case C_PORT_RESET:
fUHCI->SetPortResetChange(request->Index - 1, false);
result = B_OK;
break;
case C_PORT_CONNECTION:
@@ -273,7 +274,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
TRACE(("usb_uhci_roothub: RH_SET_FEATURE no hub changes!\n"));
result = EINVAL;
break;
} else if (request->Index > sUHCIRootHubConfig.hub.bNbrPorts) {
} else if (request->Index > sUHCIRootHubConfig.hub.num_ports) {
// Invalid port number
TRACE(("usb_uhci_roothub: RH_SET_FEATURE invalid port!\n"));
result = EINVAL;
@@ -281,17 +282,16 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
}
TRACE(("usb_uhci_roothub: RH_SET_FEATURE called. Feature: %u!\n", request->Value));
uint16 status;
switch(request->Value) {
case PORT_RESET:
result = fUHCI->ResetPort(request->Index - 1);
break;
case PORT_ENABLE:
status = fUHCI->PortStatus(request->Index - 1);
result = fUHCI->SetPortStatus(request->Index - 1,
(status & UHCI_PORTSC_DATAMASK) | UHCI_PORTSC_ENABLED);
case PORT_POWER:
// the ports are automatically powered
result = B_OK;
break;
default:
result = EINVAL;
break;
@@ -312,7 +312,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
void
UHCIRootHub::UpdatePortStatus()
{
for (int32 i = 0; i < sUHCIRootHubConfig.hub.bNbrPorts; i++) {
for (int32 i = 0; i < sUHCIRootHubConfig.hub.num_ports; i++) {
uint16 newStatus = 0;
uint16 newChange = 0;
@@ -336,8 +336,8 @@ UHCIRootHub::UpdatePortStatus()
if (portStatus & UHCI_PORTSC_RESET)
newStatus |= PORT_STATUS_RESET;
//TODO: work out reset change...
if (fUHCI->PortResetChange(i))
newChange |= PORT_STATUS_RESET;
//The port is automagically powered on
newStatus |= PORT_POWER;