
/* semfddrb.h */

/*****************************************************************************/
/* NT IBM SDLC Adapter Device Driver: Receive buffer definitions */
/*****************************************************************************/

/*****************************************************************************/
/*                                                                           */
/* Receive buffer definitions                                                */
/*                                                                           */
/* For receive, the object of the design is to miss as few frames as possible*/
/* due to interrupt latency.                                                 */
/*                                                                           */
/* For PIO, this simply means that we service receiver at interrupt level    */
/* (rather than DPC level) and, because we are controlling the chip, if we   */
/* do overrun, we know about it immediately.                                 */
/*                                                                           */
/* For DMA, we have the vagary of the 8273 continuing to receive until       */
/* disabled.  Note that DMA only usable for SDLC: for HDLC, we have to be    */
/* full-duplex and, with only one DMA channel available, must use PIO.  The  */
/* design uses the 'carry on receiving' feature of the 8273 by               */
/*                                                                           */
/* - creating 2 buffers that will receive at least 9 SDLC frames (9*269)     */
/* - whenever we restart receiver, try to switch to t'other buffer if at all */
/*   possible (i.e. if t'other buffer not in use)                            */
/* - program the 8273 with a receive buffer size of the whole buffer at the  */
/*   start of aforementioned receive sequence, and let it rip!               */
/* - we only need to disable the receiver if it receives more than 8 full    */
/*   frames worth (which it shouldn't in SDLC).                              */
/*                                                                           */
/* Late note: As of NT265, MmAllocateContiguous memory wasn't working for    */
/* > 4K.  So reduce the rcvdatabuf_size so the whole RCVBUFFARRAY is < 4K.   */
/*****************************************************************************/

#define RCVDATABUF_SIZE ((DEFAULT_FRAME_SIZE*7)+20)
                                        /* 7 SDLC frames + final poll        */

typedef struct          _RCVBUF
{
   TRC_NAME             Name;           /* name for tracing-2 bytes. To make */
                                        /* macros work, always allocate      */
   struct _RCVBUF     * OtherBuffer;
   int                  FramesPut;      /* count of entries made in this buf */
                                        /* (includes error frames if they    */
                                        /* have to go into the buffer)       */
   int                  FramesGot;      /* how many frames pulled by Get     */
   PHYSICAL_ADDRESS     DataPhysAddr;   /* &Data as physical address         */
   UCHAR                Data [RCVDATABUF_SIZE];
}                       RCVBUF,
                     * PRCVBUF,
                        RCVBUFARRAY[2];

#define RCVBUF_INUSE(bufptr) (bufptr->FramesPut NE bufptr->FramesGot)

#define RCVBUF_INIT(pDX, index)                                                \
      {                                                                        \
        PRCVBUF pRcvBuf         = & pDX->RcvInfo.pRcvBufArray[index];          \
        pRcvBuf->Name[0]        = 'R';                                         \
        pRcvBuf->Name[1]        = CAST ('0'+(index),UCHAR);                    \
        ASSERT ((index & 0xFFFE) EQ 0); /* only 0 or 1 allowed               */\
        pRcvBuf->OtherBuffer    = &pDX->RcvInfo.pRcvBufArray[1-(index)];       \
        pRcvBuf->FramesPut      = 0;                                           \
        pRcvBuf->FramesGot      = 0;                                           \
        pRcvBuf->DataPhysAddr.LowPart = (ULONG)                                \
           & ((CAST(pDX->RcvInfo.RcvBufPhysAddr.LowPart,PRCVBUF))[index].Data[0]);\
        pRcvBuf->DataPhysAddr.HighPart= 0L;                                    \
        ASSERT ((pRcvBuf->DataPhysAddr.LowPart & ~0xFFFFFF) EQ 0L);            \
                                        /* should be within first 24 bits!   */\
        TRACE_OBJECT(In,pDX->RcvInfo.pRcvBufArray[index]);                     \
      }

/*****************************************************************************/
/*                                                                           */
/* The RFD (received frame descriptor is created a) at start of day, or b)   */
/* after every receive completion.  The NowBeingPut RFD describes the RFD we */
/* are receiving into (if receiver active) or will use when Receiver next    */
/* activated.  It is incomplete: the BufPtr and StartAddr are correct; but   */
/* the RcvdDataLength and SDLC* stuff will not be filled in until EORx.      */
/*                                                                           */
/* The RFD array uses the old SNAPS HMOD approach of having the interrupt    */
/* side increment NowBeingPut when a frame is correctly received and the     */
/* read routines increment NextToGet.                                        */
/*                                                                           */
/*****************************************************************************/

