会员
周边
众包
新闻
博问
闪存
赞助商
所有博客
当前博客
我的博客
我的园子
账号设置
简洁模式
...
退出登录
注册
登录
张鹏的博客
嵌入式系统
st16c554
/*
* 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 $
*
ST16C554APN
7.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 1
UART0B:0xf0200028---0xf020002f
UART0C:0xf0200030---0xf0200037
UART0D:0xf0200038---0xf020003f
UART0E: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 1
UART0F:0xf0200048---0xf020004f
UART0G:0xf0200050---0xf0200057
UART0H:0xf0200058---0xf020005f
控制寄存器
Line-control register(LCR)
0x03
FIFO-control register(FCR)
0x02
Modem-control register(MCR)
0x04
Divisor-latch LSB(DLL)
LCR(bit7=1)0x00
Divisor-latch MSB(DLM)
LCR(bit7=1)0x01
Interrupt enable register(IER)
0x01
状态寄存器
Line-status register(LSR)
0x05
Modem-status register(MSR)
0x06
数据寄存器
Receiver-buffer register(RBR)
0x00
Transmitter-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 32
typedef
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 7
static
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;
}
return byRet;
}
inline unsigned
char st0cpopRX(
void){
//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据
unsigned
char byRet;
byRet = st0C.abyRecvData[st0C.sRecvHead];
if(!st0cIsEmpty_rx()){
st0C.sRecvHead++;
st0C.sRecvHead %= ST_RECV_LEN;
}
return byRet;
}
inline unsigned
char st0dpopRX(
void){
//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据
unsigned
char byRet;
byRet = st0D.abyRecvData[st0D.sRecvHead];
if(!st0dIsEmpty_rx()){
st0D.sRecvHead++;
st0D.sRecvHead %= ST_RECV_LEN;
}
return byRet;
}
inline unsigned
char st0epopRX(
void){
//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据
unsigned
char byRet;
byRet = st0E.abyRecvData[st0E.sRecvHead];
if(!st0eIsEmpty_rx()){
st0E.sRecvHead++;
st0E.sRecvHead %= ST_RECV_LEN;
}
return byRet;
}
inline unsigned
char st0fpopRX(
void){
//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据
unsigned
char byRet;
byRet = st0F.abyRecvData[st0F.sRecvHead];
if(!st0fIsEmpty_rx()){
st0F.sRecvHead++;
st0F.sRecvHead %= ST_RECV_LEN;
}
return byRet;
}
inline unsigned
char st0gpopRX(
void){
//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据
unsigned
char byRet;
byRet = st0G.abyRecvData[st0G.sRecvHead];
if(!st0gIsEmpty_rx()){
st0G.sRecvHead++;
st0G.sRecvHead %= ST_RECV_LEN;
}
return byRet;
}
inline unsigned
char st0hpopRX(
void){
//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据
unsigned
char byRet;
byRet = st0H.abyRecvData[st0H.sRecvHead];
if(!st0hIsEmpty_rx()){
st0H.sRecvHead++;
st0H.sRecvHead %= ST_RECV_LEN;
}
return byRet;
}
static
void InitCommont(ST_COM *pst,
int nBaud, unsigned
char byMode)
{
volatile unsigned
char byRx;
int i;
if(0 != pst->sInited){
iounmap((
void *) (pst->pbyBase0));
}
pst->pbyBase0 = (unsigned
char *)ioremap_nocache(pst->nAddress0, 8);
pst->RBR = (
int)(pst->pbyBase0);
pst->THR = (
int)(pst->pbyBase0);
pst->DLL = (
int)(pst->pbyBase0);
pst->DLM = (
int)(pst->pbyBase0+1);
pst->IER = (
int)(pst->pbyBase0+1);
pst->FCR = (
int)(pst->pbyBase0+2);
pst->IIR = (
int)(pst->pbyBase0+2);
pst->LCR = (
int)(pst->pbyBase0+3);
pst->MCR = (
int)(pst->pbyBase0+4);
pst->LSR = (
int)(pst->pbyBase0+5);
pst->MSR = (
int)(pst->pbyBase0+6);
pst->SPR = (
int)(pst->pbyBase0+7);
pst->sRecvHead = 0;
pst->sRecvTail = 0;
pst->sSendHead = 0;
pst->sSendTail = 0;
//IER
//接收保持和中断允许
*(
volatile unsigned
char *)(pst->IER) = 0x01;
//0x05;
//FIFO控制器
//set FCR.FIFO允许,RXD复位,TXD复位,DMAmode=1,触发为14
*(
volatile unsigned
char *)(pst->FCR) = 0xcf;
for(i=0; i<100; i++);
//set FCR.RXD复位,TXD复位
*(
volatile unsigned
char *)(pst->FCR) = 0xc9;
//Modem状态
//set MCR.中断A-D开
//*(volatile unsigned char *)(pst->MCR) = 0x08; //change by zhujiang,our program not use this now
if(byMode&0x80){
*(
volatile unsigned
char *)(pst->LCR) = 0x82|(byMode&0x7f);
//7 bit
}
else{
//set LCR.8BIT,1STOP,ODDPARITY,选择特殊寄存器
*(
volatile unsigned
char *)(pst->LCR) = 0x83|byMode;
}
/***************************************************************************
** SET st baudrate.
BAUD RATE GENRATOR PROGRAMMING TABLE
Output Baud Rate DLM DLL
(7.3278MHz Clock) (HEX) (HEX)
200 09 00
1200 01 80
2400 00 C0
4800 00 60
9600 00 30
19.2K 00 18
38.4K 00 0C
76.8K 00 06
153.6K 00 03
230.4K 00 02
460.8K 00 01
**
***************************************************************************/
// 特殊寄存器已打开,设置BPS
// *(volatile unsigned char *)(pst->DLL) = BAUDBASE/nBaud;
// 高位
// *(volatile unsigned char *)(pst->DLM) = 0x00;
switch(nBaud){
case 200:
*(
volatile unsigned
char *)(pst->DLL) = 0x00;
//高位
*(
volatile unsigned
char *)(pst->DLM) = 0x09;
break;
case 1200:
*(
volatile unsigned
char *)(pst->DLL) = 0x80;
//高位
*(
volatile unsigned
char *)(pst->DLM) = 0x01;
break;
case 2400:
*(
volatile unsigned
char *)(pst->DLL) = 0xC0;
//高位
*(
volatile unsigned
char *)(pst->DLM) = 0x00;
break;
case 4800:
*(
volatile unsigned
char *)(pst->DLL) = 0x60;
//高位
*(
volatile unsigned
char *)(pst->DLM) = 0x00;
break;
case 9600:
*(
volatile unsigned
char *)(pst->DLL) = 0x30;
//高位
*(
volatile unsigned
char *)(pst->DLM) = 0x00;
break;
case 19200:
*(
volatile unsigned
char *)(pst->DLL) = 0x18;
//高位
*(
volatile unsigned
char *)(pst->DLM) = 0x00;
break;
case 38400:
*(
volatile unsigned
char *)(pst->DLL) = 0x0C;
//高位
*(
volatile unsigned
char *)(pst->DLM) = 0x00;
break;
case 76800:
*(
volatile unsigned
char *)(pst->DLL) = 0x06;
//高位
*(
volatile unsigned
char *)(pst->DLM) = 0x00;
break;
case 153600:
*(
volatile unsigned
char *)(pst->DLL) = 0x03;
//高位
*(
volatile unsigned
char *)(pst->DLM) = 0x00;
break;
default:
break;
}
if(byMode&0x80){
*(
volatile unsigned
char *)(pst->LCR) = 0x02|(byMode&0x7f);
//7 bit
}
else{
//set LCR.8BIT,1STOP,ODDPARITY,选择特殊寄存器
*(
volatile unsigned
char *)(pst->LCR) = 0x03|byMode;
}
//空读一次
byRx = *(
volatile unsigned
char *)(pst->RBR);
//读空
i=0;
while(1){
//检查接收状态
byRx = *(
volatile unsigned
char *)(pst->LSR);
if(byRx&0x01){
byRx = *(
volatile unsigned
char *)(pst->RBR);
}
else
break;
//防止死循环
i++;
if(i > 4096)
//每个UART最多只能缓存16个字节
break;
}
pst->sInited = 1;
}
//ST16C554初始化
void Init_ST0A(
int nBaud, unsigned
char byMode){
InitCommont(&st0A,nBaud,byMode);
}
void Init_ST0B(
int nBaud, unsigned
char byMode){
InitCommont(&st0B,nBaud,byMode);
}
void Init_ST0C(
int nBaud, unsigned
char byMode){
InitCommont(&st0C,nBaud,byMode);
}
void Init_ST0D(
int nBaud, unsigned
char byMode){
InitCommont(&st0D,nBaud,byMode);
}
void Init_ST0E(
int nBaud, unsigned
char byMode){
InitCommont(&st0E,nBaud,byMode);
}
void Init_ST0F(
int nBaud, unsigned
char byMode){
InitCommont(&st0F,nBaud,byMode);
}
void Init_ST0G(
int nBaud, unsigned
char byMode){
InitCommont(&st0G,nBaud,byMode);
}
void Init_ST0H(
int nBaud, unsigned
char byMode){
InitCommont(&st0H,nBaud,byMode);
}
//ST16C554的接收
unsigned
char ST0A_Rxd(
void){
volatile unsigned
char byRx;
volatile unsigned
char bySt;
int nRxCnt = 0;
while(nRxCnt < 256){
bySt = *(
volatile unsigned
char *)(st0A.LSR);
//检查接收状态
if(bySt&0x01){
//数据就绪
byRx = *(
volatile unsigned
char *)(st0A.RBR);
pushST0ARX(byRx);
}
else
break;
nRxCnt++;
}
return byRx;
}
unsigned
char ST0B_Rxd(
void){
volatile unsigned
char byRx;
volatile unsigned
char bySt;
int nRxCnt = 0;
while(nRxCnt < 256){
bySt = *(
volatile unsigned
char *)(st0B.LSR);
//检查接收状态
if(bySt&0x01){
//数据就绪
byRx = *(
volatile unsigned
char *)(st0B.RBR);
pushST0BRX(byRx);
}
else{
break;
}
nRxCnt++;
}
return byRx;
}
unsigned
char ST0C_Rxd(
void){
volatile unsigned
char byRx;
volatile unsigned
char bySt;
int nRxCnt = 0;
while(nRxCnt < 256){
bySt = *(
volatile unsigned
char *)(st0C.LSR);
//检查接收状态
if(bySt&0x01){
//数据就绪
byRx = *(
volatile unsigned
char *)(st0C.RBR);
pushST0CRX(byRx);
}
else
break;
nRxCnt++;
}
return byRx;
}
unsigned
char ST0D_Rxd(
void){
volatile unsigned
char byRx;
volatile unsigned
char bySt;
int nRxCnt = 0;
while(nRxCnt < 256){
bySt = *(
volatile unsigned
char *)(st0D.LSR);
//检查接收状态
if(bySt&0x01){
//数据就绪
byRx = *(
volatile unsigned
char *)(st0D.RBR);
pushST0DRX(byRx);
}
else
break;
nRxCnt++;
}
return byRx;
}
unsigned
char ST0E_Rxd(
void){
volatile unsigned
char byRx;
volatile unsigned
char bySt;
int nRxCnt = 0;
while(nRxCnt < 256){
bySt = *(
volatile unsigned
char *)(st0E.LSR);
//检查接收状态
if(bySt&0x01){
//数据就绪
byRx = *(
volatile unsigned
char *)(st0E.RBR);
pushST0ERX(byRx);
}
else
break;
nRxCnt++;
}
return byRx;
}
unsigned
char ST0F_Rxd(
void){
volatile unsigned
char byRx;
volatile unsigned
char bySt;
int nRxCnt = 0;
while(nRxCnt < 256){
bySt = *(
volatile unsigned
char *)(st0F.LSR);
//检查接收状态
if(bySt&0x01){
//数据就绪
byRx = *(
volatile unsigned
char *)(st0F.RBR);
pushST0FRX(byRx);
}
else{
break;
}
nRxCnt++;
}
return byRx;
}
unsigned
char ST0G_Rxd(
void){
volatile unsigned
char byRx;
volatile unsigned
char bySt;
int nRxCnt = 0;
while(nRxCnt < 256){
bySt = *(
volatile unsigned
char *)(st0G.LSR);
//检查接收状态
if(bySt&0x01){
//数据就绪
byRx = *(
volatile unsigned
char *)(st0G.RBR);
pushST0GRX(byRx);
}
else
break;
nRxCnt++;
}
return byRx;
}
unsigned
char ST0H_Rxd(
void){
volatile unsigned
char byRx;
volatile unsigned
char bySt;
int nRxCnt = 0;
while(nRxCnt < 256){
bySt = *(
volatile unsigned
char *)(st0H.LSR);
//检查接收状态
if(bySt&0x01){
//数据就绪
byRx = *(
volatile unsigned
char *)(st0H.RBR);
pushST0HRX(byRx);
}
else
break;
nRxCnt++;
}
return byRx;
}
//ST16C554的发送
//返回:1,成功
// 0,失败
int ST_ComTxd(ST_COM *pst,unsigned
char byTxd){
unsigned
char byRx;
int nTxCnt = 0;
while(nTxCnt < 256){
byRx = *(
volatile unsigned
char *)(pst->LSR);
//检查发送状态
if(byRx&0x20){
//发送就绪
*(
volatile unsigned
char *)(pst->THR) = byTxd;
return 1;
}
else{
nTxCnt++;
}
}
return 0;
}
static
void UART0_interrupt(
int irq,
void *dev_id,
struct pt_regs *regs)
{
//save_flags_cli(flags);
if (st0A.sInited)
ST0A_Rxd();
// printk(KERN_INFO "UART0_interrupt1\n" );
if (st0B.sInited)
ST0B_Rxd();
// printk(KERN_INFO "UART0_interrupt2\n" );
if (st0C.sInited);
ST0C_Rxd();
// printk(KERN_INFO "UART0_interrupt3\n" );
if (st0D.sInited)
ST0D_Rxd();
// printk(KERN_INFO "UART0_interrupt4\n" );
//restore_flags(flags);
}
static
void UART1_interrupt(
int irq,
void *dev_id,
struct pt_regs *regs)
{
if (st0E.sInited)
ST0E_Rxd();
// printk(KERN_INFO "UART1_interrupt0\n" );
if (st0F.sInited)
ST0F_Rxd();
// printk(KERN_INFO "UART1_interrupt1\n" );
if (st0G.sInited)
ST0G_Rxd();
// printk(KERN_INFO "UART1_interrupt2\n" );
if (st0H.sInited)
ST0H_Rxd();
// printk(KERN_INFO "UART1_interrupt3\n" );
}
static
int st16c554_open(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_INC_USE_COUNT;
return nRet;
}
static
int st16c554_ioctl(
struct inode *inode,
struct file *file, unsigned
int cmd, unsigned
long arg)
{
int nRet = 0;
switch(cmd) {
default:
return -EINVAL;
}
return nRet;
}
static
int st16c554_read(
struct file *filp,
char *buffer,
size_t count, loff_t *ppos)
{
int nRet = 0;
return nRet;
}
static
int st16c554_release(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_DEC_USE_COUNT;
return nRet;
}
static
int st16c554_ComWrite(
const
char *buf,
size_t nCount ,ST_COM *mPst)
{
int i,j,nRet;
unsigned
char abySend[ST_SEND_LEN];
int m,k;
m=nCount/ST_SEND_LEN;
k=nCount%ST_SEND_LEN;
for(i=0; i<m; i++){
if (copy_from_user(abySend,buf+i*ST_SEND_LEN,ST_SEND_LEN)){
return -EFAULT;
}
for(nRet=0; nRet<ST_SEND_LEN; nRet++){
ST_ComTxd(mPst,abySend[nRet]);
//ST0A_Txd(abySend[nRet]);
for(j=0; j<delay_counter; j++);
//300000
// printk("A:%02X\n", abySend[nRet]);
}
}
if (k>0){
if (copy_from_user(abySend,buf+m*ST_SEND_LEN,k)){
return -EFAULT;
}
for(nRet=0; nRet<k; nRet++){
ST_ComTxd(mPst,abySend[nRet]);
//ST0A_Txd(abySend[nRet]);
for(j=0; j<delay_counter; j++);
//300000
// printk("A:%02X\n", abySend[nRet]);
}
}
return nRet;
}
static
int ST0A_open(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_INC_USE_COUNT;
return nRet;
}
static
int ST0A_ioctl(
struct inode *inode,
struct file *file, unsigned
int cmd, unsigned
long arg)
{
int nRet = 0;
switch(cmd) {
case ST_INIT:
copy_from_user(&st0A_init, (
struct tagST_INIT *)arg,
sizeof(
struct tagST_INIT));
Init_ST0A(st0A_init.nBaud, st0A_init.byMode);
break;
default:
return -EINVAL;
}
return nRet;
}
static
int ST0A_read(
struct file *filp,
char *buf,
size_t count, loff_t *ppos)
{
int i;
int nLen;
unsigned
char abyRecv[ST_RECV_LEN];
nLen = get_ST0A_rxLen();
nLen = nLen>count ? count : nLen;
for(i=0; i<nLen; i++){
abyRecv[i] = st0A.abyRecvData[st0A.sRecvHead];
if(st0A.sRecvHead != st0A.sRecvTail){
st0A.sRecvHead++;
st0A.sRecvHead %= ST_RECV_LEN;
}
else
break;
}
copy_to_user((
void *)buf, &abyRecv, i);
return i;
}
static
int ST0A_write (
struct file *file,
const
char *buf,
size_t count, loff_t *ppos){
return st16c554_ComWrite(buf,count,&st0A);
}
static
int ST0A_release(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_DEC_USE_COUNT;
return nRet;
}
static
int ST0B_open(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_INC_USE_COUNT;
return nRet;
}
static
int ST0B_ioctl(
struct inode *inode,
struct file *file, unsigned
int cmd, unsigned
long arg)
{
int nRet = 0;
switch(cmd) {
case ST_INIT:
copy_from_user(&st0B_init, (
struct tagST_INIT *)arg,
sizeof(
struct tagST_INIT));
Init_ST0B(st0B_init.nBaud, st0B_init.byMode);
break;
default:
return -EINVAL;
}
return nRet;
}
static
int ST0B_read(
struct file *filp,
char *buf,
size_t count, loff_t *ppos)
{
int i;
int nLen;
unsigned
char abyRecv[ST_RECV_LEN];
nLen = get_ST0B_rxLen();
nLen = nLen>count ? count : nLen;
for(i=0; i<nLen; i++){
abyRecv[i] = st0B.abyRecvData[st0B.sRecvHead];
if(st0B.sRecvHead != st0B.sRecvTail){
st0B.sRecvHead++;
st0B.sRecvHead %= ST_RECV_LEN;
}
else
break;
}
copy_to_user((
void *)buf, &abyRecv, i);
return i;
}
static
int ST0B_write (
struct file *file,
const
char *buf,
size_t count, loff_t *ppos){
return st16c554_ComWrite(buf,count,&st0B);
}
static
int ST0B_release(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_DEC_USE_COUNT;
return nRet;
}
static
int ST0C_open(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_INC_USE_COUNT;
return nRet;
}
static
int ST0C_ioctl(
struct inode *inode,
struct file *file, unsigned
int cmd, unsigned
long arg)
{
int nRet = 0;
switch(cmd) {
case ST_INIT:
copy_from_user(&st0C_init, (
struct tagST_INIT *)arg,
sizeof(
struct tagST_INIT));
Init_ST0C(st0C_init.nBaud, st0C_init.byMode);
break;
default:
return -EINVAL;
}
return nRet;
}
static
int ST0C_read(
struct file *filp,
char *buf,
size_t count, loff_t *ppos)
{
int i;
int nLen;
unsigned
char abyRecv[ST_RECV_LEN];
nLen = get_ST0C_rxLen();
nLen = nLen>count ? count : nLen;
for(i=0; i<nLen; i++){
abyRecv[i] = st0C.abyRecvData[st0C.sRecvHead];
if(st0C.sRecvHead != st0C.sRecvTail){
st0C.sRecvHead++;
st0C.sRecvHead %= ST_RECV_LEN;
}
else
break;
}
copy_to_user((
void *)buf, &abyRecv, i);
return i;
}
static
int ST0C_write (
struct file *file,
const
char *buf,
size_t count, loff_t *ppos){
return st16c554_ComWrite(buf,count,&st0C);
}
static
int ST0C_release(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_DEC_USE_COUNT;
return nRet;
}
static
int ST0D_open(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_INC_USE_COUNT;
return nRet;
}
static
int ST0D_ioctl(
struct inode *inode,
struct file *file, unsigned
int cmd, unsigned
long arg)
{
int nRet = 0;
switch(cmd) {
case ST_INIT:
copy_from_user(&st0D_init, (
struct tagST_INIT *)arg,
sizeof(
struct tagST_INIT));
Init_ST0D(st0D_init.nBaud, st0D_init.byMode);
break;
default:
return -EINVAL;
}
return nRet;
}
static
int ST0D_read(
struct file *filp,
char *buf,
size_t count, loff_t *ppos)
{
int i;
int nLen;
unsigned
char abyRecv[ST_RECV_LEN];
nLen = get_ST0D_rxLen();
nLen = nLen>count ? count : nLen;
for(i=0; i<nLen; i++){
abyRecv[i] = st0D.abyRecvData[st0D.sRecvHead];
if(st0D.sRecvHead != st0D.sRecvTail){
st0D.sRecvHead++;
st0D.sRecvHead %= ST_RECV_LEN;
}
else
break;
// printk("D-:%02X\n", abyRecv[i]);
}
copy_to_user((
void *)buf, &abyRecv, i);
return i;
}
static
int ST0D_write (
struct file *file,
const
char *buf,
size_t count, loff_t *ppos){
return st16c554_ComWrite(buf,count,&st0D);
}
static
int ST0D_release(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_DEC_USE_COUNT;
return nRet;
}
static
int ST0E_open(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_INC_USE_COUNT;
return nRet;
}
static
int ST0E_ioctl(
struct inode *inode,
struct file *file, unsigned
int cmd, unsigned
long arg)
{
int nRet = 0;
switch(cmd) {
case ST_INIT:
copy_from_user(&st0E_init, (
struct tagST_INIT *)arg,
sizeof(
struct tagST_INIT));
Init_ST0E(st0E_init.nBaud, st0E_init.byMode);
break;
default:
return -EINVAL;
}
return nRet;
}
static
int ST0E_read(
struct file *filp,
char *buf,
size_t count, loff_t *ppos)
{
int i;
int nLen;
unsigned
char abyRecv[ST_RECV_LEN];
nLen = get_ST0E_rxLen();
nLen = nLen>count ? count : nLen;
for(i=0; i<nLen; i++){
abyRecv[i] = st0E.abyRecvData[st0E.sRecvHead];
if(st0E.sRecvHead != st0E.sRecvTail){
st0E.sRecvHead++;
st0E.sRecvHead %= ST_RECV_LEN;
}
else
break;
}
copy_to_user((
void *)buf, &abyRecv, i);
return i;
}
static
int ST0E_write (
struct file *file,
const
char *buf,
size_t count, loff_t *ppos){
return st16c554_ComWrite(buf,count,&st0E);
}
static
int ST0E_release(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_DEC_USE_COUNT;
return nRet;
}
static
int ST0F_open(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_INC_USE_COUNT;
return nRet;
}
static
int ST0F_ioctl(
struct inode *inode,
struct file *file, unsigned
int cmd, unsigned
long arg)
{
int nRet = 0;
switch(cmd) {
case ST_INIT:
copy_from_user(&st0F_init, (
struct tagST_INIT *)arg,
sizeof(
struct tagST_INIT));
Init_ST0F(st0F_init.nBaud, st0F_init.byMode);
break;
default:
return -EINVAL;
}
return nRet;
}
static
int ST0F_read(
struct file *filp,
char *buf,
size_t count, loff_t *ppos)
{
int i;
int nLen;
unsigned
char abyRecv[ST_RECV_LEN];
nLen = get_ST0F_rxLen();
nLen = nLen>count ? count : nLen;
for(i=0; i<nLen; i++){
abyRecv[i] = st0F.abyRecvData[st0F.sRecvHead];
if(st0F.sRecvHead != st0F.sRecvTail){
st0F.sRecvHead++;
st0F.sRecvHead %= ST_RECV_LEN;
}
else
break;
}
copy_to_user((
void *)buf, &abyRecv, i);
return i;
}
static
int ST0F_write (
struct file *file,
const
char *buf,
size_t count, loff_t *ppos){
return st16c554_ComWrite(buf,count,&st0F);
}
static
int ST0F_release(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_DEC_USE_COUNT;
return nRet;
}
static
int ST0G_open(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_INC_USE_COUNT;
return nRet;
}
static
int ST0G_ioctl(
struct inode *inode,
struct file *file, unsigned
int cmd, unsigned
long arg)
{
int nRet = 0;
switch(cmd) {
case ST_INIT:
copy_from_user(&st0G_init, (
struct tagST_INIT *)arg,
sizeof(
struct tagST_INIT));
Init_ST0G(st0G_init.nBaud, st0G_init.byMode);
break;
default:
return -EINVAL;
}
return nRet;
}
static
int ST0G_read(
struct file *filp,
char *buf,
size_t count, loff_t *ppos)
{
int i;
int nLen;
unsigned
char abyRecv[ST_RECV_LEN];
nLen = get_ST0G_rxLen();
nLen = nLen>count ? count : nLen;
for(i=0; i<nLen; i++){
abyRecv[i] = st0G.abyRecvData[st0G.sRecvHead];
if(st0G.sRecvHead != st0G.sRecvTail){
st0G.sRecvHead++;
st0G.sRecvHead %= ST_RECV_LEN;
}
else
break;
}
copy_to_user((
void *)buf, &abyRecv, i);
return i;
}
static
int ST0G_write (
struct file *file,
const
char *buf,
size_t count, loff_t *ppos){
return st16c554_ComWrite(buf,count,&st0G);
}
static
int ST0G_release(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_DEC_USE_COUNT;
return nRet;
}
static
int ST0H_open(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_INC_USE_COUNT;
return nRet;
}
static
int ST0H_ioctl(
struct inode *inode,
struct file *file, unsigned
int cmd, unsigned
long arg)
{
int nRet = 0;
switch(cmd) {
case ST_INIT:
copy_from_user(&st0H_init, (
struct tagST_INIT *)arg,
sizeof(
struct tagST_INIT));
Init_ST0H(st0H_init.nBaud, st0H_init.byMode);
break;
default:
return -EINVAL;
}
return nRet;
}
static
int ST0H_read(
struct file *filp,
char *buf,
size_t count, loff_t *ppos)
{
int i;
int nLen;
unsigned
char abyRecv[ST_RECV_LEN];
nLen = get_ST0H_rxLen();
nLen = nLen>count ? count : nLen;
for(i=0; i<nLen; i++){
abyRecv[i] = st0H.abyRecvData[st0H.sRecvHead];
if(st0H.sRecvHead != st0H.sRecvTail){
st0H.sRecvHead++;
st0H.sRecvHead %= ST_RECV_LEN;
}
else
break;
// printk("D-:%02X\n", abyRecv[i]);
}
copy_to_user((
void *)buf, &abyRecv, i);
return i;
}
static
int ST0H_write (
struct file *file,
const
char *buf,
size_t count, loff_t *ppos){
return st16c554_ComWrite(buf,count,&st0H);
}
static
int ST0H_release(
struct inode *inode,
struct file *filp)
{
int nRet = 0;
MOD_DEC_USE_COUNT;
return nRet;
}
static
struct file_operations st16c554_fops = {
owner: THIS_MODULE,
open: st16c554_open,
ioctl: st16c554_ioctl,
read: st16c554_read,
release: st16c554_release,
};
static
struct file_operations ST0A_fops = {
owner: THIS_MODULE,
open: ST0A_open,
ioctl: ST0A_ioctl,
read: ST0A_read,
write: ST0A_write,
release: ST0A_release,
};
static
struct file_operations ST0B_fops = {
owner: THIS_MODULE,
open: ST0B_open,
ioctl: ST0B_ioctl,
read: ST0B_read,
write: ST0B_write,
release: ST0B_release,
};
static
struct file_operations ST0C_fops = {
owner: THIS_MODULE,
open: ST0C_open,
ioctl: ST0C_ioctl,
read: ST0C_read,
write: ST0C_write,
release: ST0C_release,
};
static
struct file_operations ST0D_fops = {
owner: THIS_MODULE,
open: ST0D_open,
ioctl: ST0D_ioctl,
read: ST0D_read,
write: ST0D_write,
release: ST0D_release,
};
static
struct file_operations ST0E_fops = {
owner: THIS_MODULE,
open: ST0E_open,
ioctl: ST0E_ioctl,
read: ST0E_read,
write: ST0E_write,
release: ST0E_release,
};
static
struct file_operations ST0F_fops = {
owner: THIS_MODULE,
open: ST0F_open,
ioctl: ST0F_ioctl,
read: ST0F_read,
write: ST0F_write,
release: ST0F_release,
};
static
struct file_operations ST0G_fops = {
owner: THIS_MODULE,
open: ST0G_open,
ioctl: ST0G_ioctl,
read: ST0G_read,
write: ST0G_write,
release: ST0G_release,
};
static
struct file_operations ST0H_fops = {
owner: THIS_MODULE,
open: ST0H_open,
ioctl: ST0H_ioctl,
read: ST0H_read,
write: ST0H_write,
release: ST0H_release,
};
static devfs_handle_t devfs_st_dir, devfs_ST0A, devfs_ST0B, devfs_ST0C, devfs_ST0D;
static devfs_handle_t devfs_ST0E, devfs_ST0F, devfs_ST0G, devfs_ST0H;
static
int __init st16c554_init(
void)
{
int ret;
printk(KERN_INFO
"Init ST16C554 ......\n" );
mtdcr(DCRN_EBC0_CFGADDR, DCRN_EBC0_B3CR);
printk(KERN_INFO
"B3CR1=== %x\n",mfdcr(DCRN_EBC0_CFGDATA) );
mtdcr(DCRN_EBC0_CFGDATA, 0xf0218000);
//SET PCS3 BASEADDR
printk(KERN_INFO
"B3CR2== %x\n",mfdcr(DCRN_EBC0_CFGDATA) );
ret = register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &st16c554_fops);
if (ret < 0) {
printk(DEVICE_NAME
" can't get major number\n");
return ret;
}
stMajor = ret;
devfs_st_dir = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
if (devfs_st_dir == NULL)
printk(
" devfs_mk_dir() error! \n");
devfs_ST0A = devfs_register(devfs_st_dir,
"0", DEVFS_FL_DEFAULT,
// dev/st16c554/0 for ST0A
stMajor, ST0A, S_IFCHR | S_IRUSR | S_IWUSR,
&ST0A_fops, NULL);
devfs_ST0B = devfs_register(devfs_st_dir,
"1", DEVFS_FL_DEFAULT,
// dev/st16c554/1 for ST0B
stMajor, ST0B, S_IFCHR | S_IRUSR | S_IWUSR,
&ST0B_fops, NULL);
devfs_ST0C = devfs_register(devfs_st_dir,
"2", DEVFS_FL_DEFAULT,
// dev/st16c554/2 for ST0C
stMajor, ST0C, S_IFCHR | S_IRUSR | S_IWUSR,
&ST0C_fops, NULL);
devfs_ST0D = devfs_register(devfs_st_dir,
"3", DEVFS_FL_DEFAULT,
// dev/st16c554/3 for ST0D
stMajor, ST0D, S_IFCHR | S_IRUSR | S_IWUSR,
&ST0D_fops, NULL);
devfs_ST0E = devfs_register(devfs_st_dir,
"4", DEVFS_FL_DEFAULT,
// dev/st16c554/4 for ST0E
stMajor, ST0E, S_IFCHR | S_IRUSR | S_IWUSR,
&ST0E_fops, NULL);
devfs_ST0F = devfs_register(devfs_st_dir,
"5", DEVFS_FL_DEFAULT,
// dev/st16c554/5 for ST0F
stMajor, ST0F, S_IFCHR | S_IRUSR | S_IWUSR,
&ST0F_fops, NULL);
devfs_ST0G = devfs_register(devfs_st_dir,
"6", DEVFS_FL_DEFAULT,
// dev/st16c554/6 for ST0G
stMajor, ST0G, S_IFCHR | S_IRUSR | S_IWUSR,
&ST0G_fops, NULL);
devfs_ST0H = devfs_register(devfs_st_dir,
"7", DEVFS_FL_DEFAULT,
// dev/st16c554/7 for ST0H
stMajor, ST0H, S_IFCHR | S_IRUSR | S_IWUSR,
&ST0H_fops, NULL);
ret = request_irq(YC_mul232_IRQ0, UART0_interrupt, SA_INTERRUPT,
"ST16C554_0_RX Ready", UART0_interrupt);
if(ret) {
printk(
"ST16C554: failed to register IRQ_EINT0(%d)\n", YC_mul232_IRQ0);
goto UART0_failed;
}
ret = request_irq(YC_mul232_IRQ1, UART1_interrupt, SA_INTERRUPT,
"ST16C554_1_RX Ready", UART1_interrupt);
if(ret) {
printk(
"ST16C554: failed to register IRQ_EINT1(%d)\n", YC_mul232_IRQ1);
goto UART1_failed;
}
return 0;
UART1_failed:
free_irq(YC_mul232_IRQ1, NULL);
UART0_failed:
printk(
"ST16C554 DEVICE: failed to register \n");
devfs_unregister(devfs_ST0D);
devfs_unregister(devfs_ST0C);
devfs_unregister(devfs_ST0B);
devfs_unregister(devfs_ST0A);
devfs_unregister(devfs_ST0E);
devfs_unregister(devfs_ST0F);
devfs_unregister(devfs_ST0G);
devfs_unregister(devfs_ST0H);
devfs_unregister(devfs_st_dir);
unregister_chrdev(stMajor, DEVICE_NAME);
return 0;
}
static
void __exit st16c554_exit(
void)
{
free_irq(YC_mul232_IRQ0, NULL);
free_irq(YC_mul232_IRQ1, NULL);
devfs_unregister(devfs_ST0D);
devfs_unregister(devfs_ST0C);
devfs_unregister(devfs_ST0B);
devfs_unregister(devfs_ST0A);
devfs_unregister(devfs_ST0E);
devfs_unregister(devfs_ST0F);
devfs_unregister(devfs_ST0G);
devfs_unregister(devfs_ST0H);
devfs_unregister(devfs_st_dir);
unregister_chrdev(stMajor, DEVICE_NAME);
iounmap((
void *) (st0A.pbyBase0));
iounmap((
void *) (st0B.pbyBase0));
iounmap((
void *) (st0C.pbyBase0));
iounmap((
void *) (st0D.pbyBase0));
iounmap((
void *) (st0E.pbyBase0));
iounmap((
void *) (st0F.pbyBase0));
iounmap((
void *) (st0G.pbyBase0));
iounmap((
void *) (st0H.pbyBase0));
}
module_init(st16c554_init);
module_exit(st16c554_exit);
posted on
2015-11-11 16:40
嵌入式操作系统
阅读(
735
) 评论(
0
)
编辑
收藏
举报
刷新页面
返回顶部
导航
博客园
首页
新随笔
联系
订阅
管理
公告