mirror of
https://github.com/reactos/reactos.git
synced 2024-10-08 10:24:06 +00:00
[USBOHCI]
- Implement function to retrieve isochronous head endpoint descriptor - Implement function to retrieve current frame number - Set isochronous descriptor flag for head endpoint - Implement retrieve device status for devices - Implement retrieve class status from device - Partly implement isochronous descriptor handling in usb queue - Start implementing isochronous transfers in ISUBRequest - Code currently not tested as the Virtual Machine with XP + ReactOS usbohci driver brings down the host system when starting the iso transfers. Ironically it crashes in MS usbohci driver svn path=/branches/usb-bringup/; revision=51957
This commit is contained in:
parent
9aff3e967c
commit
2231c8333a
|
@ -62,8 +62,10 @@ public:
|
||||||
NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
|
NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
|
||||||
NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
|
NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
|
||||||
NTSTATUS GetInterruptEndpointDescriptors(struct _OHCI_ENDPOINT_DESCRIPTOR *** OutDescriptor);
|
NTSTATUS GetInterruptEndpointDescriptors(struct _OHCI_ENDPOINT_DESCRIPTOR *** OutDescriptor);
|
||||||
|
NTSTATUS GetIsochronousHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
|
||||||
VOID HeadEndpointDescriptorModified(ULONG HeadType);
|
VOID HeadEndpointDescriptorModified(ULONG HeadType);
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager);
|
NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager);
|
||||||
NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
|
NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
|
||||||
|
|
||||||
|
@ -80,6 +82,7 @@ public:
|
||||||
|
|
||||||
KIRQL AcquireDeviceLock(void);
|
KIRQL AcquireDeviceLock(void);
|
||||||
VOID ReleaseDeviceLock(KIRQL OldLevel);
|
VOID ReleaseDeviceLock(KIRQL OldLevel);
|
||||||
|
virtual VOID GetCurrentFrameNumber(PULONG FrameNumber);
|
||||||
// local
|
// local
|
||||||
BOOLEAN InterruptService();
|
BOOLEAN InterruptService();
|
||||||
NTSTATUS InitializeController();
|
NTSTATUS InitializeController();
|
||||||
|
@ -698,6 +701,17 @@ CUSBHardwareDevice::GetInterruptEndpointDescriptors(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CUSBHardwareDevice::GetIsochronousHeadEndpointDescriptor(
|
||||||
|
struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get descriptor
|
||||||
|
//
|
||||||
|
*OutDescriptor = m_IsoEndpointDescriptor;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CUSBHardwareDevice::HeadEndpointDescriptorModified(
|
CUSBHardwareDevice::HeadEndpointDescriptorModified(
|
||||||
ULONG Type)
|
ULONG Type)
|
||||||
|
@ -848,6 +862,11 @@ CUSBHardwareDevice::InitializeController()
|
||||||
//
|
//
|
||||||
m_InterruptEndpoints[0]->NextPhysicalEndpoint = m_IsoEndpointDescriptor->PhysicalAddress.LowPart;
|
m_InterruptEndpoints[0]->NextPhysicalEndpoint = m_IsoEndpointDescriptor->PhysicalAddress.LowPart;
|
||||||
|
|
||||||
|
//
|
||||||
|
// set iso endpoint type
|
||||||
|
//
|
||||||
|
m_IsoEndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
//
|
//
|
||||||
|
@ -1183,6 +1202,15 @@ CUSBHardwareDevice::AcquireDeviceLock(void)
|
||||||
return OldLevel;
|
return OldLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CUSBHardwareDevice::GetCurrentFrameNumber(
|
||||||
|
PULONG FrameNumber)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// store frame number
|
||||||
|
//
|
||||||
|
*FrameNumber = m_HCCA->CurrentFrameNumber;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CUSBHardwareDevice::ReleaseDeviceLock(
|
CUSBHardwareDevice::ReleaseDeviceLock(
|
||||||
|
|
|
@ -231,6 +231,8 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR
|
||||||
#define OHCI_ENDPOINT_FULL_SPEED 0x00000000
|
#define OHCI_ENDPOINT_FULL_SPEED 0x00000000
|
||||||
#define OHCI_ENDPOINT_DIRECTION_OUT 0x00000800
|
#define OHCI_ENDPOINT_DIRECTION_OUT 0x00000800
|
||||||
#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000
|
#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000
|
||||||
|
#define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000
|
||||||
|
#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
|
||||||
|
|
||||||
//
|
//
|
||||||
// Maximum port count set by OHCI
|
// Maximum port count set by OHCI
|
||||||
|
@ -293,3 +295,35 @@ typedef struct
|
||||||
#define OHCI_TD_CONDITION_BUFFER_OVERRUN 0x0c
|
#define OHCI_TD_CONDITION_BUFFER_OVERRUN 0x0c
|
||||||
#define OHCI_TD_CONDITION_BUFFER_UNDERRUN 0x0d
|
#define OHCI_TD_CONDITION_BUFFER_UNDERRUN 0x0d
|
||||||
#define OHCI_TD_CONDITION_NOT_ACCESSED 0x0f
|
#define OHCI_TD_CONDITION_NOT_ACCESSED 0x0f
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
// Isochronous transfer descriptor structure (section 4.3.2)
|
||||||
|
// --------------------------------
|
||||||
|
|
||||||
|
#define OHCI_ITD_NOFFSET 8
|
||||||
|
|
||||||
|
typedef struct _OHCI_ISO_TD_
|
||||||
|
{
|
||||||
|
|
||||||
|
// Hardware part 32 byte
|
||||||
|
ULONG Flags;
|
||||||
|
ULONG BufferPhysical; // Physical page number of byte 0
|
||||||
|
ULONG NextPhysicalDescriptor; // Next isochronous transfer descriptor
|
||||||
|
ULONG LastPhysicalByteAddress; // Physical buffer end
|
||||||
|
ULONG Offset[OHCI_ITD_NOFFSET]; // Buffer offsets
|
||||||
|
|
||||||
|
// Software part
|
||||||
|
PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor
|
||||||
|
struct _OHCI_ISO_TD_ * NextLogicalDescriptor; // Logical pointer next descriptor
|
||||||
|
}OHCI_ISO_TD, *POHCI_ISO_TD;
|
||||||
|
|
||||||
|
#define OHCI_ITD_GET_STARTING_FRAME(x) ((x) & 0x0000ffff)
|
||||||
|
#define OHCI_ITD_SET_STARTING_FRAME(x) ((x) & 0xffff)
|
||||||
|
#define OHCI_ITD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7)
|
||||||
|
#define OHCI_ITD_SET_DELAY_INTERRUPT(x) ((x) << 21)
|
||||||
|
#define OHCI_ITD_NO_INTERRUPT 0x00e00000
|
||||||
|
#define OHCI_ITD_GET_FRAME_COUNT(x) ((((x) >> 24) & 7) + 1)
|
||||||
|
#define OHCI_ITD_SET_FRAME_COUNT(x) (((x) - 1) << 24)
|
||||||
|
#define OHCI_ITD_GET_CONDITION_CODE(x) ((x) >> 28)
|
||||||
|
#define OHCI_ITD_NO_CONDITION_CODE 0xf0000000
|
||||||
|
|
||||||
|
|
|
@ -1119,7 +1119,10 @@ CHubController::HandleGetStatusFromDevice(
|
||||||
IN OUT PIRP Irp,
|
IN OUT PIRP Irp,
|
||||||
PURB Urb)
|
PURB Urb)
|
||||||
{
|
{
|
||||||
PUSHORT Status;
|
PUSHORT DeviceStatus;
|
||||||
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PUSBDEVICE UsbDevice;
|
||||||
|
|
||||||
//
|
//
|
||||||
// sanity checks
|
// sanity checks
|
||||||
|
@ -1127,22 +1130,54 @@ CHubController::HandleGetStatusFromDevice(
|
||||||
PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
|
PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
|
||||||
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
|
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
|
||||||
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
|
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
|
||||||
PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// get status buffer
|
// get status buffer
|
||||||
//
|
//
|
||||||
Status = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
|
DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME need more flags ?
|
||||||
|
//
|
||||||
|
*DeviceStatus = USB_PORT_STATUS_CONNECT;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME need more flags ?
|
// check if this is a valid usb device handle
|
||||||
//
|
//
|
||||||
*Status = USB_PORT_STATUS_CONNECT;
|
ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device
|
||||||
|
//
|
||||||
|
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// generate setup packet
|
||||||
|
//
|
||||||
|
CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
|
||||||
|
CtrlSetup.wValue.LowByte = 0;
|
||||||
|
CtrlSetup.wValue.HiByte = 0;
|
||||||
|
CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index;
|
||||||
|
CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
|
||||||
|
CtrlSetup.bmRequestType.B = 0x80;
|
||||||
|
|
||||||
|
//
|
||||||
|
// submit setup packet
|
||||||
|
//
|
||||||
|
Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
DPRINT1("CHubController::HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus);
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
//
|
//
|
||||||
return STATUS_SUCCESS;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
|
@ -1155,6 +1190,8 @@ CHubController::HandleClassDevice(
|
||||||
PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
|
PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
|
||||||
ULONG PortCount, Dummy2;
|
ULONG PortCount, Dummy2;
|
||||||
USHORT Dummy1;
|
USHORT Dummy1;
|
||||||
|
PUSBDEVICE UsbDevice;
|
||||||
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
|
|
||||||
DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
|
DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
|
||||||
|
|
||||||
|
@ -1163,6 +1200,36 @@ CHubController::HandleClassDevice(
|
||||||
//
|
//
|
||||||
switch(Urb->UrbControlVendorClassRequest.Request)
|
switch(Urb->UrbControlVendorClassRequest.Request)
|
||||||
{
|
{
|
||||||
|
case USB_REQUEST_GET_STATUS:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// check if this is a valid usb device handle
|
||||||
|
//
|
||||||
|
ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device
|
||||||
|
//
|
||||||
|
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// generate setup packet
|
||||||
|
//
|
||||||
|
CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
|
||||||
|
CtrlSetup.wValue.LowByte = Urb->UrbControlVendorClassRequest.Index;
|
||||||
|
CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
|
||||||
|
CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
|
||||||
|
CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
|
||||||
|
CtrlSetup.bmRequestType.B = 0xA0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// submit setup packet
|
||||||
|
//
|
||||||
|
Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case USB_REQUEST_GET_DESCRIPTOR:
|
case USB_REQUEST_GET_DESCRIPTOR:
|
||||||
{
|
{
|
||||||
switch (Urb->UrbControlVendorClassRequest.Value >> 8)
|
switch (Urb->UrbControlVendorClassRequest.Value >> 8)
|
||||||
|
|
|
@ -188,6 +188,15 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
|
||||||
|
|
||||||
virtual NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
|
virtual NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// GetIsochronousHeadEndpointDescriptor
|
||||||
|
//
|
||||||
|
// Description: returns the control head endpoint descriptor
|
||||||
|
|
||||||
|
virtual NTSTATUS GetIsochronousHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// GetInterruptEndpointDescriptors
|
// GetInterruptEndpointDescriptors
|
||||||
|
@ -301,6 +310,14 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
|
||||||
// Description: releases the device lock
|
// Description: releases the device lock
|
||||||
|
|
||||||
virtual void ReleaseDeviceLock(KIRQL OldLevel) = 0;
|
virtual void ReleaseDeviceLock(KIRQL OldLevel) = 0;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// GetCurrentFrameNumber
|
||||||
|
//
|
||||||
|
// Description: returns the current frame number
|
||||||
|
|
||||||
|
virtual VOID GetCurrentFrameNumber(PULONG FrameNumber) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef IUSBHardwareDevice *PUSBHARDWAREDEVICE;
|
typedef IUSBHardwareDevice *PUSBHARDWAREDEVICE;
|
||||||
|
|
|
@ -61,6 +61,7 @@ protected:
|
||||||
PUSBHARDWAREDEVICE m_Hardware; // hardware
|
PUSBHARDWAREDEVICE m_Hardware; // hardware
|
||||||
POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor; // bulk head descriptor
|
POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor; // bulk head descriptor
|
||||||
POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor; // control head descriptor
|
POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor; // control head descriptor
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor; // isochronous head descriptor
|
||||||
POHCI_ENDPOINT_DESCRIPTOR * m_InterruptEndpoints;
|
POHCI_ENDPOINT_DESCRIPTOR * m_InterruptEndpoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,6 +101,9 @@ CUSBQueue::Initialize(
|
||||||
//
|
//
|
||||||
Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
|
Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
|
||||||
|
|
||||||
|
//
|
||||||
|
Hardware->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor);
|
||||||
|
|
||||||
//
|
//
|
||||||
// get interrupt endpoints
|
// get interrupt endpoints
|
||||||
//
|
//
|
||||||
|
@ -164,6 +168,8 @@ CUSBQueue::AddUSBRequest(
|
||||||
KIRQL OldLevel;
|
KIRQL OldLevel;
|
||||||
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
|
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
|
||||||
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
|
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
|
||||||
|
POHCI_ISO_TD CurrentDescriptor;
|
||||||
|
ULONG FrameNumber;
|
||||||
|
|
||||||
DPRINT("CUSBQueue::AddUSBRequest\n");
|
DPRINT("CUSBQueue::AddUSBRequest\n");
|
||||||
|
|
||||||
|
@ -177,39 +183,6 @@ CUSBQueue::AddUSBRequest(
|
||||||
//
|
//
|
||||||
Type = Request->GetTransferType();
|
Type = Request->GetTransferType();
|
||||||
|
|
||||||
//
|
|
||||||
// check if supported
|
|
||||||
//
|
|
||||||
switch(Type)
|
|
||||||
{
|
|
||||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
|
||||||
/* NOT IMPLEMENTED IN QUEUE */
|
|
||||||
Status = STATUS_NOT_SUPPORTED;
|
|
||||||
break;
|
|
||||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
|
||||||
case USB_ENDPOINT_TYPE_CONTROL:
|
|
||||||
case USB_ENDPOINT_TYPE_BULK:
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* BUG */
|
|
||||||
PC_ASSERT(FALSE);
|
|
||||||
Status = STATUS_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// check for success
|
|
||||||
//
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// request not supported, please try later
|
|
||||||
//
|
|
||||||
DPRINT1("Request Type %x not supported\n", Type);
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// add extra reference which is released when the request is completed
|
// add extra reference which is released when the request is completed
|
||||||
//
|
//
|
||||||
|
@ -258,6 +231,48 @@ CUSBQueue::AddUSBRequest(
|
||||||
HeadDescriptor = FindInterruptEndpointDescriptor(Request->GetInterval());
|
HeadDescriptor = FindInterruptEndpointDescriptor(Request->GetInterval());
|
||||||
ASSERT(HeadDescriptor);
|
ASSERT(HeadDescriptor);
|
||||||
}
|
}
|
||||||
|
else if (Type == USB_ENDPOINT_TYPE_ISOCHRONOUS)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get head descriptor
|
||||||
|
//
|
||||||
|
HeadDescriptor = m_IsoHeadEndpointDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current frame number
|
||||||
|
//
|
||||||
|
m_Hardware->GetCurrentFrameNumber(&FrameNumber);
|
||||||
|
|
||||||
|
//
|
||||||
|
// increment frame number
|
||||||
|
//
|
||||||
|
FrameNumber++;
|
||||||
|
|
||||||
|
//
|
||||||
|
// apply frame number to iso transfer descriptors
|
||||||
|
//
|
||||||
|
CurrentDescriptor = (POHCI_ISO_TD)Descriptor->HeadLogicalDescriptor;
|
||||||
|
|
||||||
|
DPRINT1("ISO: NextFrameNumber %x\n", FrameNumber);
|
||||||
|
|
||||||
|
while(CurrentDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set current frame number
|
||||||
|
//
|
||||||
|
CurrentDescriptor->Flags |= OHCI_ITD_SET_STARTING_FRAME(FrameNumber);
|
||||||
|
|
||||||
|
//
|
||||||
|
// move to next frame number
|
||||||
|
//
|
||||||
|
FrameNumber++;
|
||||||
|
|
||||||
|
//
|
||||||
|
// move to next descriptor
|
||||||
|
//
|
||||||
|
CurrentDescriptor = CurrentDescriptor->NextLogicalDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// insert endpoint at end
|
// insert endpoint at end
|
||||||
|
@ -269,9 +284,6 @@ CUSBQueue::AddUSBRequest(
|
||||||
//
|
//
|
||||||
Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
|
Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
|
||||||
|
|
||||||
DPRINT("Request %x Logical %x added to queue Queue %p Logical %x\n", Descriptor, Descriptor->PhysicalAddress.LowPart, HeadDescriptor, HeadDescriptor->PhysicalAddress.LowPart);
|
|
||||||
|
|
||||||
|
|
||||||
if (Type == USB_ENDPOINT_TYPE_CONTROL || Type == USB_ENDPOINT_TYPE_BULK)
|
if (Type == USB_ENDPOINT_TYPE_CONTROL || Type == USB_ENDPOINT_TYPE_BULK)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -280,6 +292,7 @@ CUSBQueue::AddUSBRequest(
|
||||||
m_Hardware->HeadEndpointDescriptorModified(Type);
|
m_Hardware->HeadEndpointDescriptorModified(Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,9 +57,11 @@ public:
|
||||||
NTSTATUS BuildSetupPacketFromURB();
|
NTSTATUS BuildSetupPacketFromURB();
|
||||||
NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
|
NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
|
||||||
NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
|
NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
|
||||||
|
NTSTATUS BuildIsochronousEndpoint(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
|
||||||
NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG BufferSize);
|
NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG BufferSize);
|
||||||
VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
|
VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
|
||||||
NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor);
|
NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor);
|
||||||
|
NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG FrameCount);
|
||||||
UCHAR GetEndpointAddress();
|
UCHAR GetEndpointAddress();
|
||||||
USHORT GetMaxPacketSize();
|
USHORT GetMaxPacketSize();
|
||||||
|
|
||||||
|
@ -243,6 +245,81 @@ CUSBRequest::InitializeWithIrp(
|
||||||
//
|
//
|
||||||
switch (Urb->UrbHeader.Function)
|
switch (Urb->UrbHeader.Function)
|
||||||
{
|
{
|
||||||
|
case URB_FUNCTION_ISOCH_TRANSFER:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// there must be at least one packet
|
||||||
|
//
|
||||||
|
ASSERT(Urb->UrbIsochronousTransfer.NumberOfPackets);
|
||||||
|
|
||||||
|
//
|
||||||
|
// is there data to be transferred
|
||||||
|
//
|
||||||
|
if (Urb->UrbIsochronousTransfer.TransferBufferLength)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Check if there is a MDL
|
||||||
|
//
|
||||||
|
if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create one using TransferBuffer
|
||||||
|
//
|
||||||
|
DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
|
||||||
|
m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
|
||||||
|
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!m_TransferBufferMDL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate mdl
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// build mdl for non paged pool
|
||||||
|
// FIXME: Does hub driver already do this when passing MDL?
|
||||||
|
//
|
||||||
|
MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// use provided mdl
|
||||||
|
//
|
||||||
|
m_TransferBufferMDL = Urb->UrbIsochronousTransfer.TransferBufferMDL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// save buffer length
|
||||||
|
//
|
||||||
|
m_TransferBufferLength = Urb->UrbIsochronousTransfer.TransferBufferLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set Length Completed to 0
|
||||||
|
//
|
||||||
|
m_TransferBufferLengthCompleted = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get endpoint descriptor
|
||||||
|
//
|
||||||
|
m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbIsochronousTransfer.PipeHandle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// completed initialization
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// luckily those request have the same structure layout
|
// luckily those request have the same structure layout
|
||||||
//
|
//
|
||||||
|
@ -525,6 +602,230 @@ CUSBRequest::FreeDescriptor(
|
||||||
m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
|
m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::CreateIsochronousTransferDescriptor(
|
||||||
|
POHCI_ISO_TD* OutDescriptor,
|
||||||
|
ULONG FrameCount)
|
||||||
|
{
|
||||||
|
POHCI_ISO_TD Descriptor;
|
||||||
|
PHYSICAL_ADDRESS DescriptorAddress;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate transfer descriptor
|
||||||
|
//
|
||||||
|
Status = m_DmaManager->Allocate(sizeof(OHCI_ISO_TD), (PVOID*)&Descriptor, &DescriptorAddress);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize descriptor, hardware part
|
||||||
|
//
|
||||||
|
Descriptor->Flags = OHCI_ITD_SET_FRAME_COUNT(FrameCount) | OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED);
|
||||||
|
Descriptor->BufferPhysical = 0;
|
||||||
|
Descriptor->NextPhysicalDescriptor = 0;
|
||||||
|
Descriptor->LastPhysicalByteAddress = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// software part
|
||||||
|
//
|
||||||
|
Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
|
||||||
|
Descriptor->NextLogicalDescriptor = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
*OutDescriptor = Descriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::BuildIsochronousEndpoint(
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
|
||||||
|
{
|
||||||
|
POHCI_ISO_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor;
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||||
|
ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PVOID Buffer;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PURB Urb;
|
||||||
|
|
||||||
|
DPRINT1("cp\n");
|
||||||
|
//
|
||||||
|
// get current irp stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
|
||||||
|
PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
|
||||||
|
PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
ASSERT(Urb);
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate endpoint descriptor
|
||||||
|
//
|
||||||
|
Status = AllocateEndpointDescriptor(&EndpointDescriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to create setup descriptor
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
DPRINT1("cp\n");
|
||||||
|
//
|
||||||
|
// get buffer
|
||||||
|
//
|
||||||
|
Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
|
||||||
|
ASSERT(Buffer);
|
||||||
|
|
||||||
|
DPRINT1("cp\n");
|
||||||
|
while(Index < Urb->UrbIsochronousTransfer.NumberOfPackets)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get number of packets remaining
|
||||||
|
//
|
||||||
|
NumberOfPackets = min(Urb->UrbIsochronousTransfer.NumberOfPackets - Index, OHCI_ITD_NOFFSET);
|
||||||
|
DPRINT1("cp Number Packets %lu\n", NumberOfPackets);
|
||||||
|
//
|
||||||
|
// allocate iso descriptor
|
||||||
|
//
|
||||||
|
Status = CreateIsochronousTransferDescriptor(&CurrentDescriptor, NumberOfPackets);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME: cleanup
|
||||||
|
// failed to allocate descriptor
|
||||||
|
//
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
DPRINT1("cp\n");
|
||||||
|
//
|
||||||
|
// initialize descriptor
|
||||||
|
//
|
||||||
|
CurrentDescriptor->BufferPhysical = (MmGetPhysicalAddress(Buffer).LowPart & ~ (PAGE_SIZE - 1));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get page offset
|
||||||
|
//
|
||||||
|
PageOffset = BYTE_OFFSET(MmGetPhysicalAddress(Buffer).LowPart);
|
||||||
|
DPRINT1("cp\n");
|
||||||
|
for(SubIndex = 0; SubIndex < NumberOfPackets; SubIndex++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// store buffer offset
|
||||||
|
//
|
||||||
|
CurrentDescriptor->Offset[SubIndex] = Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset + PageOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// increment packet offset
|
||||||
|
//
|
||||||
|
Index += NumberOfPackets;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if this is the last descriptor
|
||||||
|
//
|
||||||
|
if (Index == Urb->UrbIsochronousTransfer.NumberOfPackets)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// end of transfer
|
||||||
|
//
|
||||||
|
CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + m_TransferBufferLength - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// use start address of next packet - 1
|
||||||
|
//
|
||||||
|
CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset - 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// move buffer to next address
|
||||||
|
//
|
||||||
|
Buffer = (PVOID)((ULONG_PTR)Buffer + Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// is there a previous descriptor
|
||||||
|
//
|
||||||
|
if (PreviousDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// link descriptors
|
||||||
|
//
|
||||||
|
PreviousDescriptor->NextLogicalDescriptor = CurrentDescriptor;
|
||||||
|
PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// first descriptor
|
||||||
|
//
|
||||||
|
FirstDescriptor = CurrentDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// store as previous descriptor
|
||||||
|
//
|
||||||
|
PreviousDescriptor = CurrentDescriptor;
|
||||||
|
}
|
||||||
|
DPRINT1("cp\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// clear interrupt mask for last transfer descriptor
|
||||||
|
//
|
||||||
|
CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
|
||||||
|
|
||||||
|
//
|
||||||
|
// fire interrupt as soon transfer is finished
|
||||||
|
//
|
||||||
|
CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// set isochronous type
|
||||||
|
//
|
||||||
|
EndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
|
||||||
|
|
||||||
|
//
|
||||||
|
// now link descriptor to endpoint
|
||||||
|
//
|
||||||
|
EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
|
||||||
|
EndpointDescriptor->TailPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
|
||||||
|
EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
|
||||||
|
DPRINT1("cp\n");
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
*OutEndpointDescriptor = EndpointDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CUSBRequest::CreateGeneralTransferDescriptor(
|
CUSBRequest::CreateGeneralTransferDescriptor(
|
||||||
|
@ -1084,8 +1385,7 @@ CUSBRequest::GetEndpointDescriptor(
|
||||||
Status = BuildBulkInterruptEndpoint(OutDescriptor);
|
Status = BuildBulkInterruptEndpoint(OutDescriptor);
|
||||||
break;
|
break;
|
||||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||||
DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
|
Status = BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PC_ASSERT(FALSE);
|
PC_ASSERT(FALSE);
|
||||||
|
@ -1201,7 +1501,6 @@ VOID
|
||||||
CUSBRequest::CompletionCallback(
|
CUSBRequest::CompletionCallback(
|
||||||
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
||||||
{
|
{
|
||||||
POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
|
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PURB Urb;
|
PURB Urb;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue