#help_index "Comm" #help_file "::/LT/Doc/Comm.TXZ" #define EXCP_TIMEOUT 0x100 #define EXCP_RESET 0x101 #define CH_XOFF 0x13 #define CH_XON 0x11 #define UART_THR 0 #define UART_RDR 0 #define UART_BRDL 0 #define UART_IER 1 #define UART_BRDH 1 #define UART_IIR 2 #define UART_LCR 3 #define UART_MCR 4 #define UART_LSR 5 #define UART_MSR 6 #define COMMf_INCOMING_XOFFED 0 #define COMMf_INCOMING_XOFFED2 1 #define COMMf_INCOMING_XOFFED3 2 #define COMMf_OUTGOING_XOFFED 3 #define COMMf_TX_XOFF 4 #define COMMf_TX_XON 5 U8 comm_base[5]={0,0x3F8,0x2F8,0x3E8,0x2E8}; U1Fifo *comm_Rx_fifos[5]={NULL,NULL,NULL,NULL,NULL}; U1Fifo *comm_Tx_fifos[5]={NULL,NULL,NULL,NULL,NULL}; U8 comm_flags[5]={0,0,0,0,0}; LTChnl *comm_chnls[5]={NULL,NULL,NULL,NULL,NULL}; public void RmtClose(LTChnl *chnl) { U8 base; U8 old_flags=GetFlags; if (!chnl || !chnl->type) return; if (chnl->type==LCT_COMM) { base=comm_base[chnl->port]; OutP(base+UART_IER,0); Cli; if (comm_Rx_fifos[chnl->port]) { DelU1Fifo(comm_Rx_fifos[chnl->port]); comm_Rx_fifos[chnl->port]=NULL; } if (comm_Tx_fifos[chnl->port]) { DelU1Fifo(comm_Tx_fifos[chnl->port]); comm_Tx_fifos[chnl->port]=NULL; } comm_chnls[chnl->port]=NULL; SetFlags(old_flags); } AFree(chnl); } public void CommPutChar(U8 port,U1 b) { U8 old_flags=GetFlags; U8 base=comm_base[port]; Cli; if (b==CH_XOFF) Bts(&comm_flags[port],COMMf_TX_XOFF); else if (b==CH_XON) Bts(&comm_flags[port],COMMf_TX_XON); else { if (U1FifoCnt(comm_Tx_fifos[port])>comm_Tx_fifos[port]->mask-4) { Sti; while (U1FifoCnt(comm_Tx_fifos[port])>comm_Tx_fifos[port]->mask>>1) SwapInNext; Cli; } if (Bt(&comm_flags[port],COMMf_OUTGOING_XOFFED)) { Sti; while (Bt(&comm_flags[port],COMMf_OUTGOING_XOFFED)) SwapInNext; Cli; } if (comm_Tx_fifos[port]) U1FifoInsert(comm_Tx_fifos[port],b); } OutP(base+UART_IER,3); //Enable TX & RX IRQ SetFlags(old_flags); } U8 dc_rx=0,dc_tx=0; void CommRxTxChar(U8 port) { U8 i=0,ch=0,irq,base=comm_base[port]; BoolU4 have_one; BoolU4 old_raw=Raw(ON); if (comm_Rx_fifos[port] && comm_Tx_fifos[port]) { while (i++<4) { irq=InP(base+UART_IIR); if ((irq & 0x07)==4) { //RX IRQ ch=InP(base+UART_RDR); if (ch==CH_XOFF) Bts(&comm_flags[port],COMMf_OUTGOING_XOFFED); else if (ch==CH_XON) Btr(&comm_flags[port],COMMf_OUTGOING_XOFFED); else { U1FifoInsert(comm_Rx_fifos[port],ch); if (U1FifoCnt(comm_Rx_fifos[port])>comm_Rx_fifos[port]->mask>>1) { CommPutChar(port,CH_XOFF); Bts(&comm_flags[port],COMMf_INCOMING_XOFFED2); Bts(&comm_flags[port],COMMf_INCOMING_XOFFED3); } } } else if ((irq & 0x07)==2) { //TX IRQ have_one=TRUE; if (Btr(&comm_flags[port],COMMf_TX_XOFF)) ch=CH_XOFF; else if (Btr(&comm_flags[port],COMMf_TX_XON)) ch=CH_XON; else if (!U1FifoRemove(comm_Tx_fifos[port],&ch)) have_one=FALSE; if (have_one) { if (ch==CH_XOFF) Bts(&comm_flags[port],COMMf_INCOMING_XOFFED); else if (ch==CH_XON) { if (!Btr(&comm_flags[port],COMMf_INCOMING_XOFFED3)) { if (!Btr(&comm_flags[port],COMMf_INCOMING_XOFFED2)) Btr(&comm_flags[port],COMMf_INCOMING_XOFFED); else Bts(&comm_flags[port],COMMf_TX_XON); } else Bts(&comm_flags[port],COMMf_TX_XON); } OutP(base+UART_THR,ch); } if (!U1FifoCnt(comm_Tx_fifos[port]) && !Bt(&comm_flags[port],COMMf_INCOMING_XOFFED)) OutP(base+UART_IER,1); //Enable RX IRQ } else break; } } Raw(old_raw); } void Irq03Handler() { CommRxTxChar(2); CommRxTxChar(4); } void Irq04Handler() { CommRxTxChar(1); CommRxTxChar(3); } public U1 CommGetChar(U8 port) { U8 ch=0; while (!U1FifoRemove(comm_Rx_fifos[port],&ch)) SwapInNext; if (Bt(&comm_flags[port],COMMf_INCOMING_XOFFED) && U1FifoCnt(comm_Rx_fifos[port])mask>>2) CommPutChar(port,CH_XON); return ch; } public BoolU4 CommScanChar(U8 port,U1 *ch) { U8 ch1=0; if (U1FifoPeek(comm_Rx_fifos[port],&ch1)) { U1FifoRemove(comm_Rx_fifos[port],&ch1); *ch=ch1; if (Bt(&comm_flags[port],COMMf_INCOMING_XOFFED) && U1FifoCnt(comm_Rx_fifos[port])mask>>2) CommPutChar(port,CH_XON); return TRUE; } else return FALSE; } void CommRmtPutChar(LTChnl *chnl,U1 b) { CommPutChar(chnl->port,b); } U1 CommRmtGetChar(LTChnl *chnl) { return CommGetChar(chnl->port); } BoolU8 CommRmtScanChar(LTChnl *chnl,U1 *ch) { return CommScanChar(chnl->port,ch); } public LTChnl *CommOpen8N1(U8 port=1,U8 baud=38400) { LTChnl *chnl=NULL; U8 old_flags=GetFlags,base=comm_base[port]; Cli; if (!port || port>4 || comm_chnls[port]) goto co_exit; chnl=AMAllocZ(sizeof(LTChnl)); comm_chnls[port]=chnl; chnl->type=LCT_COMM; base=comm_base[port]; chnl->port=port; chnl->baud=baud; chnl->PutChar=&CommRmtPutChar; chnl->GetChar=&CommRmtGetChar; chnl->ScanChar=&CommRmtScanChar; if (comm_Rx_fifos[chnl->port]) DelU1Fifo(comm_Rx_fifos[chnl->port]); if (comm_Tx_fifos[chnl->port]) DelU1Fifo(comm_Tx_fifos[chnl->port]); comm_flags[chnl->port]=0; comm_Rx_fifos[chnl->port]=NewU1Fifo(0x1000,adam_tss); //must be power of 2 comm_Tx_fifos[chnl->port]=NewU1Fifo(0x1000,adam_tss); //must be power of 2 OutP(base+UART_LCR,0); //Set for IER OutP(base+UART_IER,0); OutP(base+UART_LCR,0x80); //Enable baud rate control OutP(base+UART_BRDL,(0x180/(baud/300)) & 0xFF); //LSB OutP(base+UART_BRDH,(0x180/(baud/300)) / 256); //MSB OutP(base+UART_LCR,3); // 8-none-1 InP(base+UART_RDR); //read garbage InP(base+UART_LSR); OutP(base+UART_MCR,4); OutP(base+UART_IER,0); //DIsable all IRQ OutP(base+UART_MCR,0xA); //out2 and rts OutP(base+UART_IER,1); //Enable RX IRQ Bts(&comm_flags[chnl->port],COMMf_INCOMING_XOFFED); Bts(&comm_flags[chnl->port],COMMf_INCOMING_XOFFED2); Bts(&comm_flags[chnl->port],COMMf_INCOMING_XOFFED3); CommPutChar(chnl->port,CH_XON); co_exit: SetFlags(old_flags); return chnl; } public void CommClose(U8 port) { LTChnl *chnl=comm_chnls[port]; RmtClose(chnl); } ext[EXT_IRQ03]=&Irq03Handler; ext[EXT_IRQ04]=&Irq04Handler; #help_index ""