/*******************************************************************/ /* */ /* Advanced Communication Borad Developer Toolkit */ /* (c)Copyright 1993-1995, Sealevel Systems Incorporated */ /* */ /*******************************************************************/ /* Please read the program abstract for details on this */ /* program. */ /* INT2.C */ /*******************************************************************/ #include #include #include #include #include #include #include #include "acb.h" #include "dma.h" #include "int.h" #include "buffer.h" #include "Z8530.h" /*******************************************************************/ /* Things to make the program "compiler friendly"! */ /*******************************************************************/ #define OUT _outp #define IN _inp /*******************************************************************/ /* Systems Resources */ /*******************************************************************/ #define PORTBASE 0x238 //BASE I/O #define IRQ 0x05 #define MAX_BUFFERS 10 #define BUFFER_LENGTH 100 #define MEMORY_REQUESTED ((MAX_BUFFERS) * (BUFFER_LENGTH) * (2)) #define TERM_COUNT 45 /*Test string length for Tx*/ #ifdef CHANNEL2 #define INT_PENDING 0x07 #define PORT PORTBASE + 2 #define PEND_EXT_INT 0x01 #define PEND_TX_INT 0x02 #define PEND_RX_INT 0x04 #else #define INT_PENDING 0x38 #define PORT PORTBASE #define PEND_EXT_INT 0x08 #define PEND_TX_INT 0x10 #define PEND_RX_INT 0x20 #endif /*******************************************************************/ /* Prototypes */ /*******************************************************************/ int PrintRxFrameInQueue(void); int QueueTxFrame(unsigned char __far * , unsigned short); void printbuf( unsigned char __far * buf, unsigned short wLength); int main(void); void __interrupt __far ACB_isr(void); static void SCCB_TxBufferEmpty (void); static void SCCB_ExtStatChange (void); static void SCCB_RxCharAvail (void); static void SCCB_SpRxCondition (void); static void SCCA_TxBufferEmpty (void); static void SCCA_ExtStatChange (void); static void SCCA_RxCharAvail (void); static void SCCA_SpRxCondition (void); /*******************************************************************/ /* Z85x30 Init Values */ /*******************************************************************/ #define PRAM_COUNT 56 unsigned char init[PRAM_COUNT]= {WR0,NULL_CODE, /* MODES */ WR4, X1_CLOCK | SYNC_MODE_ENABLE | SDLC_MODE, WR1, WAIT_DMA_DISABLE | INT_DISABLE, WR2, 0x00, /* not used in polled mode */ WR3, RX_8_BITS | RX_CRC_ENABLE | SYNC_CHAR_LOAD_INHIBIT , WR5, TX_8_BITS | CRC_SDLC | TX_CRC_ENABLE | RTS_ON, WR6, 0x00, /* not used-SDLC Address field */ WR7, 0x7e, /* SDLC Flag */ WR9, MI_DISABLE, WR10, CRC_PRESET_TO_ONE | FM0, WR11, TX_CLK_DPLL_OUT | RX_CLK_DPLL_OUT | TRXC_IS_OUTPUT | TRXC_OUT_BRG, WR12, 0x0e, /*time constant-low byte 19.2K bps*/ WR13, 0x0, /*time constant-high byte */ WR14, BRG_SOURCE_PCLK | DPLL_DISABLE_DPLL, WR14, BRG_SOURCE_PCLK | DPLL_FM_MODE, WR14, BRG_SOURCE_PCLK | DPLL_SOURCE_BRG, WR14, BRG_SOURCE_PCLK | DPLL_ENTER_SEARCH_MODE, WR14, BRG_ENABLE | BRG_SOURCE_PCLK | DPLL_NULL , /* ENABLES */ WR3, RX_8_BITS | RX_CRC_ENABLE | SYNC_CHAR_LOAD_INHIBIT | RX_ENABLE, WR5, TX_8_BITS | CRC_SDLC | TX_CRC_ENABLE | TX_ENABLE | RTS_ON, WR0, RESET_TX_CRC, WR0, ERROR_RESET, WR1, WAIT_DMA_DISABLE | INT_DISABLE, WR15, NO_EXT_STAT_INT, /*INTERRUPT*/ WR0, RESET_EXT_STATUS_INT, WR0, RESET_EXT_STATUS_INT, WR1, WAIT_DMA_DISABLE | INT_DISABLE, WR9, MI_DISABLE}; /*******************************************************************/ /* end of init table, adjust variable PRAM_COUNT after modifying */ /*******************************************************************/ unsigned char txbuff[]="The Quick Brown Fox Jumped Over The Lazy Dog.\0"; /*45 CHARACTERS INCLUDING '.' */ void __far *fp; void ( __interrupt __far *fpF)(void); /* far void function pointer */ int i; unsigned char c = 0; unsigned short number=0; unsigned char update[4]={'/', '|', '\\', '-'}; /* Must escape the "\" char*/ unsigned char updatePtr = 0; unsigned int RX_INT_COUNT,TX_INT_COUNT,RX_SP_INT_COUNT,EXT_STAT_INT_COUNT; unsigned int eof_flag = 0; /*End of Frame Flag - RX ISR */ unsigned short wTxIndex; int RestartTx=0; int RestartRx=0; int ParityError=0; int CRCError=0; int OverrunError=0; int RxFrameCount=0; int TxFrameCount=0; int ReturnValue=0; void __huge * fpMemoryBlock; unsigned char __far * fpMemory; struct DEVICE_INFO TxDevice; struct DEVICE_INFO RxDevice; fpDEVICE_INFO TxDevPtr; fpDEVICE_INFO RxDevPtr; struct BUFFER_INFO RxBuffer[MAX_BUFFERS]; struct BUFFER_INFO TxBuffer[MAX_BUFFERS]; /*******************************************************************/ /*******************************************************************/ int main (void) { printf("\nAdvanced Communication Board Interrupt Driven, Buffered Test Program.\n\n"); printf("Type \"T\" to transmit and \"X\" to exit to DOS.\n"); /*******************************************************************/ /* Verify Address of SCC (85x30) */ /*******************************************************************/ if(IN(PORT) == 0xff) {printf("\nError: Device not found at address %x HEX.\n",PORT); return(1); /*return code 1 for ERROR*/ } else printf("Device verified at address %x HEX.\n",PORT); /*******************************************************************/ /* Initialize ACB card */ /*******************************************************************/ SCCout(PORT, WR9, FORCE_HW_RESET); /*channel reset A and B*/ /*Initialize ACB */ SCCInitEx(PORT ,(unsigned char __far *)&init[0] ,PRAM_COUNT); printf("\nBase Address: %X, Rx DMA channel: 1 \n",PORT); /* Clean SCC FIFO, just a precaution */ while( RX_CHAR_AVAIL & (c = SCCin(PORT, RR0))) c = (unsigned char) IN(PORT); /* Allocate memory buffers */ fpMemoryBlock = _fmalloc(MEMORY_REQUESTED); /* For ACB-VI un-comment this line to enable on-board interrupts */ /* OUT(PORT+4, 0x40); */ SaveIRQMask(); /* Save the IRQ Mask*/ fpF = ACB_isr; /* Set isr far function pointer*/ IRQSetupEx(IRQ ,fpF); /*Save/Replace Interrupt Vector, etc. */ /* Setup Initial Interrupt Settings */ SCCout(PORT, WR1, RX_INT_ALL_CHAR_SP_COND | EXT_INT_ENABLE); SCCout(PORT, WR15, TX_UNDERRUN_IE); SCCout(PORT, WR0, RESET_EXT_STATUS_INT); SCCout(PORT, WR0, RESET_EXT_STATUS_INT); SCCout(PORT, WR9, MI_ENABLE); /* Z8530 Master Interrupt Enable*/ /* Setup memory buffers */ fpMemory = fpMemoryBlock; TxDevice.wTotal = 0; RxDevice.wTotal = 0; TxDevPtr = &TxDevice; RxDevPtr = &RxDevice; for (i = 0; i < MAX_BUFFERS; i++) {AddBuffer( TxDevPtr, &TxBuffer[i] ,fpMemory); fpMemory = (unsigned char __far* ) (fpMemory + BUFFER_LENGTH); AddBuffer( RxDevPtr, &RxBuffer[i] ,fpMemory); fpMemory = (unsigned char __far* ) (fpMemory + BUFFER_LENGTH); } StartBuffer( TxDevPtr, OUTPUT_DEVICE); StartBuffer( RxDevPtr, INPUT_DEVICE); /* Start the Receiver */ RxDevPtr->npNext_RED->wByteCount = 0; /* Here is the main loop of the program. Program execution will remain here until the 'X' is pressed from the keyboard. If 'T' is pressed, the transmit frame buffers will be filled with the test string. The receive frame buffers are continually monitored and dumped to the standard output device. */ do { c = 0; if(_bios_keybrd(_KEYBRD_READY)) {c=(unsigned char)_bios_keybrd(_KEYBRD_READ); switch(c) {case 'x': case 'X': c = 'x'; break; case 't': case 'T': /*Fill all Tx frame buffers*/ for(i = 0; i < MAX_BUFFERS; i++) {if(0==QueueTxFrame((unsigned char __far *)&txbuff,TERM_COUNT)) break; } break; default: break; } /*end switch case*/ } /*end if*/ PrintRxFrameInQueue(); /* if any frames, print them to video*/ if(number== 0x0fff) /*was 0x3fff*/ {number=0; /* PrintRxFrameInQueue();*/ printf("Tx Frames : %d , Rx Frames : %d",TxFrameCount,RxFrameCount); printf("%c\r",update[updatePtr]); /*print a cute little cursor*/ updatePtr++; if(updatePtr==4) updatePtr=0; } /* end if*/ number++; } while(c != 'x'); for(i = 0; i < MAX_BUFFERS; i++) /*Purge Rx Frame buffer*/ PrintRxFrameInQueue(); printf("Tx Frames : %d , Rx Frames : %d\n",TxFrameCount,RxFrameCount); /* Turn off Ints on the SCC*/ SCCout(PORT, WR14, BRG_ENABLE | BRG_SOURCE_PCLK ); SCCout(PORT ,WR9 ,MI_DISABLE); /*Master Interrupt Enable OFF*/ SCCout(PORT ,WR1 ,INT_DISABLE); /*All Interrupt conditions OFF*/ IRQUnsetup(IRQ); /*Restore Interrupt Vector, etc. */ ReturnIRQMask(); /*Restore IRQ Mask */ printf("\n\nTx DATA: "); printbuf((unsigned char __far *)&txbuff, TERM_COUNT); /* deallocate memory buffers*/ _ffree(fpMemoryBlock); printf("Special Rx Condition Interrupts : %d\n", RX_SP_INT_COUNT); printf("Tx Interrupts : %d\n", TX_INT_COUNT); printf("External Status Interrupts : %d\n", EXT_STAT_INT_COUNT); if(RX_INT_COUNT) printf("Rx Interrupts : %d\n", RX_INT_COUNT); if(RestartRx) printf("Rx Restarts: %d\n",RestartRx); if(RestartTx) printf("Tx Restarts: %d\n",RestartTx); if(ParityError) printf("Parity Error(s): %d\n",ParityError); if(OverrunError) printf("Rx Overrun Error(s): %d\n",OverrunError); if(CRCError) printf("CRC Error(s): %d\n",CRCError); if(CRCError || OverrunError || ParityError) ReturnValue = 1; return(ReturnValue); } /*******************************************************************/ /* This routine will print the specified buffer */ /* Note that a CR LF is added to the end. */ /*******************************************************************/ void printbuf( unsigned char __far * buf, unsigned short wLength) { unsigned int i; if(wLength > BUFFER_LENGTH) wLength = BUFFER_LENGTH; for (i = 0; i < wLength; i++) printf("%c", buf[i]); printf("\n"); } /*******************************************************************/ /* PrintRxFrameInQueue */ /* This routine will fetch a received frame from the Rx Frame */ /* buffer and display the contents on the screen. If no frames */ /* are available then a zero is returned. */ /*******************************************************************/ int PrintRxFrameInQueue(void) { unsigned char __far * fpTemp; fpTemp = AssignBuffer(RxDevPtr); if(fpTemp == NULL) return(0); printbuf(fpTemp,RxDevPtr->npCurrent->wByteCount); RxDevPtr->npCurrent->wByteCount = 0; /*reset wByteCount*/ if(BM_DEVICE_STOPPED == ReleaseBuffer(RxDevPtr)) {RestartRx++; SCCout(PORT, WR0, ERROR_RESET); SCCout(PORT, WR0, RESET_RX_CRC); } return(1); } /*******************************************************************/ /* QueueTxFrame */ /* This will queue the specified frame in the Tx Frame buffer. */ /*******************************************************************/ int QueueTxFrame(unsigned char __far * TxFrame,unsigned short wLength) { unsigned char __far * fpTemp; if(wLength > BUFFER_LENGTH) /* make sure we do not over fill */ wLength = BUFFER_LENGTH; /* the buffer*/ fpTemp = AssignBuffer(TxDevPtr); if(fpTemp == NULL) return(0); /* queue is full*/ else { _fmemmove(fpTemp, TxFrame, wLength); /*move the frame into our queue*/ TxDevPtr->npCurrent->wByteCount = wLength; if(BM_DEVICE_STOPPED == ReleaseBuffer(TxDevPtr)) /*if Tx is idle,*/ {RestartTx++; /*restart the transmitter*/ SCCout(PORT,WR0, RESET_TX_CRC); /* clear TX int. in case previous Tx left set*/ SCCout(PORT, WR0, RESET_TX_INT_PEND); /*enable Tx interrupts*/ SCCout(PORT, WR1, RX_INT_ALL_CHAR_SP_COND | EXT_INT_ENABLE | TX_INT_ENABLE); /*place first Tx character in Transmit buffer*/ OUT(PORT, *(TxDevPtr->npNext_RED->fpBufferAddress)); /* SCCout(PORT,WR8, *(TxDevPtr->npNext_RED->fpBufferAddress));*/ wTxIndex = 1; /*send second character in next Tx interrupt*/ } return(1); } } /*******************************************************************/ /* Interrupt Service Routine (ISR) */ /* This Routine is called when an interrupt is generated by the */ /* ACB adapter (SCC Based) */ /*******************************************************************/ void __interrupt __far ACB_isr(void) { static unsigned char isr_ptr, counter=0; while((isr_ptr=SCCin(PORTBASE, RR3)) & INT_PENDING) /* While Interrupt is Pending*/ { if(isr_ptr & PEND_RX_INT) SCCA_SpRxCondition(); if(isr_ptr & PEND_TX_INT) SCCA_TxBufferEmpty(); if(isr_ptr & PEND_EXT_INT) SCCA_ExtStatChange(); if(counter > 200) /* Time out just in case something*/ break; /* goes wrong. */ } counter = 0; /* Reset Time out counter */ #if (IRQ > 7) OUT(0xa0 ,0x20); /* AT PIC EOI */ #endif OUT(0x20, 0x20); /* XT PIC EOI */ } /*******************************************************************/ /* SCCA_TxBufferEmpty : called from ISR */ /* This routine is called when a Transmit Buffer Empty */ /* interrupt is pending on channel A of the SCC */ /*******************************************************************/ static void SCCA_TxBufferEmpty (void) { TX_INT_COUNT++; /* count for diagnostic purposes*/ /* There should be one Tx interrupt per Tx character*/ if(wTxIndex == TxDevPtr->npNext_RED->wByteCount) { /*turn off Tx interrupt*/ SCCout(PORT, WR1, RX_INT_ALL_CHAR_SP_COND | EXT_INT_ENABLE); SCCout(PORT, WR0, RESET_TX_INT_PEND); /*don't write to Tx buffer*/ /*we want a Tx underrun to occur*/ /*Reset TX Underun/End of Message latch so that the TX CRC will be sent when the Transmitter underruns after this byte*/ SCCout(PORT, WR0, RESET_TX_UR_EOM); } else { OUT(PORT, *(TxDevPtr->npNext_RED->fpBufferAddress+wTxIndex++)); } } /*******************************************************************/ /* SCCA_ExtStatChange : called from ISR */ /* This routine is called when a External Status Change */ /* interrupt is pending on channel A of the SCC */ /*******************************************************************/ static void SCCA_ExtStatChange (void) { /*External status interrupts, in this example will occur when the SCC loads the Transmitter with the CRC. On the Z8530 we must wait until this bit is shifted out before another DMA Tx transfer can be started or the two frames will be sent as one. Note that this is not the case on a Z85230 ESCC. */ TxFrameCount++; EXT_STAT_INT_COUNT++; /* count for diagnostic purposes*/ wTxIndex = 0; /*reset RED buffer index*/ SCCout(PORT, WR0, RESET_EXT_STATUS_INT); /*good practice to reset twice*/ SCCout(PORT, WR0, RESET_EXT_STATUS_INT); /*p. 8-2 "SCC User's Manual */ if(SwapBuffer(TxDevPtr)==BM_STOP_IO) /*setup for Tx next RED buffer*/ return; /*exit if wREDBuffers == 0 */ SCCout(PORT, WR1, RX_INT_ALL_CHAR_SP_COND | EXT_INT_ENABLE | TX_INT_ENABLE); } /*******************************************************************/ /* SCCA_RxCharAvail : called from ISR */ /* This routine will read all characters on channel A of the SCC */ /* at interrupt time */ /*******************************************************************/ static void SCCA_RxCharAvail (void) { /* Rx Chars are handled in the Sp_RxCondition routine */ } /*******************************************************************/ /* SCCA_SpRxCondition : called from ISR */ /* This routine is called when a Receive Special Condition */ /* interrupt is pending on channel A of the SCC */ /*******************************************************************/ static void SCCA_SpRxCondition (void) { unsigned char RR1_Image; RX_SP_INT_COUNT++; /* count for diagnostic purposes*/ RR1_Image = SCCin(PORT, RR1); if(RR1_Image & (PARITY_ERROR | RX_OVERRUN_ERROR | CRC_FRAMING_ERROR | END_OF_FRAME)) { SCCout(PORT, WR0, ERROR_RESET); if(RR1_Image & PARITY_ERROR) ParityError++; if(RR1_Image & RX_OVERRUN_ERROR) OverrunError++; if(RR1_Image & END_OF_FRAME) {if(RR1_Image & CRC_FRAMING_ERROR) CRCError++; else {RxFrameCount++; if(SwapBuffer(RxDevPtr)==BM_STOP_IO) {SCCout(PORT,WR0,RESET_HIGHEST_IUS); return; } RxDevPtr->npNext_RED->wByteCount=0xffff; /*Inc Buffer pointer*/ } } } /*end if for RR1 status*/ RX_INT_COUNT++; /* count for diagnostic purposes*/ /* Read Rx char and put it in the buffer*/ * (RxDevPtr->npNext_RED->fpBufferAddress+RxDevPtr->npNext_RED->wByteCount) = IN(PORT); /*Read Char*/ RxDevPtr->npNext_RED->wByteCount++; /*Inc Buffer pointer*/ } /*******************************************************************/ /* SCCB_TxBufferEmpty : called from ISR */ /* This routine is called when a Transmit Buffer Empty */ /* interrupt is pending on channel B of the SCC */ /*******************************************************************/ static void SCCB_TxBufferEmpty (void) { /*Channel B is not used in this program. */ } /*******************************************************************/ /* SCCB_ExtStatChange : called from ISR */ /* This routine is called when a External Status Change */ /* interrupt is pending on channel B of the SCC */ /*******************************************************************/ static void SCCB_ExtStatChange (void) { /*Channel B is not used in this program. */ } /*******************************************************************/ /* SCCB_RxCharAvail : called from ISR */ /* This routine will read all characters on channel B of the SCC */ /* at interrupt time */ /*******************************************************************/ static void SCCB_RxCharAvail (void) { /*Channel B is not used in this program. */ } /*******************************************************************/ /* SCCB_SpRxCondition : called from ISR */ /* This routine is called when a Receive Special Condition */ /* interrupt is pending on channel B of the SCC */ /*******************************************************************/ static void SCCB_SpRxCondition (void) { /*Channel B is not used in this program. */ } /*******************************************************************/ /* END OF FILE */ /*******************************************************************/