Author: janderwald
Date: Fri May 27 13:04:55 2011
New Revision: 51957
URL:
http://svn.reactos.org/svn/reactos?rev=51957&view=rev
Log:
[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
Modified:
branches/usb-bringup/drivers/usb/usbohci/hardware.cpp
branches/usb-bringup/drivers/usb/usbohci/hardware.h
branches/usb-bringup/drivers/usb/usbohci/hub_controller.cpp
branches/usb-bringup/drivers/usb/usbohci/interfaces.h
branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp
branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp
Modified: branches/usb-bringup/drivers/usb/usbohci/hardware.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hardware.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/hardware.cpp [iso-8859-1] Fri May 27 13:04:55
2011
@@ -62,7 +62,9 @@
NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR **
OutDescriptor);
NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR **
OutDescriptor);
NTSTATUS GetInterruptEndpointDescriptors(struct _OHCI_ENDPOINT_DESCRIPTOR ***
OutDescriptor);
+ NTSTATUS GetIsochronousHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR **
OutDescriptor);
VOID HeadEndpointDescriptorModified(ULONG HeadType);
+
NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager);
NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
@@ -80,6 +82,7 @@
KIRQL AcquireDeviceLock(void);
VOID ReleaseDeviceLock(KIRQL OldLevel);
+ virtual VOID GetCurrentFrameNumber(PULONG FrameNumber);
// local
BOOLEAN InterruptService();
NTSTATUS InitializeController();
@@ -698,6 +701,17 @@
return STATUS_SUCCESS;
}
+NTSTATUS
+CUSBHardwareDevice::GetIsochronousHeadEndpointDescriptor(
+ struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
+{
+ //
+ // get descriptor
+ //
+ *OutDescriptor = m_IsoEndpointDescriptor;
+ return STATUS_SUCCESS;
+}
+
VOID
CUSBHardwareDevice::HeadEndpointDescriptorModified(
ULONG Type)
@@ -847,6 +861,11 @@
// Now link the first endpoint to the isochronous endpoint
//
m_InterruptEndpoints[0]->NextPhysicalEndpoint =
m_IsoEndpointDescriptor->PhysicalAddress.LowPart;
+
+ //
+ // set iso endpoint type
+ //
+ m_IsoEndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
//
// done
@@ -1183,6 +1202,15 @@
return OldLevel;
}
+VOID
+CUSBHardwareDevice::GetCurrentFrameNumber(
+ PULONG FrameNumber)
+{
+ //
+ // store frame number
+ //
+ *FrameNumber = m_HCCA->CurrentFrameNumber;
+}
VOID
CUSBHardwareDevice::ReleaseDeviceLock(
Modified: branches/usb-bringup/drivers/usb/usbohci/hardware.h
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hardware.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/hardware.h [iso-8859-1] Fri May 27 13:04:55
2011
@@ -231,6 +231,8 @@
#define OHCI_ENDPOINT_FULL_SPEED 0x00000000
#define OHCI_ENDPOINT_DIRECTION_OUT 0x00000800
#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000
+#define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000
+#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
//
// Maximum port count set by OHCI
@@ -293,3 +295,35 @@
#define OHCI_TD_CONDITION_BUFFER_OVERRUN 0x0c
#define OHCI_TD_CONDITION_BUFFER_UNDERRUN 0x0d
#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
+
Modified: branches/usb-bringup/drivers/usb/usbohci/hub_controller.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hub_controller.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/hub_controller.cpp [iso-8859-1] Fri May 27
13:04:55 2011
@@ -1119,7 +1119,10 @@
IN OUT PIRP Irp,
PURB Urb)
{
- PUSHORT Status;
+ PUSHORT DeviceStatus;
+ USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+ NTSTATUS Status;
+ PUSBDEVICE UsbDevice;
//
// sanity checks
@@ -1127,22 +1130,54 @@
PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >=
sizeof(USHORT));
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
- PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL);
//
// get status buffer
//
- Status = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
-
- //
- // FIXME need more flags ?
- //
- *Status = USB_PORT_STATUS_CONNECT;
+ DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
+
+
+ if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
+ {
+ //
+ // FIXME need more flags ?
+ //
+ *DeviceStatus = USB_PORT_STATUS_CONNECT;
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // 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 = 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
//
- return STATUS_SUCCESS;
+ return Status;
}
//-----------------------------------------------------------------------------------------
@@ -1155,6 +1190,8 @@
PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
ULONG PortCount, Dummy2;
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);
@@ -1163,6 +1200,36 @@
//
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:
{
switch (Urb->UrbControlVendorClassRequest.Value >> 8)
Modified: branches/usb-bringup/drivers/usb/usbohci/interfaces.h
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/interfaces.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/interfaces.h [iso-8859-1] Fri May 27 13:04:55
2011
@@ -190,6 +190,15 @@
//-----------------------------------------------------------------------------------------
//
+// GetIsochronousHeadEndpointDescriptor
+//
+// Description: returns the control head endpoint descriptor
+
+ virtual NTSTATUS GetIsochronousHeadEndpointDescriptor(struct
_OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
+
+
+//-----------------------------------------------------------------------------------------
+//
// GetInterruptEndpointDescriptors
//
// Description: returns interrupt endpoint descriptors
@@ -301,6 +310,14 @@
// Description: releases the device lock
virtual void ReleaseDeviceLock(KIRQL OldLevel) = 0;
+
+//----------------------------------------------------------------------------------------
+//
+// GetCurrentFrameNumber
+//
+// Description: returns the current frame number
+
+ virtual VOID GetCurrentFrameNumber(PULONG FrameNumber) = 0;
};
typedef IUSBHardwareDevice *PUSBHARDWAREDEVICE;
Modified: branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/usb_queue.cpp [iso-8859-1] Fri May 27
13:04:55 2011
@@ -61,6 +61,7 @@
PUSBHARDWAREDEVICE m_Hardware;
// hardware
POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor;
// bulk head descriptor
POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor;
// control head descriptor
+ POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor;
// isochronous head descriptor
POHCI_ENDPOINT_DESCRIPTOR * m_InterruptEndpoints;
};
@@ -101,6 +102,9 @@
Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
//
+ Hardware->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor);
+
+ //
// get interrupt endpoints
//
Hardware->GetInterruptEndpointDescriptors(&m_InterruptEndpoints);
@@ -164,6 +168,8 @@
KIRQL OldLevel;
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
+ POHCI_ISO_TD CurrentDescriptor;
+ ULONG FrameNumber;
DPRINT("CUSBQueue::AddUSBRequest\n");
@@ -176,39 +182,6 @@
// get request type
//
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
@@ -258,6 +231,48 @@
HeadDescriptor = FindInterruptEndpointDescriptor(Request->GetInterval());
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
@@ -269,9 +284,6 @@
//
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)
{
//
@@ -279,6 +291,7 @@
//
m_Hardware->HeadEndpointDescriptorModified(Type);
}
+
return STATUS_SUCCESS;
}
Modified: branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/usb_request.cpp [iso-8859-1] Fri May 27
13:04:55 2011
@@ -57,9 +57,11 @@
NTSTATUS BuildSetupPacketFromURB();
NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR *
OutEndpointDescriptor);
NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR *
OutEndpointDescriptor);
+ NTSTATUS BuildIsochronousEndpoint(POHCI_ENDPOINT_DESCRIPTOR *
OutEndpointDescriptor);
NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG
BufferSize);
VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor);
+ NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG
FrameCount);
UCHAR GetEndpointAddress();
USHORT GetMaxPacketSize();
@@ -243,6 +245,81 @@
//
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
//
@@ -525,6 +602,230 @@
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
CUSBRequest::CreateGeneralTransferDescriptor(
@@ -1084,8 +1385,7 @@
Status = BuildBulkInterruptEndpoint(OutDescriptor);
break;
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
- DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
- Status = STATUS_NOT_IMPLEMENTED;
+ Status =
BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
break;
default:
PC_ASSERT(FALSE);
@@ -1201,7 +1501,6 @@
CUSBRequest::CompletionCallback(
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
{
- POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
PIO_STACK_LOCATION IoStack;
PURB Urb;