drwxr-xr-x 2 root root 0 4월 18 03:52 .
drwxr-xr-x 10 root root 5120 4월 19 11:39 ..
같은 major 번호와 다른 minor 번호를 가진다.
mintor 번호를 따로 가진다면, device driver를 따로 가져야 한다.
그렇다면.. 멀티테스킹에서
write 함수는 minor 번호만큼 가지고 있어야 한다.
하나가지고 공통으로 쓰기 어려우니. minor 번호당 write 함수가 있어야 한다.
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <asm/uaccess.h> //copy_to_user
#include <asm/io.h> //outb, inb
#include <linux/delay.h> //mdelay, udelay
#define FND 0xf1000000
#define FND_CS0 (*((volatile unsigned short *)(FND)))
#define FND_CS1 (*((volatile unsigned short *)(FND + 0x00100000)))
#define FND_CS2 (*((volatile unsigned short *)(FND + 0x00200000)))
#define FND_CS3 (*((volatile unsigned short *)(FND + 0x00300000)))
#define ADDR_FND_CS0 ((volatile unsigned short *)FND)
#define ADDR_FND_CS1 ((volatile unsigned short *)(FND + 0x00100000))
#define ADDR_FND_CS2 ((volatile unsigned short *)(FND + 0x00200000))
#define ADDR_FND_CS3 ((volatile unsigned short *)(FND + 0x00300000))
static short fnd_val[] = {0x3f3f,0x0606,0x5b5b,0x4f4f,0x6666,0x6d6d,0x7c7c,0x2727,0x7f7f,0x6767};
static int FND_MAJOR = 0;
//int fnd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
int fnd0_open (struct inode *inode, struct file *filp)
{
printk("fnd0_open\n");
MOD_INC_USE_COUNT;
return 0; /* success */
}
int fnd0_release (struct inode *inode, struct file *filp)
{
printk("fnd0_close\n");
MOD_DEC_USE_COUNT;
return 0;
}
ssize_t fnd0_read (struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
short data;
data = FND_CS0;
// equals
//data = inw(ADDR_FND_CS0);
printk("read data => %04x\n",data);
copy_to_user(buf, &data, count);
return(count);
}
ssize_t fnd0_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
int data;
copy_from_user(&data, buf, count);
printk("write data => %08x\n",data);
FND_CS0 = fnd_val[data];
// equals
//outw(fnd_val[data], ADDR_FND_CS0);
return(count);
}
int fnd0_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case 10:
printk("\n");
printk("cmd = 1\n");
FND_CS0 = 0x0000;
break;
default:
break;
}
return 0;
}
int fnd1_open (struct inode *inode, struct file *filp)
{
printk("fnd1_open\n");
MOD_INC_USE_COUNT;
return 0; /* success */
}
int fnd1_release (struct inode *inode, struct file *filp)
{
printk("fnd1_close\n");
MOD_DEC_USE_COUNT;
return 0;
}
ssize_t fnd1_read (struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
short data;
data = FND_CS1;
// equals
//data = inw(ADDR_FND_CS0);
printk("read data => %04x\n",data);
copy_to_user(buf, &data, count);
return(count);
}
ssize_t fnd1_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
int data;
copy_from_user(&data, buf, count);
printk("write data => %08x\n",data);
FND_CS1 = fnd_val[data];
// equals
//outw(fnd_val[data], ADDR_FND_CS1);
return(count);
}
int fnd1_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case 10:
printk("\n");
printk("cmd = 1\n");
FND_CS1 = 0x0000;
break;
default:
break;
}
return 0;
}
int fnd2_open (struct inode *inode, struct file *filp)
{
printk("fnd2_open\n");
MOD_INC_USE_COUNT;
return 0; /* success */
}
int fnd2_release (struct inode *inode, struct file *filp)
{
printk("fnd2_close\n");
MOD_DEC_USE_COUNT;
return 0;
}
ssize_t fnd2_read (struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
short data;
data = FND_CS2;
// equals
//data = inw(ADDR_FND_CS2);
printk("read data => %04x\n",data);
copy_to_user(buf, &data, count);
return(count);
}
ssize_t fnd2_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
int data;
copy_from_user(&data, buf, count);
printk("write data => %08x\n",data);
FND_CS2 = fnd_val[data];
// equals
//outw(fnd_val[data], ADDR_FND_CS2);
return(count);
}
int fnd2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case 10:
printk("\n");
printk("cmd = 1\n");
FND_CS2 = 0x0000;
break;
default:
break;
}
return 0;
}
int fnd3_open (struct inode *inode, struct file *filp)
{
printk("fnd3_open\n");
MOD_INC_USE_COUNT;
return 0; /* success */
}
int fnd3_release (struct inode *inode, struct file *filp)
{
printk("fnd3_close\n");
MOD_DEC_USE_COUNT;
return 0;
}
ssize_t fnd3_read (struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
short data;
data = FND_CS3;
// equals
//data = inw(ADDR_FND_CS3);
printk("read data => %04x\n",data);
copy_to_user(buf, &data, count);
return(count);
}
ssize_t fnd3_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
int data;
copy_from_user(&data, buf, count);
printk("write data => %08x\n",data);
FND_CS3 = fnd_val[data];
// equals
//outw(fnd_val[data], ADDR_FND_CS0);
return(count);
}
int fnd3_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case 10:
printk("\n");
printk("cmd = 1\n");
FND_CS3 = 0x0000;
break;
default:
break;
}
return 0;
}
void fnd_clear(void)
{
FND_CS0 = 0x0000;
FND_CS1 = 0x0000;
FND_CS2 = 0x0000;
FND_CS3 = 0x0000;
//mdelay(500);
}
/*
struct file_operations fnd_fops = {
read: fnd_read,
write: fnd_write,
open: fnd_open,
ioctl: fnd_ioctl,
release: fnd_release,
};
*/
struct file_operations minor0_fops =
{
read : fnd0_read,
write : fnd0_write,
open : fnd0_open,
release : fnd0_release,
ioctl : fnd0_ioctl,
};
struct file_operations minor1_fops =
{
read : fnd1_read,
write : fnd1_write,
open : fnd1_open,
release : fnd1_release,
ioctl : fnd1_ioctl,
};
struct file_operations minor2_fops =
{
read : fnd2_read,
write : fnd2_write,
open : fnd2_open,
release : fnd2_release,
ioctl : fnd2_ioctl,
};
struct file_operations minor3_fops =
{
read : fnd3_read,
write : fnd3_write,
open : fnd3_open,
release : fnd3_release,
ioctl : fnd3_ioctl,
};
int minor_open (struct inode *inode, struct file *filp)
{
printk( "call minor_open\n" );
printk("MINOR(inode->i_rdev) : %d\n", MINOR(inode->i_rdev));
switch (MINOR(inode->i_rdev))
{
case 0: filp->f_op = &minor0_fops; break;
case 1: filp->f_op = &minor1_fops; break;
case 2: filp->f_op = &minor2_fops; break;
case 3: filp->f_op = &minor3_fops; break;
default : return -ENXIO;
}
if (filp->f_op && filp->f_op->open)
return filp->f_op->open(inode,filp);
return -2;
}
struct file_operations minor_fops =
{
open : minor_open,
};
static int __init fnd_init(void)
{
int result;
printk("FND module is up...\n");
fnd_clear(); // H/W Initialization
//result = register_chrdev(FND_MAJOR, "FND", &fnd_fops);
result = register_chrdev(FND_MAJOR, "FND", &minor_fops);
if (result < 0) {
printk(KERN_WARNING " can't get major \n");
return result;
}
if(FND_MAJOR == 0)
FND_MAJOR = result;
printk("FND_MAJOR = %d\n", FND_MAJOR);
return 0;
}
static void __exit fnd_exit(void)
{
unregister_chrdev(FND_MAJOR, "FND");
printk("FND module is down...\n");
}
module_init(fnd_init);
module_exit(fnd_exit);
/***************************************
* Filename: fnd_app.c
* Title: fnd Device Application
* Desc: Implementation of system call
***************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main(void)
{
int retn;
int fd;
int flag = 0;
int fnd_no, menu;
char dev_name[100];
while(1)
{
printf("\n\n===== FND Test Program ====\n");
printf(" 0. FND0 Test\n");
printf(" 1. FND1 Test\n");
printf(" 2. FND2 Test\n");
printf(" 3. FND3 Test\n");
printf(" 4. Program Quit\n");
do {
printf(" Select Menu => ");
scanf("%d", &fnd_no);
} while(fnd_no<0 || fnd_no>4);
if(fnd_no == 4) break;
while(1)
{
printf("\nFND%d Test...\n", fnd_no);
do {
printf("Select(0.0_print,1.1_print, ...,9.9_print,10.clear,11.Quit) => ");
scanf("%d", &menu);
} while(menu<0 || menu>11);
if(menu == 11) break;
sprintf(dev_name, "/dev/FND%d", fnd_no);
fd = open(dev_name, O_RDWR);
if (fd<0) {
perror(dev_name);
exit(-1);
}
else printf("/dev/FND%d detected(fd:%d)...\n", fnd_no, fd);
if (menu == 10) {
ioctl(fd, menu, flag); // clear
}
else { // menu is 4byte(int)
write(fd, &menu, sizeof(menu));
}
close(fd);
}
}
return 0;
}