?? ul_c450.c
字號:
/******************************************************************* uLan Communication - uL_DRV - multiplatform uLan driver ul_c450.c - chip driver for 16450 (C) Copyright 1996-2004 by Pavel Pisa - project originator http://cmp.felk.cvut.cz/~pisa (C) Copyright 1996-2004 PiKRON Ltd. http://www.pikron.com (C) Copyright 2002-2004 Petr Smolik The uLan driver project can be used and distributed in compliance with any of next licenses - GPL - GNU Public License See file COPYING for details. - LGPL - Lesser GNU Public License - MPL - Mozilla Public License - and other licenses added by project originator Code can be modified and re-distributed under any combination of the above listed licenses. If contributor does not agree with some of the licenses, he/she can delete appropriate line. WARNING: if you delete all lines, you are not allowed to distribute code or sources in any form. *******************************************************************//*******************************************************************//* Chip driver for 16450 */#include "serial_reg.h"#define u450_inb(base,port) ul_inb(base+port*U450_BYTES_PER_REGS)#define u450_outb(base,port,val) ul_outb(base+port*U450_BYTES_PER_REGS,val)#define U450_MCR_IE_C 0x0D /* receive */#define U450_MCR_OE_C 0x0E /* transmit */#define U450_MCR_OEQ_C 0x02 /* transmit ? */#define U450_MSR_RxD_C UART_MSR_CTS /* RxD line readback */#define U450_MSR_TxD_C UART_MSR_DSR /* TxD line readback */#define U450_MSR_DTxD_C UART_MSR_DDSR /* TxD line changed */#define U450_LCR_UL 0x3B /* receive/transmit */#define U450_LCR_ULC 0x2B /* transmit control character */#define U450_LCR_ULB 0x7B /* transmit line break */#define U450_LSR_C 0x04 /* controll character received */#define U450_LSR_ERR 0x1A /* error in receiver */#ifdef CONFIG_OC_UL_DRV_SYSLESS #define U450_FIX_RDI_GARBAGE(udrv,ret_code) \ do { if(ret_code==5) u450_inb(udrv->port,UART_RX); } while(0) #else /* CONFIG_OC_UL_DRV_SYSLESS */#define U450_FIX_RDI_GARBAGE(udrv,ret_code) do{;}while(0)#endif /* CONFIG_OC_UL_DRV_SYSLESS *//*Definitions to allow support converters with different pins routing*/#ifdef CONFIG_OC_UL_DRV_U450_VARPINS#define U450_CHOPT_MSRSWAP 0x2000#define U450_MCR_CODES chip_buff[4]#define U450_MSR_CODES chip_buff[5]#define U450_MCR_IE(udrv) ((uchar)(udrv->U450_MCR_CODES>>0))#define U450_MCR_OE(udrv) ((uchar)(udrv->U450_MCR_CODES>>8))#define U450_MCR_OEQ(udrv) ((uchar)(udrv->U450_MCR_CODES>>16))#define U450_MSR_RxD(udrv) ((uchar)(udrv->U450_MSR_CODES>>0))#define U450_MSR_TxD(udrv) ((uchar)(udrv->U450_MSR_CODES>>8))#define U450_MSR_DTxD(udrv) ((uchar)(udrv->U450_MSR_CODES>>16))#define U450_SET_MCR_CODES(udrv,ie,oe,oeq) \ (udrv->U450_MCR_CODES=(ie)<<0|(oe)<<8|(oeq)<<16)#define U450_SET_MSR_CODES(udrv,rxd,txd,dtxd) \ (udrv->U450_MSR_CODES=(rxd)<<0|(txd)<<8|(dtxd)<<16)#else /*CONFIG_OC_UL_DRV_U450_VARPINS*/#define U450_MCR_IE(udrv) U450_MCR_IE_C#define U450_MCR_OE(udrv) U450_MCR_OE_C#define U450_MCR_OEQ(udrv) U450_MCR_OEQ_C#define U450_MSR_RxD(udrv) U450_MSR_RxD_C#define U450_MSR_TxD(udrv) U450_MSR_TxD_C#define U450_MSR_DTxD(udrv) U450_MSR_DTxD_C#endif /*CONFIG_OC_UL_DRV_U450_VARPINS*//*** Test interrupt request state ***/int u450_pool(ul_drv *udrv){ unsigned u; u=u450_inb(udrv->port,UART_IIR); return (u&UART_IIR_NO_INT)?0:((u&UART_IIR_ID)|1);};/*** Wait end of transmit ***/int u450_weot(ul_drv *udrv, int ret_code){ int ret; unsigned u; uchar lsr_val; uchar uc; if(!udrv->chip_buff[0]|| !(u450_inb(udrv->port,UART_MCR)&U450_MCR_OEQ(udrv))) { UL_FRET; u450_outb(udrv->port,UART_LCR,U450_LCR_UL); return UL_RC_PROC; }; u450_outb(udrv->port,UART_IER,UART_IER_RDI); lsr_val=u450_inb(udrv->port,UART_LSR); ret=UL_RC_WIRQ; if(!(~lsr_val&(UART_LSR_THRE|UART_LSR_TEMT))) { LOG_CHIO(" TMI");// ret=UL_RC_PROC; /* was commented out */ } if(lsr_val&U450_LSR_ERR) ret=UL_RC_EFRAME; /* frame error */ if(lsr_val&UART_LSR_DR) { if((u=udrv->chip_buff[1])) udrv->chip_buff[1]=0; else if((u=udrv->chip_buff[0])) udrv->chip_buff[0]=0; uc=u450_inb(udrv->port,UART_RX); if((u^uc)&0xff||!u) { LOG_CHIO(" TE%c!",u?'0':'1'); ret=UL_RC_EBADCHR; }else{ LOG_CHIO("."); if(ret>=0&&!udrv->chip_buff[0]) ret=UL_RC_PROC; }; } else { U450_FIX_RDI_GARBAGE(udrv,ret_code); } if(ret!=UL_RC_WIRQ) { u450_outb(udrv->port,UART_LCR,U450_LCR_UL); UL_FRET; }; LOG_CHIO(" weot ret %d ",ret); return ret;};/*** Switch from receive to transmit ***/ int u450_sw_R2T_1(ul_drv *udrv, int ret_code); int u450_sw_R2T_2(ul_drv *udrv, int ret_code); int u450_sw_R2T_3(ul_drv *udrv, int ret_code);int u450_sw_R2T(ul_drv *udrv, int ret_code){ udrv->chip_buff[0]=udrv->chip_buff[1]=0; /* A_wait */ UL_FCALL2(u450_weot,u450_sw_R2T_1); return UL_RC_PROC;};int u450_sw_R2T_1(ul_drv *udrv, int ret_code){ uchar uc; if(ret_code<0) {UL_FRET;return ret_code;}; u450_outb(udrv->port,UART_MCR,U450_MCR_IE(udrv)); u450_outb(udrv->port,UART_IER,UART_IER_THRI); u450_outb(udrv->port,UART_TX,0); UL_FNEXT(u450_sw_R2T_2); uc=u450_inb(udrv->port,UART_LSR); if(uc&UART_LSR_THRE) return UL_RC_PROC; else return UL_RC_WIRQ;}; int u450_sw_R2T_2(ul_drv *udrv, int ret_code){ uchar uc, uc1; /* A_wait1: */ uc=u450_inb(udrv->port,UART_MSR); /* Need to be disabled for LPC210x */ if(uc&U450_MSR_TxD(udrv)) udrv->chip_temp&=~0x400; else udrv->chip_temp|=0x400; u450_outb(udrv->port,UART_IER,UART_IER_MSI); uc1=u450_inb(udrv->port,UART_LSR); if (!(~uc1&(UART_LSR_TEMT|UART_LSR_THRE))) { UL_FRET; return UL_RC_PROC; } #ifdef CONFIG_OC_UL_DRV_SYSLESS /* The next code seems to be required for LPC2148 UART */ if((!(uc&U450_MSR_TxD(udrv)))&&(uc1&UART_LSR_THRE)) { UL_FRET; return UL_RC_PROC; } #endif /*CONFIG_OC_UL_DRV_SYSLESS*/ UL_FNEXT(u450_sw_R2T_3); return UL_RC_WIRQ;}; int u450_sw_R2T_3(ul_drv *udrv, int ret_code){ uchar uc; #if 0 static int reported_bad_chip=0; #endif /* A_wait2: */ uc=u450_inb(udrv->port,UART_MSR); if(uc&U450_MSR_DTxD(udrv)) udrv->chip_temp&=~0x400; if((uc&U450_MSR_TxD(udrv))&&(udrv->chip_temp&0x400)) return UL_RC_WIRQ; #if 0 while(~u450_inb(udrv->port,UART_LSR)& (UART_LSR_TEMT|UART_LSR_THRE)) if(!reported_bad_chip++) LOG_FATAL(KERN_CRIT "uLan u450_sw_R2T_3 : problematic IC => looping in ISR\n"); #endif UL_FRET; return UL_RC_PROC;}; /*** Receive character into char_buff ***/ int u450_recch_1(ul_drv *udrv, int ret_code); int u450_recch_2(ul_drv *udrv, int ret_code);int u450_recch(ul_drv *udrv, int ret_code){ udrv->char_buff=0; if(u450_inb(udrv->port,UART_MCR)&U450_MCR_OEQ(udrv)) { UL_FCALL2(u450_weot,u450_recch_1); return UL_RC_PROC; }; UL_FNEXT(u450_recch_2); return UL_RC_PROC;}; int u450_recch_1(ul_drv *udrv, int ret_code){ u450_outb(udrv->port,UART_MCR,U450_MCR_IE(udrv)); if(ret_code<0) {UL_FRET;return ret_code;}; UL_FNEXT(u450_recch_2); return UL_RC_PROC;};INLINE int u450_recch_sub(ul_drv *udrv,int lsr_val,int rec_char){ /* helper function to process received character */ if(lsr_val&U450_LSR_C) udrv->last_ctrl=rec_char|=0x100; else udrv->last_ctrl&=0x7F; udrv->char_buff=rec_char; udrv->xor_sum^=rec_char;udrv->xor_sum++; if(lsr_val&U450_LSR_ERR) { LOG_CHIO(" ER:%03X",udrv->char_buff); return UL_RC_EFRAME; /* frame error */ }; LOG_CHIO(" R:%03X",udrv->char_buff); return UL_RC_PROC;}; int u450_recch_2(ul_drv *udrv, int ret_code){ uchar lsr_val; u450_outb(udrv->port,UART_IER,UART_IER_RDI); lsr_val=u450_inb(udrv->port,UART_LSR); if(!(lsr_val&UART_LSR_DR)) { U450_FIX_RDI_GARBAGE(udrv,ret_code); return UL_RC_WIRQ; } UL_FRET; return u450_recch_sub(udrv,lsr_val,u450_inb(udrv->port,UART_RX));};/*** Send character from char_buff ***/ int u450_sndch_1(ul_drv *udrv, int ret_code); int u450_sndch_2(ul_drv *udrv, int ret_code);int u450_sndch(ul_drv *udrv, int ret_code){ uchar uc; uc=(udrv->char_buff&0x100)?U450_LCR_ULC:U450_LCR_UL; if(u450_inb(udrv->port,UART_LCR)!=uc) { /* change between control and data character format */ if((u450_inb(udrv->port,UART_MCR)&U450_MCR_OEQ(udrv))) { /* wait to end of transmit */ UL_FCALL2(u450_weot,u450_sndch_1); return UL_RC_PROC; }else{ /* direction switch necessary */ udrv->chip_buff[0]=udrv->chip_buff[1]=0; UL_FCALL2(u450_sw_R2T_1,u450_sndch_1); UL_FCALL2(u450_weot,u450_sw_R2T_1); return UL_RC_PROC; }; }; if(!(u450_inb(udrv->port,UART_MCR)&U450_MCR_OEQ(udrv))) { /* direction switch necessary */ udrv->chip_buff[0]=udrv->chip_buff[1]=0; UL_FCALL2(u450_sw_R2T_1,u450_sndch_1); UL_FCALL2(u450_weot,u450_sw_R2T_1); } else UL_FNEXT(u450_sndch_1); return UL_RC_PROC;};int u450_sndch_1(ul_drv *udrv, int ret_code){ uchar uc; if(ret_code<0) {UL_FRET;return ret_code;}; u450_outb(udrv->port,UART_MCR,U450_MCR_OE(udrv)); if(udrv->char_buff&0x100) { /* store last ctrl for connect line busy/ready */ udrv->last_ctrl=udrv->char_buff; uc=U450_LCR_ULC; }else{ uc=U450_LCR_UL; }; udrv->chip_buff[1]=udrv->chip_buff[0]; udrv->chip_buff[0]=udrv->char_buff|0x1000; udrv->xor_sum^=udrv->char_buff;udrv->xor_sum++; u450_outb(udrv->port,UART_IER,UART_IER_THRI); u450_outb(udrv->port,UART_LCR,uc); /* control/data character */ u450_outb(udrv->port,UART_TX,(uchar)udrv->char_buff); LOG_CHIO(" T:%03X",udrv->char_buff); UL_FNEXT(u450_sndch_2); return UL_RC_WIRQ;}; int u450_sndch_2(ul_drv *udrv, int ret_code){ uchar uc; unsigned u; uc=u450_inb(udrv->port,UART_LSR); UL_FRET; if(uc&U450_LSR_ERR) return UL_RC_EFRAME; /* frame error */ if(!(uc&UART_LSR_DR)) { U450_FIX_RDI_GARBAGE(udrv,ret_code); return UL_RC_PROC; /* no char */ } if((u=udrv->chip_buff[1])) udrv->chip_buff[1]=0; else if((u=udrv->chip_buff[0])) udrv->chip_buff[0]=0; else return UL_RC_PROC; uc=u450_inb(udrv->port,UART_RX); if((u^uc)&0xff||!u) { LOG_CHIO(" TE%c!",u?'2':'3'); return UL_RC_EBADCHR; }; LOG_CHIO("."); return UL_RC_PROC;}; /*** Wait for time or received character ***/ int u450_wait_1(ul_drv *udrv, int ret_code); int u450_wait_2(ul_drv *udrv, int ret_code);int u450_wait(ul_drv *udrv, int ret_code){ udrv->char_buff=0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -