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

📄 shortbak.c

📁 并口驱动程序
💻 C
字号:
#ifndef __KERNEL__
#  define __KERNEL__
#endif
#ifndef MODULE
#  define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>

#include <linux/sched.h>
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h>     /* everything... */
#include <linux/errno.h>  /* error codes */
#include <linux/delay.h>  /* udelay */
#include <linux/malloc.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/tqueue.h>

#include <asm/io.h>

#include "sysdep.h"

#define SHORT_NR_PORTS 1 /* use 8 ports by default */

static int major = 0; /* dynamic by default */
MODULE_PARM(major, "i");

/* default is the first printer port on PC's. "short_base" is there too
   because it's what we want to use in the code */
static unsigned long base = 0x378;
MODULE_PARM(base, "l");

/* The interrupt line is undefined by default. "short_irq" is as above */
static int irq = 7;
MODULE_PARM(irq, "i");

MODULE_AUTHOR ("Alessandro Rubini");

DECLARE_WAIT_QUEUE_HEAD(short_queue);



int short_open (struct inode *inode, struct file *filp)
{
    
    MOD_INC_USE_COUNT;
    return 0;
}

int short_release (struct inode *inode, struct file *filp)
{
    MOD_DEC_USE_COUNT;
    return 0;
}

ssize_t do_short_read (struct inode *inode, struct file *filp, char *buf,
                size_t count, loff_t *f_pos)
{
    int retval = count;
	unsigned long=base;
    unsigned char *kbuf,*ptr;

    interruptible_sleep_on(&short_queue);

    kbuf=kmalloc(count, GFP_KERNEL);
    if (!kbuf) return -ENOMEM;
    ptr=kbuf
    while (count--) {
         *(ptr++) = inb(address);
	     rmb();
	}
    
    if ( (retval > 0) && copy_to_user(buf, kbuf, retval))
	retval = -EFAULT;
    kfree(kbuf);
    return retval;
}

ssize_t short_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
    return do_short_read(filp->f_dentry->d_inode, filp, buf, count, f_pos);
}



ssize_t do_short_write (struct inode *inode, struct file *filp, const char *buf,
                size_t count, loff_t *f_pos)
{
    int retval = count;
    unsigned long address = base;
    unsigned char *kbuf=kmalloc(count, GFP_KERNEL), *ptr;
    if (!kbuf) return -ENOMEM;
    if (copy_from_user(kbuf, buf, count))
	return -EFAULT;
    ptr=kbuf;
    while (count--) {
            outb(*(ptr++), address);
	    wmb();
	}
        
    kfree(kbuf);
    return retval;
}

ssize_t short_write(struct file *filp, const char *buf, size_t count,
                loff_t *f_pos)
{
    return do_short_write(filp->f_dentry->d_inode, filp, buf, count, f_pos);
}

void short_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    wake_up_interruptible(&short_queue); /* awake any reading process */
}

struct file_operations short_fops = {
    read: short_read,
    write: short_write,
    open: short_open,
    release: short_release,
};


int short_init(void)
{
  int result;
  short_base=base;
  short_irq=irq;

  SET_MODULE_OWNER(&short_fops);
  
  result=check_region(short_base,SHORT_NR_PORTS);
  if (result) {
     printk(KERN_INFO "short: can't get I/O port address 0x%lx\n",short_base);
	 return result;
  }
     request_region(short_base, SHORT_NR_PORTS, "short");
   
  result = register_chrdev(major, "short", &short_fops);
  if (result<0) {
     printk(KERN_INFO "short: can't get major number\n");
     release_region(short_base,SHORT_NR_PORTS);
     return result;
  }
  if (major == 0) major = result; /* dynamic */

  if (short_irq >= 0) {
        result = request_irq(short_irq, short_interrupt,
                             SA_INTERRUPT, "short", NULL);
        if (result) {
            printk(KERN_INFO "short: can't get assigned irq %i\n",
                   short_irq);
            short_irq = -1;
        }
        else { /* actually enable it -- assume this *is* a parallel port */
            outb(0x10,short_base+2);
        }
    }

  return 0;
}

void short_cleanup(void)
{
    if (short_irq >= 0) {
        outb(0x0, short_base + 2);   /* disable the interrupt */
        free_irq(short_irq, NULL);
    }
        
    unregister_chrdev(major, "short");
    
	release_region(short_base,SHORT_NR_PORTS);
}

module_init(short_init);
module_exit(short_cleanup);



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -