?? ul_c950pci.c
字號:
/******************************************************************* uLan Communication - uL_DRV - multiplatform uLan driver ul_c950pci.c - chip driver for Oxford Semiconductor's OX16950 based pCI acards (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 OX16950-pci */#include "serial_reg.h"#define u950pci_inb(base,port) ul_inb(base+port)#define u950pci_outb(base,port,val) ul_outb(base+port,val)#define U950PCI_MCR_IE 0x08 /* receive 0x09 for Advantech */#define U950PCI_MCR_OE 0x09 /* transmit 0x08 for Advantech */#define U950PCI_MCR_TXDTRPOL 0x01#define U950PCI_LCR_UL 0x03 /* receive/transmit */#define U950PCI_LCR_ULB 0x43 /* transmit line break */#define U950PCI_LCR_EFR 0xBF /* enable access to EFR, XONx */#define U950PCI_LSR_C 0x04 /* controll character received */#define U950PCI_LSR_ERR 0x1A /* error in receiver */#define U950PCI_NMR_EN 0x03 /* 9-bit communication settings */#define U950PCI_IIR_ID 0x3f /* more IRQ levels */#define U950pci_MSR_RxD UART_MSR_RI /* Pin for RxD level sense *//* flags of chip options used in u950pci_init *//* unfortunate random DTR polarity over different vendors !!! */#define U950PCI_CHOPT_TXDTRNEG 1 /* negated polarity (Advantech) */#define U950PCI_CHOPT_HSPDOSC 2 /* oscilator 14.7456MHz/1.8432MHz */#define U950PCI_CHOPT_RXDONRI 4 /* RxD signal connected to RI */#define U950PCI_ACR_VAL chip_buff[2] /* shaddow buffer of ACR *//* default ACR value : DTR=1 when Tx, 950 trigger levels enable */#define U950PCI_ACR_UL (UART_ACR_TLENB)#define U950PCI_ACR_ULTX (U950PCI_ACR_UL|0x10|UART_ACR_RXDIS)/**/#define U950PCI_ACR_TXDTRPOL 0x08 /* ^- 0x18 for Advantech */#define U950PCI_STATE chip_buff[3] /* chip state information */#define U950PCI_STATE_TX 1#define U950PCI_STATE_FLUSH 2#define U950PCI_RX_ACRMCR chip_buff[4] /* set this for RX - LSB=ACR, MSB=MCR */ #define U950PCI_RX_ACR(udrv) ((uchar)udrv->U950PCI_RX_ACRMCR) #define U950PCI_RX_MCR(udrv) ((uchar)(udrv->U950PCI_RX_ACRMCR>>8))#define U950PCI_TX_ACRMCR chip_buff[5] /* set this for TX - LSB=ACR, MSB=MCR */ #define U950PCI_TX_ACR(udrv) ((uchar)udrv->U950PCI_TX_ACRMCR) #define U950PCI_TX_MCR(udrv) ((uchar)(udrv->U950PCI_TX_ACRMCR>>8))INLINE void u950pci_icr_write(ul_drv *udrv, int index, int val){ u950pci_outb(udrv->port,UART_SCR,(uchar)index); u950pci_outb(udrv->port,UART_ICR,(uchar)val);}unsigned u950pci_icr_read(ul_drv *udrv, int index){ unsigned val; u950pci_icr_write(udrv,UART_ACR,udrv->U950PCI_ACR_VAL|UART_ACR_ICRRD); u950pci_outb(udrv->port,UART_SCR,(uchar)index); val=u950pci_inb(udrv->port,UART_ICR); u950pci_icr_write(udrv,UART_ACR,udrv->U950PCI_ACR_VAL); return val;}unsigned u950pci_xfl_read(ul_drv *udrv, int reg){ unsigned val; u950pci_icr_write(udrv,UART_ACR,udrv->U950PCI_ACR_VAL|UART_ACR_ASREN); val=u950pci_inb(udrv->port,reg); /* no need to set ACR index - SCR not changed */ u950pci_outb(udrv->port,UART_ICR,(uchar)(udrv->U950PCI_ACR_VAL)); return val;}INLINE void u950pci_acr_write(ul_drv *udrv, int val){ udrv->U950PCI_ACR_VAL=val; u950pci_icr_write(udrv,UART_ACR,val); }int u950pci_rxd_cs(ul_drv *udrv){ /* returns 1 if active level detected */ if(!(udrv->chip_options&U950PCI_CHOPT_RXDONRI)) return 0; if(!(u950pci_inb(udrv->port,UART_MSR)&U950pci_MSR_RxD)); return 0; LOG_CHIO(" CSCD"); return 1;}/*** Test interrupt request state ***/int u950pci_pool(ul_drv *udrv){ unsigned u; u=u950pci_inb(udrv->port,UART_IIR); return (u&UART_IIR_NO_INT)?0:((u&U950PCI_IIR_ID)|1);};/*** Wait end of transmit ***/int u950pci_weot(ul_drv *udrv, int ret_code){ uchar lsr_val; lsr_val=u950pci_inb(udrv->port,UART_LSR); if(lsr_val&UART_LSR_TEMT){ UL_FRET; return UL_RC_PROC; } u950pci_icr_write(udrv,UART_TTL,0); /* transmittion FIFO treshold */ u950pci_outb(udrv->port,UART_IER,UART_IER_THRI); LOG_CHIO(".weot"); return UL_RC_WIRQ;};/* Help subroutine for switch from transmit to receive */int u950pci_recch_sub_tx2rx(ul_drv *udrv, int lsr_val){ if(lsr_val&UART_LSR_TEMT){ udrv->U950PCI_STATE&=~(U950PCI_STATE_TX|U950PCI_STATE_FLUSH); u950pci_outb(udrv->port,UART_FCR,UART_FCR_ENABLE_FIFO| UART_FCR_CLEAR_RCVR); /**/ u950pci_acr_write(udrv,U950PCI_RX_ACR(udrv)); return UL_RC_PROC; } u950pci_icr_write(udrv,UART_TTL,0); /* wait for TEMT */ u950pci_outb(udrv->port,UART_IER,UART_IER_THRI); LOG_CHIO(".t2r"); return UL_RC_WIRQ;}/* Help subroutine for reading 9-bit character */int u950pci_recch_sub_rec9bit(ul_drv *udrv, int lsr_val){ udrv->char_buff=u950pci_inb(udrv->port,UART_RX); if(lsr_val&U950PCI_LSR_C){ udrv->last_ctrl=udrv->char_buff|=0x100; /* last char for ready/busy */ } else udrv->last_ctrl&=0x7f; /* somebody other has line */ udrv->xor_sum^=udrv->char_buff;udrv->xor_sum++; if(lsr_val&U950PCI_LSR_ERR){ LOG_CHIO(" ER:%03X",udrv->char_buff); return UL_RC_EFRAME; /* frame error */ }else{ LOG_CHIO(" R:%03X",udrv->char_buff); return UL_RC_PROC; }}/*** Receive character into char_buff ***/int u950pci_recch(ul_drv *udrv, int ret_code){ uchar lsr_val; uchar rfl_val; udrv->char_buff=0; lsr_val=u950pci_inb(udrv->port,UART_LSR); LOG_CHIO(" lsr%02X",lsr_val); if(udrv->U950PCI_STATE& (U950PCI_STATE_TX|U950PCI_STATE_FLUSH)){ /* Manage all necessary for TX/RX switch */ return u950pci_recch_sub_tx2rx(udrv,lsr_val); } rfl_val=(uchar)u950pci_xfl_read(udrv,UART_RFL); LOG_CHIO(" rfl%02X",rfl_val); /*if(lsr_val&UART_LSR_DR){*/ if(rfl_val>0){ /* Construct and return 9-bit character */ UL_FRET; return u950pci_recch_sub_rec9bit(udrv,lsr_val); } LOG_CHIO("-"); u950pci_outb(udrv->port,UART_IER,UART_IER_RDI|UART_IER_RLSI); u950pci_icr_write(udrv,UART_RTL,6); /* receive FIFO treshold */ return UL_RC_WIRQ; /**/}/*** Send character from char_buff ***/ int u950pci_sndch_1(ul_drv *udrv, int ret_code);int u950pci_sndch(ul_drv *udrv, int ret_code){ unsigned u; uchar lsr_val; uchar tfl_val; lsr_val=u950pci_inb(udrv->port,UART_LSR); if(udrv->U950PCI_STATE&U950PCI_STATE_TX){ LOG_CHIO(" lsr%02X",lsr_val); /*if(lsr_val&UART_LSR_THRE){*/ tfl_val=(uchar)u950pci_xfl_read(udrv,UART_TFL); LOG_CHIO(" tfl%02X",tfl_val); if(tfl_val<0x08){ u=udrv->char_buff; udrv->xor_sum^=udrv->char_buff;udrv->xor_sum++; if(u&0x100){ udrv->last_ctrl=u; /* store last control char */ u950pci_outb(udrv->port,UART_SCR,1); } else u950pci_outb(udrv->port,UART_SCR,0); u950pci_outb(udrv->port,UART_TX,(uchar)u); UL_FRET; LOG_CHIO(" T:%03X",u); return UL_RC_PROC; } LOG_CHIO("-"); u950pci_outb(udrv->port,UART_IER,UART_IER_THRI); return UL_RC_WIRQ; } /* flush timing dummy transmit chars and manage 1 char switch delay*/ u950pci_outb(udrv->port,UART_FCR,UART_FCR_ENABLE_FIFO| UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT); u950pci_acr_write(udrv,U950PCI_RX_ACR(udrv)); u950pci_icr_write(udrv,UART_TTL,0); /* wait for TEMT */ u950pci_outb(udrv->port,UART_TX,0); u950pci_outb(udrv->port,UART_IER,UART_IER_THRI); UL_FNEXT(u950pci_sndch_1); LOG_CHIO(".r2t"); return UL_RC_WIRQ;} int u950pci_sndch_1(ul_drv *udrv, int ret_code){ uchar lsr_val; lsr_val=u950pci_inb(udrv->port,UART_LSR); if(~lsr_val&UART_LSR_TEMT) return UL_RC_WIRQ; /* finally setup for transmit */ udrv->U950PCI_STATE|=U950PCI_STATE_TX; u950pci_icr_write(udrv,UART_TTL,4); /* min 4 bytes in Tx FIFO */ u950pci_acr_write(udrv,U950PCI_TX_ACR(udrv)); UL_FNEXT(u950pci_sndch); return UL_RC_PROC;}/*** Wait for time or received character ***/ int u950pci_wait_1(ul_drv *udrv, int ret_code);int u950pci_wait(ul_drv *udrv, int ret_code){ int i; uchar lsr_val; uchar rfl_val; udrv->char_buff=0; lsr_val=u950pci_inb(udrv->port,UART_LSR); if(udrv->U950PCI_STATE& (U950PCI_STATE_TX|U950PCI_STATE_FLUSH)){ /* Manage all necessary for TX/RX switch */ return u950pci_recch_sub_tx2rx(udrv,lsr_val); } rfl_val=(uchar)u950pci_xfl_read(udrv,UART_RFL); LOG_CHIO(" w1rfl%02X",rfl_val); /*if(lsr_val&UART_LSR_DR){*/ if(rfl_val>0){ /* Construct and return 9-bit character */ UL_FRET; return u950pci_recch_sub_rec9bit(udrv,lsr_val); } /* flush Tx FIFO */ u950pci_outb(udrv->port,UART_FCR,UART_FCR_ENABLE_FIFO| UART_FCR_CLEAR_XMIT); u950pci_icr_write(udrv,UART_RTL,1); /* receive FIFO treshold */ u950pci_icr_write(udrv,UART_TTL,0); /* wait TEMT */ for(i=udrv->wait_time;i--;){ u950pci_outb(udrv->port,UART_TX,0); /* wait timed by dummy TX */ } u950pci_outb(udrv->port,UART_IER,UART_IER_RDI| UART_IER_RLSI|UART_IER_THRI); UL_FNEXT(u950pci_wait_1); LOG_CHIO("="); return UL_RC_WIRQ;}int u950pci_wait_1(ul_drv *udrv, int ret_code){ uchar lsr_val; uchar rfl_val; uchar tfl_val; lsr_val=u950pci_inb(udrv->port,UART_LSR); rfl_val=(uchar)u950pci_xfl_read(udrv,UART_RFL); LOG_CHIO(" w2rfl%02X",rfl_val); /*if(lsr_val&UART_LSR_DR){*/ if(rfl_val>0){ /* Construct and return 9-bit character */ UL_FRET; return u950pci_recch_sub_rec9bit(udrv,lsr_val); } tfl_val=(uchar)u950pci_xfl_read(udrv,UART_TFL); LOG_CHIO(" w3tfl%02X",tfl_val); if(tfl_val>0) return UL_RC_WIRQ; u950pci_outb(udrv->port,UART_FCR,UART_FCR_ENABLE_FIFO| UART_FCR_CLEAR_XMIT); UL_FRET; LOG_CHIO(" Timeout!"); return UL_RC_ETIMEOUT;};/*** Connect to RS485 bus ***/ int u950pci_connect_1(ul_drv *udrv, int ret_code); int u950pci_connect_2(ul_drv *udrv, int ret_code);int u950pci_connect(ul_drv *udrv, int ret_code){ unsigned u; u=udrv->last_ctrl;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -