?? cpipe.hpp
字號:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
// 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.
//
// Module Name:
// CPipe.hpp
//
// Abstract: Implements class for managing open pipes for UHCI
//
// CPipe (ADT)
// / \
// CQueuedPipe (ADT) CIsochronousPipe
// / | \
// / | \
// CControlPipe CInterruptPipe CBulkPipe
//
// Notes:
//
#ifndef __CPIPE_HPP__
#define __CPIPE_HPP__
#include <globals.hpp>
#include <cphysmem.hpp>
#include <pipeabs.hpp>
class CPipe;
class CIsochronousPipe;
class CQueuedPipe;
class CControlPipe;
class CInterruptPipe;
class CBulkPipe;
class CUHCIFrame;
class CUhcd;
struct _UHCD_TD;
struct _UHCD_QH;
//
// Frame List (Section 3.1 of UHCI spec)
//
// number of entries in the frame list - 1024
#define FRAME_LIST_LENGTH DWORD(0x400)
#define FRAME_LIST_LENGTH_MASK DWORD(0x3FF)
// each of the 1024 entries of the frame list is 32 bits
typedef ULONG FRAME_LIST_POINTER;
// this should come out to be 4Kb, and will be debug checked in the code
#define FRAME_LIST_SIZE_IN_BYTES DWORD(FRAME_LIST_LENGTH * sizeof(FRAME_LIST_POINTER))
// UHCI spec section 3.1.1 defines the structure of the Frame List Pointer
#define FRAME_LIST_POINTER_MASK DWORD(0xFFFFFFF0)
#define FRAME_LIST_POINTER_TERMINATE DWORD(1 << 0)
#define FRAME_LIST_POINTER_VALID DWORD(0 << 0)
#define FRAME_LIST_POINTER_QH DWORD(1 << 1)
#define FRAME_LIST_POINTER_TD DWORD(0 << 1)
//
// Transfer Descriptor for UHCI (Section 3.2 of UHCI spec)
//
typedef ULONG TD_LINK_POINTER_PHYSICAL_ADDRESS;
#define TD_LINK_POINTER_MASK DWORD(0xFFFFFFF0)
#define TD_LINK_POINTER_TERMINATE DWORD(1 << 0)
#define TD_LINK_POINTER_VALID DWORD(0 << 0)
#define TD_LINK_POINTER_QH DWORD(1 << 1)
#define TD_LINK_POINTER_TD DWORD(0 << 1)
#define TD_LINK_POINTER_DEPTH_FIRST DWORD(1 << 2)
#define TD_LINK_POINTER_BREADTH_FIRST DWORD(0 << 2)
typedef ULONG TD_BUFFER_PHYSICAL_ADDRESS;
typedef ULONG TD_PHYSICAL_ADDRESS;
typedef struct _UHCD_TD * PUHCD_TD;
typedef struct _UHCD_TD {
TD_LINK_POINTER_PHYSICAL_ADDRESS HW_paLink; // DWORD1 - link used by host controller
// to find next TD/QH to process
DWORD ActualLength:11; // DWORD2, 0 ..10 - actual amount of data transferred
// encoded in (n-1) form
DWORD Reserved_1:6; // DWORD2, 11..16
DWORD StatusField:6; // DWORD2, 17..22 - used to indicate done transfer's status
DWORD Active:1; // DWORD2, 23 - indicates whether transfer is active
DWORD InterruptOnComplete:1; // DWORD2, 24 - indicates to send USB interrupt when finished
DWORD Isochronous:1; // DWORD2, 25 - indicates Isochronous vs Queued transfer
DWORD LowSpeedControl:1; // DWORD2, 26 - indicates transfer to low speed device
DWORD ErrorCounter:2; // DWORD2, 27..28 - this field is decremented every time
// there is an error on the transfer
DWORD ShortPacketDetect:1; // DWORD2, 29 - indicates to allow ActualLength < MaxLength
DWORD ReservedMBZ:2; // DWORD2, 30..31
DWORD PID:8; // DWORD3, 0..7 - indicates SETUP/IN/OUT transfer
DWORD Address:7; // DWORD3, 8..14 - address of device to send transfer to
DWORD Endpoint:4; // DWORD3, 15..18 - endpoint on device to send transfer to
DWORD DataToggle:1; // DWORD3, 19 - used to send multipacket transfers
DWORD Reserved_2:1; // DWORD3, 20
DWORD MaxLength:11; // DWORD3, 21..31 - maximum data size to send/receive
TD_BUFFER_PHYSICAL_ADDRESS HW_paBuffer; // DWORD4 - phys addr of data buffer
// These 4 DWORDs are for software use
PUHCD_TD vaPrevIsochTD; // prev TD (only for Isoch)
PUHCD_TD vaNextTD; // next TD
DWORD dwUNUSED1; // unused for now
DWORD dwUNUSED2; // unused for now
} UHCD_TD;
// Status bits for StatusField in UHCD_TD
// Reserved bit is taken care of by Reserved_1 above
#define TD_STATUS_NO_ERROR DWORD(0)
#define TD_STATUS_BITSTUFF_ERROR DWORD(1 << 0)
#define TD_STATUS_CRC_TIMEOUT_ERROR DWORD(1 << 1)
#define TD_STATUS_NAK_RECEIVED DWORD(1 << 2)
#define TD_STATUS_BABBLE_DETECTED DWORD(1 << 3)
#define TD_STATUS_DATA_BUFFER_ERROR DWORD(1 << 4)
#define TD_STATUS_STALLED DWORD(1 << 5)
#define TD_STATUS_EVERY_ERROR DWORD(TD_STATUS_BITSTUFF_ERROR | TD_STATUS_CRC_TIMEOUT_ERROR | TD_STATUS_NAK_RECEIVED | TD_STATUS_BABBLE_DETECTED | TD_STATUS_DATA_BUFFER_ERROR | TD_STATUS_STALLED)
// For ErrorCounter field
#define TD_ERRORCOUNTER_NEVER_INTERRUPT DWORD(0)
#define TD_ERRORCOUNTER_INTERRUPT_AFTER_ONE DWORD(1)
#define TD_ERRORCOUNTER_INTERRUPT_AFTER_TWO DWORD(2)
#define TD_ERRORCOUNTER_INTERRUPT_AFTER_THREE DWORD(3)
// Active bit has its own field above
// TDs are 32 bytes long
#define TD_REQUIRED_SIZE_IN_BYTES DWORD(32)
// TDs must be aligned on 16 byte boundaries
#define TD_ALIGNMENT_BOUNDARY DWORD(16)
#define TD_ENDPOINT_MASK DWORD(0xF)
// constants for MaxLength field
#define TD_MAXLENGTH_MAX DWORD(0x4FF)
#define TD_MAXLENGTH_INVALID DWORD(0x7FE)
#define TD_MAXLENGTH_NULL_BUFFER DWORD(0x7FF)
// constants for ActualLength field (used for SW to maintain data integrity)
#define TD_ACTUALLENGTH_INVALID TD_MAXLENGTH_INVALID
// constants for the PID (Packet Identifcation) field
// see UHCI spec 3.2.3
#define TD_IN_PID DWORD(0x69)
#define TD_OUT_PID DWORD(0xE1)
#define TD_SETUP_PID DWORD(0x2D)
// Queue Head for UHCI (Section 3.3 of UHCI spec)
typedef ULONG QUEUE_HEAD_LINK_POINTER_PHYSICAL_ADDRESS;
#define QUEUE_HEAD_LINK_POINTER_MASK DWORD(0xFFFFFFF0)
#define QUEUE_HEAD_LINK_POINTER_TERMINATE DWORD(1 << 0)
#define QUEUE_HEAD_LINK_POINTER_VALID DWORD(0 << 0)
#define QUEUE_HEAD_LINK_POINTER_QH DWORD(1 << 1)
// #define QUEUE_HEAD_LINK_POINTER_TD DWORD(0 << 1) <- our QH's never point horizontally to TDs
typedef ULONG QUEUE_ELEMENT_LINK_POINTER_PHYSICAL_ADDRESS;
#define QUEUE_ELEMENT_LINK_POINTER_MASK DWORD(0xFFFFFFF0)
#define QUEUE_ELEMENT_LINK_POINTER_TERMINATE DWORD(1 << 0)
#define QUEUE_ELEMENT_LINK_POINTER_VALID DWORD(0 << 0)
// #define QUEUE_ELEMENT_LINK_POINTER_QH DWORD(1 << 1) <- our QH's never point vertically to QHs
#define QUEUE_ELEMENT_LINK_POINTER_TD DWORD(0 << 1)
typedef struct _UHCD_QH * PUHCD_QH;
typedef struct _UHCD_QH {
QUEUE_HEAD_LINK_POINTER_PHYSICAL_ADDRESS HW_paHLink; // phys addr of next QH
QUEUE_ELEMENT_LINK_POINTER_PHYSICAL_ADDRESS HW_paVLink; // phys addr of queued TD
// queue heads must be aligned on 16 byte boundaries. We'll make
// them 32 bytes long. These fields are for SW use only.
PUHCD_QH vaPrevQH; // virt addr of prev QH
PUHCD_QH vaNextQH; // virt addr of next QH
PUHCD_TD vaVertTD; // virt addr of queued TD
// dwInterruptTree is used for interrupt transfer QHs.
// For m_interruptQHTree members, which are just placeholders and
// do not actually carry transfers, the Load field will describe
// how much interrupt traffic follows the QH branch. For other
// QHs, the BranchIndex field will describe where in the tree the
// QH is located
union {
DWORD Load;
DWORD BranchIndex;
} dwInterruptTree;
DWORD dwUNUSED1; // unused...
DWORD dwUNUSED2; // unused...
} UHCD_QH;
// QHs must be aligned on 16 byte boundaries
#define QH_ALIGNMENT_BOUNDARY DWORD(16)
// THIS ***MUST*** BE A POWER OF TWO!!! It is the maximum number of milliseconds
// that can go between polling for an interrupt on a device. We use this
// to set up the interrupt queue tree. This tree contains 2*MAX_INTERRUPT_INTERVAL - 1
// nodes, and allows us to specify intervals of 1, 2, 4, 8, ..., MAX_INTERRUPT_INTERVAL
#define UHCD_MAX_INTERRUPT_INTERVAL UCHAR(32)
// structure used for managing busy pipes
typedef struct _PIPE_LIST_ELEMENT {
CPipe* pPipe;
struct _PIPE_LIST_ELEMENT * pNext;
} PIPE_LIST_ELEMENT, *PPIPE_LIST_ELEMENT;
struct STransfer {
// These are the IssueTransfer parameters
UCHAR address;
LPTRANSFER_NOTIFY_ROUTINE lpfnCallback;
LPVOID lpvCallbackParameter;
DWORD dwFlags;
LPCVOID lpvControlHeader;
DWORD paControlHeader;
DWORD dwStartingFrame;
DWORD dwFrames;
LPCDWORD aLengths;
DWORD dwBufferSize;
LPVOID lpvClientBuffer;
ULONG paClientBuffer;
LPCVOID lpvCancelId;
LPDWORD adwIsochErrors;
LPDWORD adwIsochLengths;
LPBOOL lpfComplete;
LPDWORD lpdwBytesTransferred;
LPDWORD lpdwError;
// additional parameters/data
PUCHAR vaTDList; // TD list for the transfer
USHORT numTDsInList; // # TDs in pTDListHead list
PUCHAR vaActualBuffer; // virt addr of buffer used by TD list
ULONG paActualBuffer; // phys addr of buffer used by TD list
DWORD dwCurrentPermissions;
struct STransfer * lpNextTransfer;
};
void InitializeTD( OUT PUHCD_TD const pTD,
IN const TD_LINK_POINTER_PHYSICAL_ADDRESS HW_paLink,
IN const PUHCD_TD vaNextTD,
IN const UCHAR InterruptOnComplete,
IN const UCHAR Isochronous,
IN const BOOL LowSpeedControl,
IN const DWORD PID,
IN const UCHAR Address,
IN const UCHAR Endpoint,
IN const USHORT DataToggle,
IN const DWORD MaxLength,
IN const TD_BUFFER_PHYSICAL_ADDRESS HW_paBuffer,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -