⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fifo-drv.c

📁 ARM9200+嵌入式linux下串口通信程序
💻 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 + -