/* 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; iRcvInfo.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++;