#include #include #include #include"uart.h" #ifndef __TURBOC__ #define enable() _enable() #define disable() _disable() #endif #define InBufSize 1024 #define OutBufSize 128 int iBase1=0,iBase2=0; /* com port base address */ int err1=0,err2=0; static unsigned long OldIntVect1=0L,OldIntVect2=0L; static unsigned char InData1[InBufSize]; static unsigned char OutData1[OutBufSize]; static unsigned char InData2[InBufSize]; static unsigned char OutData2[OutBufSize]; int In_InIdx1,In_OutIdx1,Out_InIdx1,Out_OutIdx1; int In_InIdx2,In_OutIdx2,Out_InIdx2,Out_OutIdx2; int save232[2][4]; unsigned long far *IntVect=(unsigned long far *)0L; void interrupt Serial1_Isr(void) { do{ switch(inp(iBase1+Iir)&0x07){ case 0: /* inp(iBase1+Msr); */ break; case 1: /* No interrupt to be service */ goto end; case 2: /* can send data */ if(Out_InIdx1!=Out_OutIdx1){ outp(iBase1,OutData1[Out_OutIdx1++]); Out_OutIdx1&=OutBufSize-1; if(Out_OutIdx1==Out_InIdx1) outp(iBase1+Ier, 0x01); } else { outp(iBase1+Ier, 0x01); } break; case 4: /* receive data */ ReadAgain: InData1[In_InIdx1++]=inp(iBase1); /* receive next char */ In_InIdx1&=(InBufSize-1); if(In_InIdx1==In_OutIdx1) { In_InIdx1--; In_InIdx1&=(InBufSize-1); err1=1; } if(inp(iBase1+Lsr) & 1) goto ReadAgain; break; case 6: inp(iBase1+Lsr); break; default: /* error status */ goto end; } }while(1); end: outp(0x20,0x20); } static unsigned char ratehi,ratelo,format; int GetBaudData(unsigned long baud, int data, int parity, int stop) { int cc; format=0; switch(data) { case 5: break; /* format+=0; */ case 6: format+=1; break; case 7: format+=2; break; case 8: format+=3; break; default: return(DataError); } switch(parity) { case 0: break; /* format+=0; */ case 1: format+=0x18; break; case 2: format+=0x10; break; default: return(ParityError); } switch(stop) { case 1: break; /* format+=0; */ case 2: format+=4; break; default: return(StopError); } switch(baud){ case 1200L : ratehi=0; ratelo=96; break; case 2400L : ratehi=0; ratelo=48; break; case 4800L : ratehi=0; ratelo=24; break; case 9600L : ratehi=0; ratelo=12; break; case 19200L: ratehi=0; ratelo=6; break; case 38400L: ratehi=0; ratelo=3; break; case 57600L: ratehi=0; ratelo=2; break; case 115200L: ratehi=0; ratelo=1; break; default : return BaudRateError; /* baud rate error */ } return NoError; } int InstallCom1(unsigned long baud, int data, int parity, int stop) { int cc; err1=0; cc=GetBaudData(baud,data,parity,stop); if(cc) return cc; /* _asm cli */ disable(); save232[0][2]=inp(iBase1+Lcr); /* format */ outp(iBase1+Lcr,0x80); /* 1 set DLAB (baud rate) */ save232[0][0]=inp(iBase1+Dll); /* baud rate */ save232[0][1]=inp(iBase1+Dlh); outp(iBase1+Dll,ratelo); outp(iBase1+Dlh,ratehi); outp(iBase1+Lcr,format); /* 2. data format */ save232[0][3]=inp(iBase1+Ier); /* interrupt status*/ outp(iBase1+Fcr, 0x87); /* 3. enable & clear FIFO */ outp(iBase1+Ier, 0x01); /* 4. enable COM1 interrupt */ outp(iBase1+Mcr,0x0b); /* set DTR line active */ In_InIdx1=In_OutIdx1=Out_InIdx1=Out_OutIdx1=0; /* 5. init QUEUE */ OldIntVect1=IntVect[12]; /* save old ISR */ IntVect[12]=(unsigned long)Serial1_Isr; /* install new ISR */ outp(0x21,inp(0x21) & 0xef); /* enable IRQ 4 for COM1 */ /*_asm sti */ enable(); return(NoError); } void interrupt Serial2_Isr(void) { do{ switch(inp(iBase2+Iir)&0x07){ case 0: /* inp(iBase2+Msr); */ break; case 1: /* No interrupt to be service */ goto end; case 2: /* can send data */ if(Out_InIdx2!=Out_OutIdx2){ outp(iBase2,OutData2[Out_OutIdx2++]); Out_OutIdx2&=OutBufSize-1; if(Out_OutIdx2==Out_InIdx2) outp(iBase2+Ier, 0x01); } else { outp(iBase2+Ier, 0x01); } break; case 4: /* receive data */ ReadAgain: InData2[In_InIdx2++]=inp(iBase2); /* receive next char */ In_InIdx2&=(InBufSize-1); if(In_InIdx2==In_OutIdx2) { In_InIdx2--; In_InIdx2&=(InBufSize-1); err2=1; } if(inp(iBase2+Lsr) & 1) goto ReadAgain; break; case 6: inp(iBase2+Lsr); break; default: /* error status */ goto end; } }while(1); end: outp(0x20,0x20); } int InstallCom2(unsigned long baud, int data, int parity, int stop) { int cc; err2=0; cc=GetBaudData(baud,data,parity,stop); if(cc) return cc; /* _asm cli */ disable(); save232[1][2]=inp(iBase2+Lcr); /* format */ outp(iBase2+Lcr,0x80); /* 1. set DLAB (baud rate) */ save232[1][0]=inp(iBase2+Dll); /* baud rate */ save232[1][1]=inp(iBase2+Dlh); outp(iBase2+Dll,ratelo); outp(iBase2+Dlh,ratehi); outp(iBase2+Lcr,format); /* 2. data format */ save232[1][3]=inp(iBase2+Ier); /* interrupt status */ outp(iBase2+Fcr, 0x87); /* 3. enable & clear FIFO */ outp(iBase2+Ier, 0x01); /* 4. enable COM1 interrupt */ outp(iBase2+Mcr,0x0b); /* set DTR line active */ In_InIdx2=In_OutIdx2=Out_InIdx2=Out_OutIdx2=0; /* 5. init QUEUE */ OldIntVect2=IntVect[11]; /* save old ISR */ IntVect[11]=(unsigned long)Serial2_Isr; /* install new ISR */ outp(0x21,inp(0x21) & 0xf7); /* enable IRQ 3 for COM2 */ /* _asm sti */ enable(); return(NoError); } /* ----------------------------------------------------------------------- // // input : port = 1/2, 3/4 not support // baud = 1200/2400/4800/9600/19200/38400 // chksum = 0 is DISABLE, others is ENABLE // return : 0 --> OK // 1 --> port value error // 2 --> baud rate error */ int InstallCom(int iPort,unsigned long lBaudRate,int iData,int iParity,int iStop) { int uart,i; char ratehi,ratelo; int cc; int far *ComBase=(int far *)0x00400000L; switch(iPort) { case 1 : if(OldIntVect1) RestoreCom(1); iBase1=ComBase[0]; return InstallCom1(lBaudRate,iData,iParity,iStop); case 2 : if(OldIntVect2) RestoreCom(2); iBase2=ComBase[1]; return InstallCom2(lBaudRate,iData,iParity,iStop); default: printf("Error:PortError,(iPort=%d)",iPort); getch(); return PortError; /* port must 1/2 */ } /*? for (i=0; i<8; i++) inportb(iBase+i); */ /* clear R */ } int RestoreCom(int iPort) { switch(iPort){ case 1: if(!OldIntVect1) return NoError; /* _asm cli */ disable(); IntVect[12]=OldIntVect1; /* 1. restore OLD ISR */ OldIntVect1=0L; outp(iBase1+Lcr,0x80); /* 2. restore baud rate */ outp(iBase1+Dll,save232[0][0]); outp(iBase1+Dlh,save232[0][1]); outp(iBase1+Lcr,(save232[0][2])&0x7f); /* 3. restore data format */ outp(iBase1+Ier, save232[0][3]);/* 4. restore enable COM1's interrupt */ outp(0x21,inp(0x21) | 0x10); /* mask IRQ 4 for COM1 */ /* _asm sti */ enable(); break; case 2: if(!OldIntVect2) return NoError; /* _asm cli */ disable(); IntVect[11]=OldIntVect2; /* 1. restore OLD ISR */ OldIntVect2=0L; outp(iBase2+Lcr,0x80); /* 2. restore baud rate */ outp(iBase2+Lcr,(save232[1][2])&0x7f); /* 3. restore data format */ outp(iBase2+Ier, save232[1][3]);/* 4. restore enable COM2's interrupt*/ outp(0x21,inp(0x21) | 0x08); /* mask IRQ 3 for COM2 */ /* _asm sti */ enable(); break; default: return PortError; } return NoError; } int IsCom(int iPort) { switch(iPort){ case 1: return In_InIdx1-In_OutIdx1; case 2: return In_InIdx2-In_OutIdx2; default: return PortError; } } long ToComTimeOut=100000L; int ToCom(int iPort, char data) { long t=ToComTimeOut; int nextidx,done; switch(iPort){ case 1: do{ _asm cli done=(nextidx=(Out_InIdx1+1)&(OutBufSize-1)) != Out_OutIdx1; if(done){ OutData1[Out_InIdx1]=data; Out_InIdx1=nextidx; } _asm sti t--; if(!t) break; } while(!done); if(done){ outp(iBase1+Lcr,inp(iBase1+Lcr)&0x7f); outp(iBase1+Ier, 0x03); /* enable COM1 interrupt */ return NoError; } else return TimeOut; break; case 2: do{ _asm cli done=(nextidx=(Out_InIdx2+1)&(OutBufSize-1)) != Out_OutIdx2; if(done){ OutData2[Out_InIdx2]=data; Out_InIdx2=nextidx; } _asm sti t--; if(!t) break; } while(!done); if(done){ outp(iBase2+Lcr,inp(iBase2+Lcr)&0x7f); outp(iBase2+Ier, 0x03); /* enable COM1 interrupt */ return NoError; } else return TimeOut; break; default: return PortError; } return NoError; } int ReadCom(int iPort) { unsigned data; switch(iPort){ case 1: while(!IsCom(iPort)){ ; } data=InData1[In_OutIdx1++]; In_OutIdx1&=(InBufSize-1); return data; case 2: while(!IsCom(iPort)){ ; } data=InData2[In_OutIdx2++]; In_OutIdx2&=(InBufSize-1); return data; default: return PortError; } } int ClearCom(int iPort) { switch(iPort){ case 1: In_OutIdx1=In_InIdx1=0; return NoError; case 2: In_OutIdx2=In_InIdx2=0; return NoError; default: return PortError; } }