* Switched from the old v2 callback status codes to the new v3 codes
This means that the usb_callback_func now takes a status_t instead of a uint32 status. Also the error codes are now different. I don't see this as a real problem in binary compatibility, as the status codes were never really documented and most drivers just assumed that a nonzero status meant an error. Source compatibility breaks for callback functions and error defines. I fixed (hopefully) all places in the tree that are currenty included in the image and affected by the change. * Corrected error reporting in UHCI and EHCI using the new status codes. * Fixed a memory leak in EHCI where the async advance interrupt was not triggered in time. * Fixed another race condition in usb_raw that could cause a crash when a device is removed while a transfer is pending. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18916 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
8a278a1bb7
commit
17f83b219d
@ -73,7 +73,7 @@ struct usb_configuration_info {
|
||||
usb_interface_list *interface;
|
||||
};
|
||||
|
||||
typedef void (*usb_callback_func)(void *cookie, uint32 status, void *data,
|
||||
typedef void (*usb_callback_func)(void *cookie, status_t status, void *data,
|
||||
size_t actualLength);
|
||||
|
||||
|
||||
@ -203,24 +203,6 @@ struct usb_module_info {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* These status are passed to the usb_callback_func callbacks. They indicate
|
||||
* the status of a completed queued transfer. Multiple of these status codes
|
||||
* may be combined. For example it is possible to have:
|
||||
* B_USB_STATUS_DEVICE_TIMEOUT | B_USB_STATUS_DEVICE_STALLED
|
||||
* This indicates that a timeout happened and that the used pipe is now
|
||||
* stalled.
|
||||
*/
|
||||
#define B_USB_STATUS_SUCCESS 0x0000
|
||||
#define B_USB_STATUS_DEVICE_CRC_ERROR 0x0002
|
||||
#define B_USB_STATUS_DEVICE_TIMEOUT 0x0004
|
||||
#define B_USB_STATUS_DEVICE_STALLED 0x0008
|
||||
#define B_USB_STATUS_IRP_CANCELLED_BY_REQUEST 0x0010
|
||||
#define B_USB_STATUS_DRIVER_INTERNAL_ERROR 0x0020
|
||||
#define B_USB_STATUS_ADAPTER_HARDWARE_ERROR 0x0040
|
||||
#define B_USB_STATUS_ISOCH_IRP_ABORTED 0x0080
|
||||
|
||||
|
||||
#define B_USB_MODULE_NAME "bus_managers/usb/v2"
|
||||
|
||||
|
||||
|
@ -79,7 +79,7 @@ typedef struct {
|
||||
status_t status;
|
||||
} usb_iso_packet_descriptor;
|
||||
|
||||
typedef void (*usb_callback_func)(void *cookie, uint32 status, void *data,
|
||||
typedef void (*usb_callback_func)(void *cookie, status_t status, void *data,
|
||||
size_t actualLength);
|
||||
|
||||
|
||||
@ -214,24 +214,6 @@ struct usb_module_info {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* These status are passed to the usb_callback_func callbacks. They indicate
|
||||
* the status of a completed queued transfer. Multiple of these status codes
|
||||
* may be combined. For example it is possible to have:
|
||||
* B_USB_STATUS_DEVICE_TIMEOUT | B_USB_STATUS_DEVICE_STALLED
|
||||
* This indicates that a timeout happened and that the used pipe is now
|
||||
* stalled.
|
||||
*/
|
||||
#define B_USB_STATUS_SUCCESS 0x0000
|
||||
#define B_USB_STATUS_DEVICE_CRC_ERROR 0x0002
|
||||
#define B_USB_STATUS_DEVICE_TIMEOUT 0x0004
|
||||
#define B_USB_STATUS_DEVICE_STALLED 0x0008
|
||||
#define B_USB_STATUS_IRP_CANCELLED_BY_REQUEST 0x0010
|
||||
#define B_USB_STATUS_DRIVER_INTERNAL_ERROR 0x0020
|
||||
#define B_USB_STATUS_ADAPTER_HARDWARE_ERROR 0x0040
|
||||
#define B_USB_STATUS_ISOCH_IRP_ABORTED 0x0080
|
||||
|
||||
|
||||
#define B_USB_MODULE_NAME "bus_managers/usb/v3"
|
||||
|
||||
|
||||
|
@ -10,6 +10,22 @@
|
||||
#define IS_USER_ADDRESS(x) (((uint32)x & 0x80000000) > 0)
|
||||
#define IS_KERNEL_ADDRESS(x) (((uint32)x & 0x80000000) == 0)
|
||||
|
||||
#ifndef B_DEV_INVALID_PIPE
|
||||
enum {
|
||||
B_DEV_INVALID_PIPE = B_DEV_DOOR_OPEN + 1,
|
||||
B_DEV_CRC_ERROR,
|
||||
B_DEV_STALLED,
|
||||
B_DEV_BAD_PID,
|
||||
B_DEV_UNEXPECTED_PID,
|
||||
B_DEV_DATA_OVERRUN,
|
||||
B_DEV_DATA_UNDERRUN,
|
||||
B_DEV_FIFO_OVERRUN,
|
||||
B_DEV_FIFO_UNDERRUN,
|
||||
B_DEV_PENDING,
|
||||
B_DEV_MULTIPLE_ERRORS,
|
||||
B_DEV_TOO_LATE,
|
||||
};
|
||||
#endif
|
||||
|
||||
inline status_t
|
||||
benaphore_init(benaphore *ben, const char *name)
|
||||
|
@ -230,7 +230,7 @@ Hub::Explore()
|
||||
|
||||
|
||||
void
|
||||
Hub::InterruptCallback(void *cookie, uint32 status, void *data,
|
||||
Hub::InterruptCallback(void *cookie, status_t status, void *data,
|
||||
size_t actualLength)
|
||||
{
|
||||
TRACE(("USB Hub: interrupt callback!\n"));
|
||||
|
@ -204,9 +204,9 @@ IsochronousPipe::QueueIsochronous(void *data, size_t dataLength,
|
||||
|
||||
|
||||
typedef struct transfer_result_data_s {
|
||||
sem_id notify_sem;
|
||||
uint32 status;
|
||||
size_t actual_length;
|
||||
sem_id notify_sem;
|
||||
status_t status;
|
||||
size_t actual_length;
|
||||
} transfer_result_data;
|
||||
|
||||
|
||||
@ -243,15 +243,12 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value,
|
||||
if (actualLength)
|
||||
*actualLength = transferResult.actual_length;
|
||||
|
||||
if (transferResult.status == B_USB_STATUS_SUCCESS)
|
||||
return B_OK;
|
||||
|
||||
return B_ERROR;
|
||||
return transferResult.status;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ControlPipe::SendRequestCallback(void *cookie, uint32 status, void *data,
|
||||
ControlPipe::SendRequestCallback(void *cookie, status_t status, void *data,
|
||||
size_t actualLength)
|
||||
{
|
||||
transfer_result_data *transferResult = (transfer_result_data *)cookie;
|
||||
|
@ -123,7 +123,7 @@ set_configuration(usb_device device,
|
||||
TRACE(("usb_module: set_configuration(0x%08x, 0x%08x)\n", device, configuration));
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((Device *)object)->SetConfiguration(configuration);
|
||||
}
|
||||
@ -135,7 +135,7 @@ set_alt_interface(usb_device device, const usb_interface_info *interface)
|
||||
TRACE(("usb_module: set_alt_interface(0x%08x, 0x%08x)\n", device, interface));
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
@ -147,7 +147,7 @@ set_feature(usb_id handle, uint16 selector)
|
||||
TRACE(("usb_module: set_feature(0x%08x, %d)\n", handle, selector));
|
||||
Object *object = gUSBStack->GetObject(handle);
|
||||
if (!object)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return object->SetFeature(selector);
|
||||
}
|
||||
@ -159,7 +159,7 @@ clear_feature(usb_id handle, uint16 selector)
|
||||
TRACE(("usb_module: clear_feature(0x%08x, %d)\n", handle, selector));
|
||||
Object *object = gUSBStack->GetObject(handle);
|
||||
if (!object)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return object->ClearFeature(selector);
|
||||
}
|
||||
@ -174,7 +174,7 @@ get_status(usb_id handle, uint16 *status)
|
||||
|
||||
Object *object = gUSBStack->GetObject(handle);
|
||||
if (!object)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return object->GetStatus(status);
|
||||
}
|
||||
@ -187,7 +187,7 @@ get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
|
||||
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));
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((Device *)object)->GetDescriptor(type, index, languageID,
|
||||
data, dataLength, actualLength);
|
||||
@ -201,7 +201,7 @@ send_request(usb_device device, uint8 requestType, uint8 request,
|
||||
TRACE(("usb_module: send_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, actualLength));
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request,
|
||||
value, index, length, data, length, actualLength);
|
||||
@ -216,7 +216,7 @@ queue_request(usb_device device, uint8 requestType, uint8 request,
|
||||
TRACE(("usb_module: queue_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, callback, callbackCookie));
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((Device *)object)->DefaultPipe()->QueueRequest(requestType,
|
||||
request, value, index, length, data, length, callback, callbackCookie);
|
||||
@ -230,7 +230,7 @@ queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
|
||||
TRACE(("usb_module: queue_interrupt(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie));
|
||||
Object *object = gUSBStack->GetObject(pipe);
|
||||
if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
|
||||
callbackCookie);
|
||||
@ -244,7 +244,7 @@ queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
|
||||
TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie));
|
||||
Object *object = gUSBStack->GetObject(pipe);
|
||||
if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
|
||||
callbackCookie);
|
||||
@ -258,7 +258,7 @@ queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
|
||||
TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, vector, vectorCount, callback, callbackCookie));
|
||||
Object *object = gUSBStack->GetObject(pipe);
|
||||
if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
|
||||
callbackCookie);
|
||||
@ -274,7 +274,7 @@ queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
|
||||
TRACE(("usb_module: queue_isochronous(0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, flags, callback, callbackCookie));
|
||||
Object *object = gUSBStack->GetObject(pipe);
|
||||
if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
|
||||
packetDesc, packetCount, startingFrameNumber, flags, callback,
|
||||
@ -289,7 +289,7 @@ set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
|
||||
TRACE(("usb_module: set_pipe_policy(0x%08x, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize));
|
||||
Object *object = gUSBStack->GetObject(pipe);
|
||||
if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
@ -301,7 +301,7 @@ cancel_queued_transfers(usb_pipe pipe)
|
||||
TRACE(("usb_module: cancel_queued_transfers(0x%08x)\n", pipe));
|
||||
Object *object = gUSBStack->GetObject(pipe);
|
||||
if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((Pipe *)object)->CancelQueuedTransfers();
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ virtual void SetDataToggle(bool toggle) {};
|
||||
void *data, size_t dataLength,
|
||||
size_t *actualLength);
|
||||
static void SendRequestCallback(void *cookie,
|
||||
uint32 status, void *data,
|
||||
status_t status, void *data,
|
||||
size_t actualLength);
|
||||
|
||||
status_t QueueRequest(uint8 requestType,
|
||||
@ -437,7 +437,7 @@ virtual status_t GetDescriptor(uint8 descriptorType,
|
||||
status_t ResetPort(uint8 index);
|
||||
void Explore();
|
||||
static void InterruptCallback(void *cookie,
|
||||
uint32 status, void *data,
|
||||
status_t status, void *data,
|
||||
size_t actualLength);
|
||||
|
||||
virtual status_t ReportDevice(
|
||||
|
@ -2,6 +2,10 @@ SubDir HAIKU_TOP src add-ons kernel busses scsi usb ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
if $(TARGET_PLATFORM) != haiku {
|
||||
UsePublicHeaders [ FDirName drivers ] ;
|
||||
}
|
||||
|
||||
KernelAddon usb_scsi :
|
||||
usb_scsi.c
|
||||
tracing.c
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
???
|
||||
*/
|
||||
void bulk_callback(void *cookie, uint32 status, void* data, uint32 actual_len)
|
||||
void bulk_callback(void *cookie, status_t status, void* data, uint32 actual_len)
|
||||
{
|
||||
TRACE_BULK_CALLBACK(status, actual_len);
|
||||
if(cookie){
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "device_info.h"
|
||||
#endif /* _DEVICE_INFO_H_ */
|
||||
|
||||
void bulk_callback(void *cookie, uint32 status, void* data, uint32 actual_len);
|
||||
void bulk_callback(void *cookie, status_t status, void* data, uint32 actual_len);
|
||||
|
||||
status_t process_data_io(usb_device_info *udi, iovec *sg_data, int32 sg_count/*sg_buffer *sgb*/, EDirection dir);
|
||||
|
||||
|
@ -106,6 +106,7 @@ EHCI::EHCI(pci_info *info, Stack *stack)
|
||||
fLastTransfer(NULL),
|
||||
fFinishThread(-1),
|
||||
fStopFinishThread(false),
|
||||
fFreeListHead(NULL),
|
||||
fRootHub(NULL),
|
||||
fRootHubAddress(0),
|
||||
fPortCount(0),
|
||||
@ -879,7 +880,7 @@ EHCI::CancelPendingTransfer(Transfer *transfer)
|
||||
transfer_data *current = fFirstTransfer;
|
||||
while (current) {
|
||||
if (current->transfer == transfer) {
|
||||
current->transfer->Finished(B_USB_STATUS_IRP_CANCELLED_BY_REQUEST, 0);
|
||||
current->transfer->Finished(B_CANCELED, 0);
|
||||
delete current->transfer;
|
||||
|
||||
if (last)
|
||||
@ -912,7 +913,7 @@ EHCI::CancelAllPendingTransfers()
|
||||
|
||||
transfer_data *transfer = fFirstTransfer;
|
||||
while (transfer) {
|
||||
transfer->transfer->Finished(B_USB_STATUS_IRP_CANCELLED_BY_REQUEST, 0);
|
||||
transfer->transfer->Finished(B_CANCELED, 0);
|
||||
delete transfer->transfer;
|
||||
|
||||
transfer_data *next = transfer->link;
|
||||
@ -956,7 +957,6 @@ EHCI::FinishTransfers()
|
||||
transfer_data *transfer = fFirstTransfer;
|
||||
Unlock();
|
||||
|
||||
ehci_qh *freeListHead = NULL;
|
||||
while (transfer) {
|
||||
bool transferDone = false;
|
||||
ehci_qtd *descriptor = (ehci_qtd *)transfer->queue_head->element_log;
|
||||
@ -977,18 +977,34 @@ EHCI::FinishTransfers()
|
||||
// a transfer error occured
|
||||
TRACE_ERROR(("usb_ehci: qtd (0x%08lx) error: 0x%08lx\n", descriptor->this_phy, status));
|
||||
|
||||
uint32 callbackStatus = 0;
|
||||
if (status & EHCI_QTD_STATUS_HALTED)
|
||||
callbackStatus |= B_USB_STATUS_DEVICE_STALLED;
|
||||
if (status & EHCI_QTD_STATUS_BUFFER)
|
||||
callbackStatus |= B_USB_STATUS_DEVICE_TIMEOUT;
|
||||
if (status & EHCI_QTD_STATUS_BABBLE)
|
||||
callbackStatus |= B_USB_STATUS_ADAPTER_HARDWARE_ERROR;
|
||||
if (status & EHCI_QTD_STATUS_TERROR)
|
||||
callbackStatus |= B_USB_STATUS_DRIVER_INTERNAL_ERROR;
|
||||
// ToDo: define better error values!
|
||||
status_t callbackStatus = B_ERROR;
|
||||
uint8 errorCount = status >> EHCI_QTD_ERRCOUNT_SHIFT;
|
||||
errorCount &= EHCI_QTD_ERRCOUNT_MASK;
|
||||
if (errorCount == 0) {
|
||||
// the error counter counted down to zero, report why
|
||||
int32 reasons = 0;
|
||||
if (status & EHCI_QTD_STATUS_BUFFER) {
|
||||
callbackStatus = transfer->incoming ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN;
|
||||
reasons++;
|
||||
}
|
||||
if (status & EHCI_QTD_STATUS_TERROR) {
|
||||
callbackStatus = B_DEV_CRC_ERROR;
|
||||
reasons++;
|
||||
}
|
||||
|
||||
UnlinkQueueHead(transfer->queue_head, &freeListHead);
|
||||
if (reasons > 1)
|
||||
callbackStatus = B_DEV_MULTIPLE_ERRORS;
|
||||
} else if (status & EHCI_QTD_STATUS_BABBLE) {
|
||||
// there is a babble condition
|
||||
callbackStatus = transfer->incoming ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN;
|
||||
} else {
|
||||
// if the error counter didn't count down to zero
|
||||
// and there was no babble, then this halt was caused
|
||||
// by a stall handshake
|
||||
callbackStatus = B_DEV_STALLED;
|
||||
}
|
||||
|
||||
UnlinkQueueHead(transfer->queue_head, &fFreeListHead);
|
||||
transfer->transfer->Finished(callbackStatus, 0);
|
||||
transferDone = true;
|
||||
break;
|
||||
@ -1038,9 +1054,9 @@ EHCI::FinishTransfers()
|
||||
&nextDataToggle);
|
||||
}
|
||||
|
||||
UnlinkQueueHead(transfer->queue_head, &freeListHead);
|
||||
UnlinkQueueHead(transfer->queue_head, &fFreeListHead);
|
||||
transfer->transfer->TransferPipe()->SetDataToggle(nextDataToggle);
|
||||
transfer->transfer->Finished(B_USB_STATUS_SUCCESS, actualLength);
|
||||
transfer->transfer->Finished(B_OK, actualLength);
|
||||
transferDone = true;
|
||||
break;
|
||||
}
|
||||
@ -1065,19 +1081,22 @@ EHCI::FinishTransfers()
|
||||
Unlock();
|
||||
}
|
||||
} else {
|
||||
lastTransfer = transfer;
|
||||
transfer = transfer->link;
|
||||
if (Lock()) {
|
||||
lastTransfer = transfer;
|
||||
transfer = transfer->link;
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (freeListHead) {
|
||||
if (fFreeListHead) {
|
||||
// set the doorbell and wait for the host controller to notify us
|
||||
WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_INTONAAD);
|
||||
if (acquire_sem_etc(fAsyncAdvanceSem, 1, B_RELATIVE_TIMEOUT, 1000) == B_OK) {
|
||||
while (freeListHead) {
|
||||
ehci_qh *next = (ehci_qh *)freeListHead->next_log;
|
||||
FreeQueueHead(freeListHead);
|
||||
freeListHead = next;
|
||||
while (fFreeListHead) {
|
||||
ehci_qh *next = (ehci_qh *)fFreeListHead->next_log;
|
||||
FreeQueueHead(fFreeListHead);
|
||||
fFreeListHead = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,6 +142,7 @@ static pci_module_info *sPCIModule;
|
||||
sem_id fFinishTransfersSem;
|
||||
thread_id fFinishThread;
|
||||
bool fStopFinishThread;
|
||||
ehci_qh *fFreeListHead;
|
||||
|
||||
// Root Hub
|
||||
EHCIRootHub *fRootHub;
|
||||
|
@ -153,7 +153,7 @@ typedef struct {
|
||||
#define EHCI_QTD_PID_SETUP 0x02
|
||||
#define EHCI_QTD_STATUS_SHIFT 0
|
||||
#define EHCI_QTD_STATUS_MASK 0x7f
|
||||
#define EHCI_QTD_STATUS_ERRMASK 0x70
|
||||
#define EHCI_QTD_STATUS_ERRMASK 0x50
|
||||
#define EHCI_QTD_STATUS_ACTIVE (1 << 7) // Active
|
||||
#define EHCI_QTD_STATUS_HALTED (1 << 6) // Halted
|
||||
#define EHCI_QTD_STATUS_BUFFER (1 << 5) // Data Buffer Error
|
||||
|
@ -136,8 +136,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
usb_request_data *request = transfer->RequestData();
|
||||
TRACE(("usb_ehci_roothub: request: %d\n", request->Request));
|
||||
|
||||
// ToDo: define better status codes. We should return a request error.
|
||||
uint32 status = B_USB_STATUS_DEVICE_TIMEOUT;
|
||||
status_t status = B_TIMED_OUT;
|
||||
size_t actualLength = 0;
|
||||
switch (request->Request) {
|
||||
case USB_REQUEST_GET_STATUS: {
|
||||
@ -149,7 +148,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
// and if there is a over-current condition (bit 1).
|
||||
// everything as 0 means all is ok.
|
||||
memset(transfer->Data(), 0, actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -157,7 +156,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
if (ehci->GetPortStatus(request->Index - 1, &portStatus) >= B_OK) {
|
||||
actualLength = MIN(sizeof(usb_port_status), transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&portStatus, actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -165,12 +164,12 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
|
||||
case USB_REQUEST_SET_ADDRESS:
|
||||
if (request->Value >= 128) {
|
||||
status = B_USB_STATUS_DEVICE_TIMEOUT;
|
||||
status = B_TIMED_OUT;
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE(("usb_ehci_roothub: set address: %d\n", request->Value));
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
|
||||
case USB_REQUEST_GET_DESCRIPTOR:
|
||||
@ -182,7 +181,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sEHCIRootHubDevice,
|
||||
actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -192,7 +191,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
sEHCIRootHubConfig.hub.num_ports = ehci->PortCount();
|
||||
memcpy(transfer->Data(), (void *)&sEHCIRootHubConfig,
|
||||
actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -205,7 +204,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sEHCIRootHubStrings[index],
|
||||
actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -215,14 +214,14 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
sEHCIRootHubConfig.hub.num_ports = ehci->PortCount();
|
||||
memcpy(transfer->Data(), (void *)&sEHCIRootHubConfig.hub,
|
||||
actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQUEST_SET_CONFIGURATION:
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
|
||||
case USB_REQUEST_CLEAR_FEATURE: {
|
||||
@ -234,7 +233,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
|
||||
TRACE(("usb_ehci_roothub: clear feature: %d\n", request->Value));
|
||||
if (ehci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK)
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -247,7 +246,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
|
||||
|
||||
TRACE(("usb_ehci_roothub: set feature: %d\n", request->Value));
|
||||
if (ehci->SetPortFeature(request->Index - 1, request->Value) >= B_OK)
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -770,14 +770,39 @@ UHCI::FinishTransfers()
|
||||
// an error occured. we have to remove the
|
||||
// transfer from the queue and clean up
|
||||
|
||||
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;
|
||||
status_t callbackStatus = B_ERROR;
|
||||
uint8 errorCount = status >> TD_ERROR_COUNT_SHIFT;
|
||||
errorCount &= TD_ERROR_COUNT_MASK;
|
||||
if (errorCount == 0) {
|
||||
// the error counter counted down to zero, report why
|
||||
int32 reasons = 0;
|
||||
if (status & TD_STATUS_ERROR_BUFFER) {
|
||||
callbackStatus = transfer->incoming ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN;
|
||||
reasons++;
|
||||
}
|
||||
if (status & TD_STATUS_ERROR_TIMEOUT) {
|
||||
callbackStatus = transfer->incoming ? B_DEV_CRC_ERROR : B_TIMED_OUT;
|
||||
reasons++;
|
||||
}
|
||||
if (status & TD_STATUS_ERROR_NAK) {
|
||||
callbackStatus = B_DEV_UNEXPECTED_PID;
|
||||
reasons++;
|
||||
}
|
||||
if (status & TD_STATUS_ERROR_BITSTUFF) {
|
||||
callbackStatus = B_DEV_CRC_ERROR;
|
||||
reasons++;
|
||||
}
|
||||
|
||||
if (reasons > 1)
|
||||
callbackStatus = B_DEV_MULTIPLE_ERRORS;
|
||||
} else if (status & TD_STATUS_ERROR_BABBLE) {
|
||||
// there is a babble condition
|
||||
callbackStatus = transfer->incoming ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN;
|
||||
} else {
|
||||
// if the error counter didn't count down to zero
|
||||
// and there was no babble, then this halt was caused
|
||||
// by a stall handshake
|
||||
callbackStatus = B_DEV_STALLED;
|
||||
}
|
||||
|
||||
transfer->queue->RemoveDescriptorChain(
|
||||
@ -841,7 +866,7 @@ UHCI::FinishTransfers()
|
||||
|
||||
FreeDescriptorChain(transfer->first_descriptor);
|
||||
transfer->transfer->TransferPipe()->SetDataToggle(lastDataToggle == 0);
|
||||
transfer->transfer->Finished(B_USB_STATUS_SUCCESS, actualLength);
|
||||
transfer->transfer->Finished(B_OK, actualLength);
|
||||
transferDone = true;
|
||||
break;
|
||||
}
|
||||
|
@ -128,7 +128,9 @@ typedef struct
|
||||
|
||||
#define TD_DEPTH_FIRST 0x04
|
||||
#define TD_TERMINATE 0x01
|
||||
#define TD_ERROR_MASK 0x7e0000
|
||||
#define TD_ERROR_MASK 0x440000
|
||||
#define TD_ERROR_COUNT_SHIFT 27
|
||||
#define TD_ERROR_COUNT_MASK 0x03
|
||||
#define TD_LINK_MASK 0xfffffff0
|
||||
|
||||
|
||||
|
@ -140,8 +140,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
|
||||
usb_request_data *request = transfer->RequestData();
|
||||
TRACE(("usb_uhci_roothub: request: %d\n", request->Request));
|
||||
|
||||
// ToDo: define better status codes. We should return a request error.
|
||||
uint32 status = B_USB_STATUS_DEVICE_TIMEOUT;
|
||||
status_t status = B_TIMED_OUT;
|
||||
size_t actualLength = 0;
|
||||
switch (request->Request) {
|
||||
case USB_REQUEST_GET_STATUS: {
|
||||
@ -150,7 +149,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
|
||||
actualLength = MIN(sizeof(usb_port_status),
|
||||
transfer->DataLength());
|
||||
memset(transfer->Data(), 0, actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -158,19 +157,19 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
|
||||
if (uhci->GetPortStatus(request->Index - 1, &portStatus) >= B_OK) {
|
||||
actualLength = MIN(sizeof(usb_port_status), transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&portStatus, actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case USB_REQUEST_SET_ADDRESS:
|
||||
if (request->Value >= 128) {
|
||||
status = B_USB_STATUS_DEVICE_TIMEOUT;
|
||||
status = B_TIMED_OUT;
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE(("usb_uhci_roothub: set address: %d\n", request->Value));
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
|
||||
case USB_REQUEST_GET_DESCRIPTOR:
|
||||
@ -182,7 +181,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice,
|
||||
actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -191,7 +190,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig,
|
||||
actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -204,7 +203,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index],
|
||||
actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -213,14 +212,14 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub,
|
||||
actualLength);
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQUEST_SET_CONFIGURATION:
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
|
||||
case USB_REQUEST_CLEAR_FEATURE: {
|
||||
@ -232,7 +231,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
|
||||
|
||||
TRACE(("usb_uhci_roothub: clear feature: %d\n", request->Value));
|
||||
if (uhci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK)
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -245,7 +244,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
|
||||
|
||||
TRACE(("usb_uhci_roothub: set feature: %d!\n", request->Value));
|
||||
if (uhci->SetPortFeature(request->Index - 1, request->Value) >= B_OK)
|
||||
status = B_USB_STATUS_SUCCESS;
|
||||
status = B_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -99,12 +99,13 @@ usb_raw_device_removed(void *cookie)
|
||||
gDeviceCount--;
|
||||
benaphore_unlock(&gDeviceListLock);
|
||||
|
||||
benaphore_lock(&device->lock);
|
||||
device->device = 0;
|
||||
benaphore_destroy(&device->lock);
|
||||
delete_sem(device->notify);
|
||||
if (device->reference_count == 0)
|
||||
if (device->reference_count == 0) {
|
||||
benaphore_lock(&device->lock);
|
||||
benaphore_destroy(&device->lock);
|
||||
delete_sem(device->notify);
|
||||
free(device);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -123,12 +124,6 @@ usb_raw_open(const char *name, uint32 flags, void **cookie)
|
||||
raw_device *element = gDeviceList;
|
||||
while (element) {
|
||||
if (strcmp(name, element->name) == 0) {
|
||||
if (element->reference_count > 0) {
|
||||
// device is already open
|
||||
benaphore_unlock(&gDeviceListLock);
|
||||
return B_BUSY;
|
||||
}
|
||||
|
||||
element->reference_count++;
|
||||
*cookie = element;
|
||||
benaphore_unlock(&gDeviceListLock);
|
||||
@ -159,8 +154,12 @@ usb_raw_free(void *cookie)
|
||||
|
||||
raw_device *device = (raw_device *)cookie;
|
||||
device->reference_count--;
|
||||
if (device->device == 0)
|
||||
if (device->device == 0) {
|
||||
benaphore_lock(&device->lock);
|
||||
benaphore_destroy(&device->lock);
|
||||
delete_sem(device->notify);
|
||||
free(device);
|
||||
}
|
||||
|
||||
benaphore_unlock(&gDeviceListLock);
|
||||
return B_OK;
|
||||
@ -168,27 +167,27 @@ usb_raw_free(void *cookie)
|
||||
|
||||
|
||||
static void
|
||||
usb_raw_callback(void *cookie, uint32 status, void *data, size_t actualLength)
|
||||
usb_raw_callback(void *cookie, status_t status, void *data, size_t actualLength)
|
||||
{
|
||||
TRACE((DRIVER_NAME": callback()\n"));
|
||||
raw_device *device = (raw_device *)cookie;
|
||||
|
||||
switch (status) {
|
||||
case B_USB_STATUS_SUCCESS:
|
||||
case B_OK:
|
||||
device->status = RAW_STATUS_SUCCESS;
|
||||
break;
|
||||
case B_USB_STATUS_DEVICE_CRC_ERROR:
|
||||
device->status = RAW_STATUS_CRC_ERROR;
|
||||
break;
|
||||
case B_USB_STATUS_DEVICE_TIMEOUT:
|
||||
case B_TIMED_OUT:
|
||||
device->status = RAW_STATUS_TIMEOUT;
|
||||
break;
|
||||
case B_USB_STATUS_DEVICE_STALLED:
|
||||
device->status = RAW_STATUS_STALLED;
|
||||
break;
|
||||
case B_USB_STATUS_IRP_CANCELLED_BY_REQUEST:
|
||||
case B_CANCELED:
|
||||
device->status = RAW_STATUS_ABORTED;
|
||||
break;
|
||||
case B_DEV_CRC_ERROR:
|
||||
device->status = RAW_STATUS_CRC_ERROR;
|
||||
break;
|
||||
case B_DEV_STALLED:
|
||||
device->status = RAW_STATUS_STALLED;
|
||||
break;
|
||||
default:
|
||||
device->status = RAW_STATUS_FAILED;
|
||||
break;
|
||||
|
@ -592,11 +592,11 @@ usb_callback(void *cookie, uint32 busStatus,
|
||||
acquire_sem(device->sem_lock);
|
||||
device->actual_length = actualLength;
|
||||
device->bus_status = busStatus; /* B_USB_STATUS_* */
|
||||
if (busStatus != B_USB_STATUS_SUCCESS) {
|
||||
if (busStatus != B_OK) {
|
||||
/* request failed */
|
||||
release_sem(device->sem_lock);
|
||||
DPRINTF_ERR((MY_ID "bus status %d\n", (int)busStatus));
|
||||
if (busStatus == B_USB_STATUS_IRP_CANCELLED_BY_REQUEST) {
|
||||
if (busStatus == B_CANCELED) {
|
||||
/* cancelled: device is unplugged */
|
||||
return;
|
||||
}
|
||||
|
@ -158,11 +158,11 @@ midi_usb_callback(void *cookie, uint32 status,
|
||||
acquire_sem (my_dev->sem_lock);
|
||||
my_dev->actual_length = actual_len;
|
||||
my_dev->bus_status = status; /* B_USB_STATUS_* */
|
||||
if (status != B_USB_STATUS_SUCCESS) {
|
||||
if (status != B_OK) {
|
||||
/* request failed */
|
||||
release_sem (my_dev->sem_lock);
|
||||
DPRINTF_ERR ((MY_ID "bus status %d\n", (int)status));
|
||||
if (status == B_USB_STATUS_IRP_CANCELLED_BY_REQUEST) {
|
||||
if (status == B_CANCELED) {
|
||||
/* cancelled: device is unplugged */
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user