Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

337 lines
9.0 KiB

/*++
Copyright (c) 1999, 2000 Microsoft Corporation
Module Name:
async.c
Abstract:
miniport transfer code for sstool (single step tool) interface
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1999, 2000 Microsoft Corporation. All Rights Reserved.
Revision History:
1-1-00 : created, jdunn
--*/
#include "common.h"
typedef struct _SS_PACKET_CONTEXT {
MP_HW_POINTER Qh;
MP_HW_POINTER Td;
MP_HW_POINTER Data;
ULONG padTo8[2];
} SS_PACKET_CONTEXT, *PSS_PACKET_CONTEXT;
#define EHCI_TEST_TD_ALIGNMENT 256
C_ASSERT((sizeof(SS_PACKET_CONTEXT) <= EHCI_TEST_TD_ALIGNMENT));
C_ASSERT((sizeof(HCD_QUEUEHEAD_DESCRIPTOR) <= EHCI_TEST_TD_ALIGNMENT));
C_ASSERT((sizeof(HCD_TRANSFER_DESCRIPTOR) <= EHCI_TEST_TD_ALIGNMENT));
//implements the following miniport functions:
//non paged
//EHCI_StartSendOnePacket
//EHCI_EndSendOnePacket
USB_MINIPORT_STATUS
USBMPFN
EHCI_StartSendOnePacket(
PDEVICE_DATA DeviceData,
PMP_PACKET_PARAMETERS PacketParameters,
PUCHAR PacketData,
PULONG PacketLength,
PUCHAR WorkspaceVirtualAddress,
HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress,
ULONG WorkSpaceLength,
OUT USBD_STATUS *UsbdStatus
)
/*++
Routine Description:
insert structures to transmit a single packet -- this is for debug
tool purposes only so we can be a little creative here.
Arguments:
Return Value:
--*/
{
PHC_OPERATIONAL_REGISTER hcOp;
PHCD_QUEUEHEAD_DESCRIPTOR qh;
PHCD_TRANSFER_DESCRIPTOR td;
PUCHAR pch, data;
PSS_PACKET_CONTEXT context;
HW_LINK_POINTER hwQh, tdLink;
ULONG phys, qhPhys, tdPhys, dataPhys, i;
ULONG siz;
hcOp = DeviceData->OperationalRegisters;
// allocate an TD from the scratch space and
// initialize it
phys = WorkspacePhysicalAddress;
pch = WorkspaceVirtualAddress;
LOGENTRY(DeviceData, G, '_ssS', phys, 0, pch);
// specify a TD alignment to work around HW bugs.
siz = EHCI_TEST_TD_ALIGNMENT;
context = (PSS_PACKET_CONTEXT) pch;
pch += siz;
phys += siz;
// carve out a qh
qhPhys = phys;
qh = (PHCD_QUEUEHEAD_DESCRIPTOR) pch;
pch += siz;
phys += siz;
LOGENTRY(DeviceData, G, '_ssQ', qh, 0, qhPhys);
// carve out a TD
tdPhys = phys;
td = (PHCD_TRANSFER_DESCRIPTOR) pch;
pch += siz;
phys += siz;
LOGENTRY(DeviceData, G, '_ssT', td, 0, tdPhys);
// use the rest for data
LOGENTRY(DeviceData, G, '_ssD', PacketData, *PacketLength, 0);
dataPhys = phys;
data = pch;
RtlCopyMemory(data, PacketData, *PacketLength);
pch+=*PacketLength;
phys+=*PacketLength;
// init qh
RtlZeroMemory(qh, sizeof(*qh));
qh->PhysicalAddress = qhPhys;
ENDPOINT_DATA_PTR(qh->EndpointData) = NULL;
qh->Sig = SIG_HCD_DQH;
hwQh.HwAddress = qh->PhysicalAddress;
SET_QH(hwQh.HwAddress);
//qh->HwQH.EpChars.HeadOfReclimationList = 1;
// manual Toggle
qh->HwQH.EpChars.DataToggleControl = HcEPCHAR_Toggle_From_qTD;
// init the hw descriptor
qh->HwQH.EpChars.DeviceAddress =
PacketParameters->DeviceAddress;
qh->HwQH.EpChars.EndpointNumber =
PacketParameters->EndpointAddress;
qh->HwQH.EpCaps.HighBWPipeMultiplier = 1;
qh->HwQH.EpCaps.HubAddress = 0;
qh->HwQH.EpCaps.PortNumber = 0;
// link back to ourselves
//qh->HwQH.HLink.HwAddress = hwQh.HwAddress;
switch (PacketParameters->Speed) {
case ss_Low:
qh->HwQH.EpChars.EndpointSpeed = HcEPCHAR_LowSpeed;
qh->HwQH.EpCaps.HubAddress = PacketParameters->HubDeviceAddress;
qh->HwQH.EpCaps.PortNumber = PacketParameters->PortTTNumber;
break;
case ss_Full:
qh->HwQH.EpChars.EndpointSpeed = HcEPCHAR_FullSpeed;
qh->HwQH.EpCaps.HubAddress = PacketParameters->HubDeviceAddress;
qh->HwQH.EpCaps.PortNumber = PacketParameters->PortTTNumber;
break;
case ss_High:
qh->HwQH.EpChars.EndpointSpeed = HcEPCHAR_HighSpeed;
break;
default:
USBPORT_BUGCHECK(DeviceData);
}
// jdxxx
//qh->HwQH.EpChars.EndpointSpeed = HcEPCHAR_HighSpeed;
qh->HwQH.EpChars.MaximumPacketLength =
PacketParameters->MaximumPacketSize;
// init td
RtlZeroMemory(td, sizeof(*td));
for (i=0; i<5; i++) {
td->HwTD.BufferPage[i].ul = 0x0badf000;
}
td->PhysicalAddress = tdPhys;
td->Sig = SIG_HCD_TD;
switch(PacketParameters->Type) {
case ss_Setup:
LOGENTRY(DeviceData, G, '_sSU', 0, 0, 0);
td->HwTD.Token.Pid = HcTOK_Setup;
break;
case ss_In:
LOGENTRY(DeviceData, G, '_ssI', 0, 0, 0);
td->HwTD.Token.Pid = HcTOK_In;
break;
case ss_Out:
td->HwTD.Token.Pid = HcTOK_Out;
LOGENTRY(DeviceData, G, '_ssO', 0, 0, 0);
break;
case ss_Iso_In:
break;
case ss_Iso_Out:
break;
}
switch(PacketParameters->Toggle) {
case ss_Toggle0:
td->HwTD.Token.DataToggle = HcTOK_Toggle0;
break;
case ss_Toggle1:
td->HwTD.Token.DataToggle = HcTOK_Toggle1;
break;
}
// prime the overlay with td so that this td
// becomes the current td.
qh->HwQH.Overlay.qTD.Next_qTD.HwAddress =
td->PhysicalAddress;
td->HwTD.Token.Active = 1;
td->HwTD.Token.ErrorCounter = PacketParameters->ErrorCount;
// point TD at the data
td->HwTD.BufferPage[0].ul = dataPhys;
td->HwTD.Token.BytesToTransfer = *PacketLength;
tdLink.HwAddress = 0;
SET_T_BIT(tdLink.HwAddress);
td->HwTD.Next_qTD.HwAddress = tdLink.HwAddress;
td->HwTD.AltNext_qTD.HwAddress = tdLink.HwAddress;
QH_DESCRIPTOR_PTR(context->Qh) = qh;
TRANSFER_DESCRIPTOR_PTR(context->Td) = td;
HW_PTR(context->Data) = data;
*UsbdStatus = USBD_STATUS_SUCCESS;
// stick the QH in the schedule and wait for it to complete
// swap the async qh, wait one frame then
// replace the old value.
// NOTE: This will interrupt normal bus operation for one ms
//WRITE_REGISTER_ULONG(&hcOp->AsyncListAddr, hwQh.HwAddress);
EHCI_InsertQueueHeadInAsyncList(DeviceData, qh);
EHCI_EnableAsyncList(DeviceData);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
USBMPFN
EHCI_EndSendOnePacket(
PDEVICE_DATA DeviceData,
PMP_PACKET_PARAMETERS PacketParameters,
PUCHAR PacketData,
PULONG PacketLength,
PUCHAR WorkspaceVirtualAddress,
HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress,
ULONG WorkSpaceLength,
OUT USBD_STATUS *UsbdStatus
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PHC_OPERATIONAL_REGISTER hcOp;
PUCHAR pch;
PSS_PACKET_CONTEXT context;
HW_LINK_POINTER asyncHwQh;
PHCD_QUEUEHEAD_DESCRIPTOR qh;
PHCD_TRANSFER_DESCRIPTOR td;
PUCHAR data;
LOGENTRY(DeviceData, G, '_ssE', 0, 0, 0);
hcOp = DeviceData->OperationalRegisters;
context = (PSS_PACKET_CONTEXT) WorkspaceVirtualAddress;
qh = QH_DESCRIPTOR_PTR(context->Qh);
td = TRANSFER_DESCRIPTOR_PTR(context->Td);
data = HW_PTR(context->Data);
LOGENTRY(DeviceData, G, '_sE2', qh, td, *PacketLength );
asyncHwQh.HwAddress = DeviceData->AsyncQueueHead->PhysicalAddress;
SET_QH(asyncHwQh.HwAddress);
*PacketLength = *PacketLength - td->HwTD.Token.BytesToTransfer;
LOGENTRY(DeviceData, G, '_sE3', td->HwTD.Token.BytesToTransfer, td,
*PacketLength );
RtlCopyMemory(PacketData, data, *PacketLength);
EHCI_DisableAsyncList(DeviceData);
EHCI_RemoveQueueHeadFromAsyncList(DeviceData, qh);
// WRITE_REGISTER_ULONG(&hcOp->AsyncListAddr, asyncHwQh.HwAddress);
// return the error here
*UsbdStatus = USBD_STATUS_SUCCESS;
if (td->HwTD.Token.Halted == 1) {
if (td->HwTD.Token.XactErr) {
*UsbdStatus = USBD_STATUS_XACT_ERROR;
} else if (td->HwTD.Token.BabbleDetected) {
*UsbdStatus = USBD_STATUS_BABBLE_DETECTED;
} else if (td->HwTD.Token.DataBufferError) {
*UsbdStatus = USBD_STATUS_DATA_BUFFER_ERROR;
} else {
*UsbdStatus = USBD_STATUS_STALL_PID;
}
}
EHCI_KdPrint((DeviceData, 1, "'Status.XactErr %d\n",
td->HwTD.Token.XactErr));
EHCI_KdPrint((DeviceData, 1, "'Status.BabbleDetected %d\n",
td->HwTD.Token.BabbleDetected));
EHCI_KdPrint((DeviceData, 1, "'Status.DataBufferError %d\n",
td->HwTD.Token.DataBufferError));
return USBMP_STATUS_SUCCESS;
}