📄 fifo-drv.c
字号:
/*
pio driver for LPT2NET project
author: zou jian guo <zounix@126.com>
date: 2004-10-18
update: 2005-01-6
pio_read:
read count bytes data to user,but if no enough data to read ,
then return the actual count bytes to user, the EF sigh
is the driver to bethought, the user needn't take account.
pio_write:
user write the count bytes to pio ,the FF sigh need to be
careful deal with;
pio_ioctl: number 1 is to reset pio
*/
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/poll.h> /* COPY_TO_USER */
#include <asm/system.h> /* cli(), *_flags */
#include <asm/arch/AT91RM9200.h> /* cli(), *_flags */
#include <asm/arch/hardware.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/delay.h> /* udelay */
#include <linux/interrupt.h>
#include <linux/tqueue.h>
#include <asm/io.h>
//#define readl(addr) (*(volatile unsigned int*)addr)
//#define readw(addr) (*(volatile unsigned short*)addr)
//#define readb(addr) (*(volatile unsigned char*)addr)
#define DEVICE_NAME "pio"
#define pio_MAJOR 254
#define pio_MINOR 0
#define SIGN_EF_RX (1<<0) //GPC0
#define SIGN_HF_RX (1<<1)
#define SIGN_FF_RX (1<<2)
#define SIGN_EF_TX (1<<3) //GPC3
#define SIGN_HF_TX (1<<4)
#define SIGN_FF_TX (1<<5)
#define RS485_TX_ENABLE (1<<15)
static unsigned long VM_pio_IO_BASE;
static int MAX_BUF_LEN=4096;
static char drv_buf[4096];
static AT91PS_SYS BASE_SYS=((AT91PS_SYS)AT91C_VA_BASE_SYS);
static void AT91_PIO_INIT(void)
{
/*
PC0 ->EF_RX
PC1 ->EF_RX
PC2 ->FF_RX
PC3 ->EF_TX
PC4 ->HF_TX
PC5 ->FF_TX
*/
unsigned int PIN_USED;
PIN_USED=AT91C_PIO_PC0 | AT91C_PIO_PC1 |AT91C_PIO_PC2 |
AT91C_PIO_PC3 | AT91C_PIO_PC4 |AT91C_PIO_PC5 |;
//pio clock enable
BASE_SYS->PMC_PCER |= (1<<AT91C_ID_PIOC);
//PIO ENABLE
BASE_SYS->PIOC_PER = PIN_USED |AT91C_PIO_PC15;
BASE_SYS->PIOC_PDR = ~(PIN_USED |AT91C_PIO_PC15);
//SET IO OUTPUT ENABLE
BASE_SYS->PIOC_OER = AT91C_PIO_PC15 |AT91C_PIO_PC14;
BASE_SYS->PIOC_ODR = ~( AT91C_PIO_PC14 |AT91C_PIO_PC15);
BASE_SYS->PIOC_OWER = AT91C_PIO_PC15 |AT91C_PIO_PC14;
BASE_SYS->PIOC_OWDR = ~(AT91C_PIO_PC14 |AT91C_PIO_PC15);
//pio interrupt disable
// BASE_SYS->PIOC_IDR = PIN_USED;
//Input Filter Enable Register
BASE_SYS->PIOC_IFER = PIN_USED;
//PULL UP ENABLE
BASE_SYS->PIOC_PPUER= PIN_USED;
//setup NCS2 TO 8bit data bus RD WR->50ns
BASE_SYS->EBI_SMC2_CSR[2] = 0x00004082; //ok=0x00004082->8bit 3081->16bit 0081->32bit
VM_pio_IO_BASE = (unsigned long)ioremap(0X30000000,0x10000);//+0X30000000; //NCS2
// printk("VM_pio_IO_BASE = %lX\n\r",VM_pio_IO_BASE);
}
static int pio_status(void)
{
return BASE_SYS->PIOC_PDSR;
}
/*********************************************************************/
static void do_reset()
{
printk("kernel# reset pio\n");
}
/*********************************************************************/
static ssize_t pio_write(struct file *filp,char *buffer, size_t count)
{
int i,j;
if(count > MAX_BUF_LEN)count = MAX_BUF_LEN;
copy_from_user(drv_buf , buffer, count);
for(i=0;i<count;i++){
while(!(BASE_SYS->PIOC_PDSR & SIGN_FF_TX)); //WAIT FOR NOT FULL
*((char *)VM_pio_IO_BASE) = drv_buf[i];
for(j=0;j<100000;j++);
}
return count;
}
/*********************************************************************/
static ssize_t pio_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
int i,j=0;
unsigned int stat;
if(count > MAX_BUF_LEN)
count=MAX_BUF_LEN;
//while((BASE_SYS->PIOC_PDSR & SIGN_HF_RX)); //WAIT FOR HF SIGN
for(i=0; i < count; i++){
while(!(BASE_SYS->PIOC_PDSR & SIGN_EF_RX)){//WAIT FOR NOT EMPTY
//if(++j >10000)break;
;
}
drv_buf[i] = readb(VM_pio_IO_BASE);
}
copy_to_user(buffer, (char *)drv_buf,count);
return count;
}
/*********************************************************************/
static int pio_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
switch(cmd){
case 0: BASE_SYS->PIOC_SODR = ~RS485_TX_ENABLE;
BASE_SYS->PIOC_CODR = RS485_TX_ENABLE;
printk("RS485 TX DISABLED\n");
break;
case 1: BASE_SYS->PIOC_SODR = RS485_TX_ENABLE;
BASE_SYS->PIOC_CODR = ~RS485_TX_ENABLE;
printk("RS485 TX ENABLED\n");
break;
default:
printk("error cmd number\n");break;
}
return 0;
}
/*********************************************************************/
static int pio_open(struct inode *inode, struct file *file)
{
MOD_INC_USE_COUNT;
AT91_PIO_INIT();
printk("device open sucess!\n");
return 0;
}
/*********************************************************************/
static int pio_release(struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
printk("device release\n");
return 0;
}
/*********************************************************************/
static struct file_operations pio_fops = {
owner: THIS_MODULE,
write: pio_write,
read: pio_read,
ioctl: pio_ioctl,
open: pio_open,
release: pio_release,
};
/*********************************************************************/
#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_pio_dir, devfs_pioraw;
#endif
/*********************************************************************/
static int __init pio_init(void)
{
#ifdef CONFIG_DEVFS_FS
devfs_pio_dir = devfs_mk_dir(NULL, "pio", NULL);
devfs_pioraw = devfs_register(devfs_pio_dir, "0", DEVFS_FL_DEFAULT,
pio_MAJOR, pio_MINOR, S_IFCHR | S_IRUSR | S_IWUSR,
&pio_fops, NULL);
#else
int result;
SET_MODULE_OWNER(&pio_fops);
result = register_chrdev(pio_MAJOR, "pio", &pio_fops);
if (result < 0) return result;
// if (pio_MAJOR == 0) pio_MAJOR = result; /* dynamic */
#endif
printk(DEVICE_NAME " initialized\n");
return 0;
}
/*********************************************************************/
static void __exit pio_exit(void)
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_pioraw);
devfs_unregister(devfs_pio_dir);
#else
unregister_chrdev(pio_MAJOR, "pio");
#endif
//kfree(pio_devices);
printk(DEVICE_NAME " unloaded\n");
}
/*********************************************************************/
module_init(pio_init);
module_exit(pio_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -