📄 st16c554.c
字号:
/* * st16c554.c * * TWO ST16C554 driver for AMCC PPC405EP * * Author: Li Zhi You/Zhu jiang <godiscrazy@163.com> * Date : $Date: 2007/11/27 11:07:04 $ * * $Revision: 1.1V $ *ST16C554APN7.3728mhz扩展芯片:2*ST16C554可为系统增加8个串口,直接与PPC405EP总线连接,8位数据宽度地址空间:占用系统PC3地址从前到后分别对应每个UART0-7个寄存器UART0A:0xf0200020---0xf020027 A2A1A0(ST16C554) 0xf0200020 0 0 0 0xf0200021 0 0 1 0xf0200022 0 1 0 0xf0200023 0 1 1 0xf0200024 1 0 0 0xf0200025 1 0 1 0xf0200026 1 1 0 0xf0200027 1 1 1UART0B:0xf0200028---0xf020002fUART0C:0xf0200030---0xf0200037UART0D:0xf0200038---0xf020003fUART0E:0xf0200040---0xf020047 A2A1A0(ST16C554) 0xf0200040 0 0 0 0xf0200041 0 0 1 0xf0200042 0 1 0 0xf0200043 0 1 1 0xf0200044 1 0 0 0xf0200045 1 0 1 0xf0200046 1 1 0 0xf0200047 1 1 1UART0F:0xf0200048---0xf020004fUART0G:0xf0200050---0xf0200057UART0H:0xf0200058---0xf020005f控制寄存器Line-control register(LCR)0x03FIFO-control register(FCR)0x02Modem-control register(MCR)0x04Divisor-latch LSB(DLL)LCR(bit7=1)0x00Divisor-latch MSB(DLM)LCR(bit7=1)0x01Interrupt enable register(IER)0x01状态寄存器Line-status register(LSR)0x05Modem-status register(MSR)0x06数据寄存器Receiver-buffer register(RBR)0x00Transmitter-holding register(THR)0x00 */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <asm/processor.h>#include <platforms/ibm405ep.h>#include <platforms/ibm405lp.h>#include <linux/devfs_fs_kernel.h>#include <asm/io.h>#define ST0_A_READ 0#define ST0_B_READ 1#define ST0_C_READ 2#define ST0_D_READ 3#define ST1_A_READ 4#define ST1_B_READ 5#define ST1_C_READ 6#define ST1_D_READ 7#define ST0_A_WRITE 8#define ST0_B_WRITE 9#define ST0_C_WRITE 10#define ST0_D_WRITE 11#define ST1_A_WRITE 12#define ST1_B_WRITE 13#define ST1_C_WRITE 14#define ST1_D_WRITE 15#define ST_INIT 32typedef struct tagST_INIT{ int nChn; int nBaud; unsigned char byMode;} myST_INIT;myST_INIT st0A_init;myST_INIT st0B_init;myST_INIT st0C_init;myST_INIT st0D_init;myST_INIT st0E_init;myST_INIT st0F_init;myST_INIT st0G_init;myST_INIT st0H_init;#define NONEPARITY 0x00#define ODDPARITY 0x08#define EVENPARITY 0x18#define DATA7BIT 0x80#define BAUDBASE 0x30 /***4800bps->hex***/#define ST_COM_CNT 8#define ST_RECV_LEN 1600#define ST_SEND_LEN 160//以下定义与系统地址相关(与CPLD有关系)/* 68 mode interface HOW TO Select CHannel CS A4 A3 CHANNEL 1 0/1 0/1 None 0 0 0 A 0 0 1 B 0 1 0 C 0 1 1 D Internal Register is Decoded by A2 A1 A0; 具体定义见程序开头的宏定义 两片ST16C554都接在405EP的PCS3上, 用A6和A5来区分ST16C554 */ /*这里采用D、C、B、A及H、G、F、E的方式编号主要是为了满足板子 上串口定死的从左到右1——8顺序,并没有其它特殊含义*/#define YC_PHY_BASE_ADRR 0xf0200000 //映射基地址空间#define UcsAnd 0xffffff07 // addr(7)='0',addr(6)='0',addr(5)='0',addr(4)='0',addr(3)='0'#define Ucs_DChannel_Or 0x20 // addr(7)='0',addr(6)='0',addr(5)='1',addr(4)='0',addr(3)='0'#define Ucs_CChannel_Or 0x28 // addr(7)='0',addr(6)='0',addr(5)='1',addr(4)='0',addr(3)='1'#define Ucs_BChannel_Or 0x30 // addr(7)='0',addr(6)='0',addr(5)='1',addr(4)='1',addr(3)='0'#define Ucs_AChannel_Or 0x38 // addr(7)='0',addr(6)='0',addr(5)='1',addr(4)='1',addr(3)='1'#define Ucs_HChannel_Or 0x40 // addr(7)='0',addr(6)='1',addr(5)='0',addr(4)='0',addr(3)='0'#define Ucs_GChannel_Or 0x48 // addr(7)='0',addr(6)='1',addr(5)='0',addr(4)='0',addr(3)='1'#define Ucs_FChannel_Or 0x50 // addr(7)='0',addr(6)='1',addr(5)='0',addr(4)='1',addr(3)='0'#define Ucs_EChannel_Or 0x58 // addr(7)='0',addr(6)='1',addr(5)='0',addr(4)='1',addr(3)='1'#define YC_mul232_IRQ0 26 //中断号 IRQ1#define YC_mul232_IRQ1 30 //中断号 IRQ5#define delay_counter 100000 //用于写函数,写入一个字符寄存器先延时,然后再写下一个字符typedef struct { int nAddress0; int nAddress1; int sInited; unsigned char *pbyBase0; //数据寄存器 int RBR;//Receiver-buffer register 0 int THR;//Transmitter-holding register 0 //状态寄存器 int LSR;//Line-status register 5 int MSR;//Modem-status register 6 //控制寄存器 int LCR;//Line-control register 3 int FCR;//FIFO-control register 2 int MCR;//Modem-control register 4 int DLL;//Divisor-latch LSB 0 int DLM;//Divisor-latch MSB 1 int IER;//Interrupt enable register 1 //其它寄存器 int SPR;//Scratchpad register 7 int IIR;//Interrupt identification register 2 //串口数据接收缓冲区 volatile short sRecvHead; volatile short sRecvTail; volatile unsigned char abyRecvData[ST_RECV_LEN]; //串口数据发送缓冲区 volatile short sSendHead; volatile short sSendTail; volatile unsigned char abySendData[ST_SEND_LEN]; } ST_COM;static ST_COM st0A = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_AChannel_Or), 0};static ST_COM st0B = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_BChannel_Or), 0};static ST_COM st0C = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_CChannel_Or), 0};static ST_COM st0D = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_DChannel_Or), 0};static ST_COM st0E = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_EChannel_Or), 0};static ST_COM st0F = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_FChannel_Or), 0};static ST_COM st0G = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_GChannel_Or), 0};static ST_COM st0H = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_HChannel_Or), 0};#define DEVICE_NAME "ST16C554"#define DEVICE_MAJOR 233#define ST0A 0#define ST0B 1#define ST0C 2#define ST0D 3#define ST0E 4#define ST0F 5#define ST0G 6#define ST0H 7static int stMajor = 233;inline int get_ST0A_rxLen(void){ if(st0A.sRecvHead==st0A.sRecvTail){ return 0; } else if(st0A.sRecvTail>st0A.sRecvHead){ return (st0A.sRecvTail-st0A.sRecvHead); } else{ return ( ST_RECV_LEN-(st0A.sRecvHead-st0A.sRecvTail) ); }}inline int get_ST0B_rxLen(void){ if(st0B.sRecvHead==st0B.sRecvTail){ return 0; } else if(st0B.sRecvTail>st0B.sRecvHead){ return (st0B.sRecvTail-st0B.sRecvHead); } else{ return ( ST_RECV_LEN-(st0B.sRecvHead-st0B.sRecvTail) ); }}inline int get_ST0C_rxLen(void){ if(st0C.sRecvHead==st0C.sRecvTail){ return 0; } else if(st0C.sRecvTail>st0C.sRecvHead){ return (st0C.sRecvTail-st0C.sRecvHead); } else{ return ( ST_RECV_LEN-(st0C.sRecvHead-st0C.sRecvTail) ); }}inline int get_ST0D_rxLen(void){ if(st0D.sRecvHead==st0D.sRecvTail){ return 0; } else if(st0D.sRecvTail>st0D.sRecvHead){ return (st0D.sRecvTail-st0D.sRecvHead); } else{ return ( ST_RECV_LEN-(st0D.sRecvHead-st0D.sRecvTail) ); }}inline int get_ST0E_rxLen(void){ if(st0E.sRecvHead==st0E.sRecvTail){ return 0; } else if(st0E.sRecvTail>st0E.sRecvHead){ return (st0E.sRecvTail-st0E.sRecvHead); } else{ return ( ST_RECV_LEN-(st0E.sRecvHead-st0E.sRecvTail) ); }}inline int get_ST0F_rxLen(void){ if(st0F.sRecvHead==st0F.sRecvTail){ return 0; } else if(st0F.sRecvTail>st0F.sRecvHead){ return (st0F.sRecvTail-st0F.sRecvHead); } else{ return ( ST_RECV_LEN-(st0F.sRecvHead-st0F.sRecvTail) ); }}inline int get_ST0G_rxLen(void){ if(st0G.sRecvHead==st0G.sRecvTail){ return 0; } else if(st0G.sRecvTail>st0G.sRecvHead){ return (st0G.sRecvTail-st0G.sRecvHead); } else{ return ( ST_RECV_LEN-(st0G.sRecvHead-st0G.sRecvTail) ); }}inline int get_ST0H_rxLen(void){ if(st0H.sRecvHead==st0H.sRecvTail){ return 0; } else if(st0H.sRecvTail>st0H.sRecvHead){ return (st0H.sRecvTail-st0H.sRecvHead); } else{ return ( ST_RECV_LEN-(st0H.sRecvHead-st0H.sRecvTail) ); }}inline int get_ST0A_txLen(void){ if(st0A.sSendHead==st0A.sSendTail){ return 0; } else if(st0A.sSendTail>st0A.sSendHead){ return (st0A.sSendTail-st0A.sSendHead); } else{ return ( ST_SEND_LEN-(st0A.sSendHead-st0A.sSendTail) ); }}inline int get_ST0B_txLen(void){ if(st0B.sSendHead==st0B.sSendTail){ return 0; } else if(st0B.sSendTail>st0B.sSendHead){ return (st0B.sSendTail-st0B.sSendHead); } else{ return ( ST_SEND_LEN-(st0B.sSendHead-st0B.sSendTail) ); }}inline int get_ST0C_txLen(void){ if(st0C.sSendHead==st0C.sSendTail){ return 0; } else if(st0C.sSendTail>st0C.sSendHead){ return (st0C.sSendTail-st0C.sSendHead); } else{ return ( ST_SEND_LEN-(st0C.sSendHead-st0C.sSendTail) ); }}inline int get_ST0D_txLen(void){ if(st0D.sSendHead==st0D.sSendTail){ return 0; } else if(st0D.sSendTail>st0D.sSendHead){ return (st0D.sSendTail-st0D.sSendHead); } else{ return ( ST_SEND_LEN-(st0D.sSendHead-st0D.sSendTail) ); }}inline int get_ST0E_txLen(void){ if(st0E.sSendHead==st0E.sSendTail){ return 0; } else if(st0E.sSendTail>st0E.sSendHead){ return (st0E.sSendTail-st0E.sSendHead); } else{ return ( ST_SEND_LEN-(st0E.sSendHead-st0E.sSendTail) ); }}inline int get_ST0F_txLen(void){ if(st0F.sSendHead==st0F.sSendTail){ return 0; } else if(st0F.sSendTail>st0F.sSendHead){ return (st0F.sSendTail-st0F.sSendHead); } else{ return ( ST_SEND_LEN-(st0F.sSendHead-st0F.sSendTail) ); }}inline int get_ST0G_txLen(void){ if(st0G.sSendHead==st0G.sSendTail){ return 0; } else if(st0G.sSendTail>st0G.sSendHead){ return (st0G.sSendTail-st0G.sSendHead); } else{ return ( ST_SEND_LEN-(st0G.sSendHead-st0G.sSendTail) ); }}inline int get_ST0H_txLen(void){ if(st0H.sSendHead==st0H.sSendTail){ return 0; } else if(st0H.sSendTail>st0H.sSendHead){ return (st0H.sSendTail-st0H.sSendHead); } else{ return ( ST_SEND_LEN-(st0H.sSendHead-st0H.sSendTail) ); }}inline char st0aIsEmpty_rx(void){ return (st0A.sRecvHead==st0A.sRecvTail ? 1 : 0);}inline char st0bIsEmpty_rx(void){ return (st0B.sRecvHead==st0B.sRecvTail ? 1 : 0);}inline char st0cIsEmpty_rx(void){ return (st0C.sRecvHead==st0C.sRecvTail ? 1 : 0);}inline char st0dIsEmpty_rx(void){ return (st0D.sRecvHead==st0D.sRecvTail ? 1 : 0);}inline char st0eIsEmpty_rx(void){ return (st0E.sRecvHead==st0E.sRecvTail ? 1 : 0);}inline char st0fIsEmpty_rx(void){ return (st0F.sRecvHead==st0F.sRecvTail ? 1 : 0);}inline char st0gIsEmpty_rx(void){ return (st0G.sRecvHead==st0G.sRecvTail ? 1 : 0);}inline char st0hIsEmpty_rx(void){ return (st0H.sRecvHead==st0H.sRecvTail ? 1 : 0);}inline char st0aIsFull_rx(void){ return (st0A.sRecvHead==(st0A.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0bIsFull_rx(void){ return (st0B.sRecvHead==(st0B.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0cIsFull_rx(void){ return (st0C.sRecvHead==(st0C.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0dIsFull_rx(void){ return (st0D.sRecvHead==(st0D.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0eIsFull_rx(void){ return (st0E.sRecvHead==(st0E.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0fIsFull_rx(void){ return (st0F.sRecvHead==(st0F.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0gIsFull_rx(void){ return (st0G.sRecvHead==(st0G.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0hIsFull_rx(void){ return (st0H.sRecvHead==(st0H.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0aIsEmpty_tx(void){ return (st0A.sSendHead==st0A.sSendTail ? 1 : 0);}inline char st0bIsEmpty_tx(void){ return (st0B.sSendHead==st0B.sSendTail ? 1 : 0);}inline char st0cIsEmpty_tx(void){ return (st0C.sSendHead==st0C.sSendTail ? 1 : 0);}inline char st0dIsEmpty_tx(void){ return (st0D.sSendHead==st0D.sSendTail ? 1 : 0);}inline char st0eIsEmpty_tx(void){ return (st0E.sSendHead==st0E.sSendTail ? 1 : 0);}inline char st0fIsEmpty_tx(void){ return (st0F.sSendHead==st0F.sSendTail ? 1 : 0);}inline char st0gIsEmpty_tx(void){ return (st0G.sSendHead==st0G.sSendTail ? 1 : 0);}inline char st0hIsEmpty_tx(void){ return (st0H.sSendHead==st0H.sSendTail ? 1 : 0);}inline char st0aIsFull_tx(void){ return (st0A.sSendHead==(st0A.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0bIsFull_tx(void){ return (st0B.sSendHead==(st0B.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0cIsFull_tx(void){ return (st0C.sSendHead==(st0C.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0dIsFull_tx(void){ return (st0D.sSendHead==(st0D.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0eIsFull_tx(void){ return (st0E.sSendHead==(st0E.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0fIsFull_tx(void){ return (st0F.sSendHead==(st0F.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0gIsFull_tx(void){ return (st0G.sSendHead==(st0G.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0hIsFull_tx(void){ return (st0H.sSendHead==(st0H.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline void pushST0ARX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置 st0A.abyRecvData[st0A.sRecvTail] = byRx; if(!st0aIsFull_rx()){ st0A.sRecvTail++; st0A.sRecvTail %= ST_RECV_LEN; }}inline void pushST0BRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置 st0B.abyRecvData[st0B.sRecvTail] = byRx; if(!st0bIsFull_rx()){ st0B.sRecvTail++; st0B.sRecvTail %= ST_RECV_LEN; }}inline void pushST0CRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置 st0C.abyRecvData[st0C.sRecvTail] = byRx; if(!st0cIsFull_rx()){ st0C.sRecvTail++; st0C.sRecvTail %= ST_RECV_LEN; }}inline void pushST0DRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置 st0D.abyRecvData[st0D.sRecvTail] = byRx; if(!st0dIsFull_rx()){ st0D.sRecvTail++; st0D.sRecvTail %= ST_RECV_LEN; }}inline void pushST0ERX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置 st0E.abyRecvData[st0E.sRecvTail] = byRx; if(!st0eIsFull_rx()){ st0E.sRecvTail++; st0E.sRecvTail %= ST_RECV_LEN; }}inline void pushST0FRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置 st0F.abyRecvData[st0F.sRecvTail] = byRx; if(!st0fIsFull_rx()){ st0F.sRecvTail++; st0F.sRecvTail %= ST_RECV_LEN; }}inline void pushST0GRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置 st0G.abyRecvData[st0G.sRecvTail] = byRx; if(!st0gIsFull_rx()){ st0G.sRecvTail++; st0G.sRecvTail %= ST_RECV_LEN; }}inline void pushST0HRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置 st0H.abyRecvData[st0H.sRecvTail] = byRx; if(!st0hIsFull_rx()){ st0H.sRecvTail++; st0H.sRecvTail %= ST_RECV_LEN; }}inline unsigned char st0apopRX(void){//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据 unsigned char byRet; byRet = st0A.abyRecvData[st0A.sRecvHead]; if(!st0aIsEmpty_rx()){ st0A.sRecvHead++; st0A.sRecvHead %= ST_RECV_LEN; } return byRet;}inline unsigned char st0bpopRX(void){//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据 unsigned char byRet; byRet = st0B.abyRecvData[st0B.sRecvHead]; if(!st0bIsEmpty_rx()){ st0B.sRecvHead++; st0B.sRecvHead %= ST_RECV_LEN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -