/******************************************************************** ** buffer.c ** ** Developers Toolkit 1995. ** ** ** ** (c)Copyright Sealevel Systems Incorporated, 1993 - 1995 ** ** ** ** Application turns Buffers from GREEN to RED and the ISR turns ** ** Buffers RED to GREEN ** ** Buffer Swaping Algorithm is described in "The Art of ** ** Computer Programming, Volume I", by Donald E. Knuth. ** ** (Addison-Wesley, 1973) ** ** The ISR uses the "Next RED" Buffer. ** ** NOTE: All buffer structs must be in the same segment. ** ** npCurrent ** ********************************************************************/ #include "buffer.h" #ifdef _BORLAND #define FAR far #else #define FAR __far #endif /******************************************************************** ** AddBuffer : Called from Application level ** ** This routine ** ** Passes: Far Pointer to DEVICE_INFO struct ** ** ** ** Returns: void ** ** ** ** NOTE: This routine will: ** ** If the buffer is the first ,save the near pointer to the first ** ** BUFFER_INFO struct, set npNext_RED, npNext_GREEN, npNextBuffer ** ** and npCurrent to the first buffer address. If the BUFFER_INFO ** ** struct is NOT the first, npNextBuffer is set to the last ** ** buffer added and npCurrent is set to the current buffer. ** ********************************************************************/ void AddBuffer( fpDEVICE_INFO fpDeviceInfo, npBUFFER_INFO npBufferInfo, unsigned char FAR * fpBuffer) { fpDeviceInfo->wTotal++; /* if this is our first buffer for the device*/ if (fpDeviceInfo->wTotal == 1) { fpDeviceInfo->npFirstBuffer = npBufferInfo; fpDeviceInfo->npNext_RED = npBufferInfo; fpDeviceInfo->npNext_GREEN = npBufferInfo; fpDeviceInfo->npCurrent = npBufferInfo; npBufferInfo->npNextBuffer = npBufferInfo; npBufferInfo->fpBufferAddress = fpBuffer; } /* else do this for all the rest of the buffers added*/ else { npBufferInfo->npNextBuffer = fpDeviceInfo->npCurrent; fpDeviceInfo->npCurrent = npBufferInfo; npBufferInfo->fpBufferAddress = fpBuffer; } } /******************************************************************** ** StartBuffer : Called from Application level ** ** This routine ** ** Passes: Far Pointer to DEVICE_INFO struct ** ** Defines Device as input or output. ** ** Returns: AX = BM_DEVICE_STOPPED if I/O needs to be started. ** ********************************************************************/ unsigned short StartBuffer( fpDEVICE_INFO fpDeviceInfo, unsigned char bDeviceType) { fpDeviceInfo->npFirstBuffer->npNextBuffer = fpDeviceInfo->npCurrent; fpDeviceInfo->wTimeOut = 0xFF; if (bDeviceType == INPUT_DEVICE) { fpDeviceInfo->bDeviceType = INPUT_DEVICE; fpDeviceInfo->bDeviceFlag = DEVICE_IS_RUNNING; fpDeviceInfo->wRedBuffers = fpDeviceInfo->wTotal; } else { fpDeviceInfo->bDeviceType = OUTPUT_DEVICE; fpDeviceInfo->bDeviceFlag = DEVICE_IS_STOPPED; fpDeviceInfo->wRedBuffers = 0; } return(BM_DEVICE_STOPPED); } /******************************************************************** ** AssignBuffer : ** ** AssignBuffer : Called from from Application level ** ** These routines will wait for a GREEN buffer to become ** ** available (until time out), then makes the current buffer ** ** pointer point to the next GREEN buffer, then the next GREEN** ** pointer is advanced to the next buffer in the ring. ** ** Passes: Far Pointer to DEVICE_INFO struct ** ** Returns: Address of Next Available Buffer to process ** ** IF wNumRed < wTotalBuffers THEN ** ** npCurrent = npNext_GREEN ** ** npNext_GREEN = Next Buffer in the Ring ** ** ELSE Repeat IF unitl Time-Out ** ********************************************************************/ unsigned char FAR * AssignBuffer( fpDEVICE_INFO fpDeviceInfo) { unsigned int i; npBUFFER_INFO npTemp; /* Wait for a RED Buffer to become available OR time out and return NULL */ for (i = 0; i < fpDeviceInfo->wTimeOut; i++) { if (fpDeviceInfo->wRedBuffers < fpDeviceInfo->wTotal) { /* Set current buffer to Next GREEN*/ fpDeviceInfo->npCurrent = fpDeviceInfo->npNext_GREEN; /* Advance Next GREEN pointer*/ npTemp = fpDeviceInfo->npNext_GREEN->npNextBuffer; fpDeviceInfo->npNext_GREEN = npTemp; /* Return Address of buffer to application */ return(fpDeviceInfo->npCurrent->fpBufferAddress); } } return(0); } /******************************************************************** ** ReleaseBuffer : Called from Application level ** ** This routine will increment the number of red buffers. ** ** Then check to see if I/O is busy. If yes ** ** Passes: Far Pointer to DEVICE_INFO struct ** ** Returns: 0 if device is OK, 1 if device needs to be restarted. ** ********************************************************************/ unsigned short ReleaseBuffer( fpDEVICE_INFO fpDeviceInfo) { fpDeviceInfo->wRedBuffers++; if (fpDeviceInfo->bDeviceType==INPUT_DEVICE) { if (fpDeviceInfo->bDeviceFlag == DEVICE_IS_RUNNING) { return(BM_DEVICE_OK); } else { return(BM_DEVICE_STOPPED); } } if (fpDeviceInfo->bDeviceType==OUTPUT_DEVICE) { if (fpDeviceInfo->wRedBuffers == 1) { return(BM_DEVICE_STOPPED); } else { return(BM_DEVICE_OK); } } } /******************************************************************** ** SwapBuffer : Called from Interrupt Service Routine (ISR) ** ** This routine will wait for a RED buffer to become ** ** available (until time out), then ** ** Passes: Far pointer to DEVICE_INFO struct ** ** Returns: 1 if OK to process do I/O ** ** Else 0 if no buffer is available ** ** NOTE: ISR always utilizes Next RED buffer ** ********************************************************************/ unsigned short SwapBuffer( fpDEVICE_INFO fpDeviceInfo) { npBUFFER_INFO npTemp; npTemp = fpDeviceInfo->npNext_RED->npNextBuffer; fpDeviceInfo->npNext_RED = npTemp; fpDeviceInfo->wRedBuffers--; if (fpDeviceInfo->wRedBuffers == 0) { fpDeviceInfo->bDeviceFlag = DEVICE_IS_STOPPED; return(BM_STOP_IO); /*stop device*/ } else { fpDeviceInfo->bDeviceFlag = DEVICE_IS_RUNNING; return(BM_DEVICE_OK); /*continue with I/O*/ } } /*******************************************************************/ void EraseBuffers( fpDEVICE_INFO fpDeviceInfo) { fpDeviceInfo->wTotal = 0; fpDeviceInfo->npCurrent = 0; fpDeviceInfo->wRedBuffers = 0; fpDeviceInfo->npFirstBuffer = 0; fpDeviceInfo->npNext_GREEN = 0; fpDeviceInfo->npNext_RED = 0; fpDeviceInfo->bDeviceType = 0; fpDeviceInfo->bDeviceFlag = 0; } /*******************************************************************/