⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpipe.hpp

📁 Latest USB 802.3, HID printer and mass storage divers from Microsoft for Platform Builder 4.2.
💻 HPP
📖 第 1 页 / 共 3 页
字号:
//
// 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 + -