typedef struct          _RFD        /* received frame descriptor */
{
#ifdef IBMSYNC_TRACE
  TRC_NAME              Name;
#endif
  RCVBUF              * BufPtr;         /* pointer to the RCVBUF */
  UCHAR               * StartAddr;      /* &Data[StartIndex] */
  short                 StartIndex;     /* index in Data[] of Address byte */
  short                 RcvdDataLength; /* only valid if valid frame for RFD */
                                        /* received. This length is for data */
                                        /* only (as read from chip in bufferd*/
                                        /* mode).  User buffer needs 2 extra */
                                        /* bytes for A & C.                  */
  UCHAR                 SDLCAddressByte;
  UCHAR                 SDLCControlByte;
}                       RFD;

#define RFDARRAY_SIZE 9

/*****************************************************************************/
/* The RCVINFO stuff is not moved about as a structure: it is collected as a */
/* structure for ease of reference as there is so much of it.                */
/*****************************************************************************/

typedef struct          _RCVINFO
{
        PMDL            pRcvMdl;
        PRCVBUF         pRcvBufArray;       /* actually a ptr to RCVBUF [2]  */
        PHYSICAL_ADDRESS RcvBufPhysAddr;    /* -> start of whole RCVBUF array*/
                                            /* not just 'Data' area          */
        RFD             RFDArray [RFDARRAY_SIZE];

        short           RFDNowBeingPut;
        short           RFDNextToGet;
}                       RCVINFO;

#ifdef IBMSYNC_TRACE
#define RFDARRAY_INIT_NAMES(pDX)                                               \
                          {                                                    \
                            short i;                                           \
                            for (i=0; i<RFDARRAY_SIZE; i++)                    \
                            {                                                  \
                              pDX->RcvInfo.RFDArray[i].Name[0] = 'D';          \
                              pDX->RcvInfo.RFDArray[i].Name[1] = CAST('0'+i,   \
                                                                      UCHAR);  \
                            }                                                  \
                          }
#else
#define RFDARRAY_INIT_NAMES(pDX)
#endif

#define RCVINFO_INIT(pDX)                                                      \
                        { /* pRcvMdl,pRcvBufArray,PhysAddr set by AllocateDMA*/\
                                                                               \
                          RCVBUF_INIT(pDX, 0);                                 \
                          RCVBUF_INIT(pDX, 1);                                 \
                                                                               \
                          pDX->RcvInfo.RFDArray[0].BufPtr =                    \
                                                 &pDX->RcvInfo.pRcvBufArray[0];\
                          pDX->RcvInfo.RFDArray[0].StartIndex = 0;             \
                          pDX->RcvInfo.RFDArray[0].StartAddr =                 \
                                       &(pDX->RcvInfo.pRcvBufArray[0].Data[0]);\
                          pDX->RcvInfo.RFDArray[0].RcvdDataLength = -1;        \
                                                                    /* debug */\
                          RFDARRAY_INIT_NAMES(pDX);                            \
                                                                               \
                          pDX->RcvInfo.RFDNowBeingPut = 0;                     \
                          pDX->RcvInfo.RFDNextToGet   = 0;                     \
                                                                               \
                          TRACE_EVENT(InRF);                                   \
                        }

#define RFD_CAN_GET(pDX) (pDX->RcvInfo.RFDNextToGet NE pDX->RcvInfo.RFDNowBeingPut)

#define RFD_GOT(pDX) /* means: "We have pulled the data, move NextToGet on" */ \
{                                                                              \
   short *n = &pDX->RcvInfo.RFDNextToGet;                                      \
                                                                               \
   ASSERT(RFD_CAN_GET(pDX));                                                   \
   ASSERT(pDX->RcvInfo.RFDArray[*n].RcvdDataLength NE -1);                     \
                                                                               \
   TRACE_OBJECT(Rg, pDX->RcvInfo.RFDArray[*n]);                                \
                                                                               \
   TRACE_DWORD (pDX->RcvInfo.RFDArray[*n].StartAddr);                          \
                                                                               \
   pDX->RcvInfo.RFDArray[*n].BufPtr->FramesGot++; /* may now be able to      */\
                                                  /* refresh buffer          */\
                                                                               \
   *n = CAST((*n + 1) % RFDARRAY_SIZE, short);                                 \
 }

#define RFD_PUT(pDX) /* means: "We have put another frames "                 */\
   pDX->RcvInfo.RFDArray[pDX->RcvInfo.RFDNowBeingPut].BufPtr->FramesPut++;

