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

📄 spull.c

📁 LINUX设备驱动程序第二版配套源码 LINUX设备驱动程序第二版配套源码 Alessandro rubini&Jonathan corbet著 中国电力出版社 魏永明 骆刚 姜君译 69元
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * spull.c -- the simple partitionable utility * * Tested with 2.0 on the x86, Sparc *********/#ifndef __KERNEL__#  define __KERNEL__#endif#ifndef MODULE#  define MODULE#endif#define __NO_VERSION__ /* don't define kernel_verion in module.h */#include <linux/module.h>#include <linux/version.h>char kernel_version [] = UTS_RELEASE;#include <linux/sched.h>#include <linux/kernel.h> /* printk() */#include <linux/malloc.h> /* kmalloc() */#include <linux/fs.h>     /* everything... */#include <linux/errno.h>  /* error codes */#include <linux/timer.h>#include <linux/types.h>  /* size_t */#include <linux/fcntl.h>        /* O_ACCMODE */#include <linux/hdreg.h>  /* HDIO_GETGEO */#include <asm/system.h>   /* cli(), *_flags */#define MAJOR_NR spull_major /* force definitions on in blk.h */int spull_major; /* must be known to the compiler */#define SPULL_SHIFT 4                         /* max 16 partitions  */#define SPULL_MAXNRDEV 4                      /* max 4 device units */#define DEVICE_NR(device) (MINOR(device)>>SPULL_SHIFT)#define DEVICE_NAME "pd"                      /* name for messaging */#define DEVICE_INTR spull_intrptr             /* pointer to the bottom half */#define DEVICE_NO_RANDOM                      /* no entropy to contribute */#define DEVICE_OFF(d) /* do-nothing */#if LINUX_VERSION_CODE < 0x10324 /* 1.3.36 */#  include <linux/../../drivers/block/blk.h>#else#  include <linux/blk.h>#endif#include "spull.h"        /* local definitions */#include "sysdep.h"/* Partitionable modules can't load before 1.3.7 */#if LINUX_VERSION_CODE < VERSION_CODE(1,3,7)#error "This modules requires at least Linux 1.3.7 to load"#endif/* * Non-prefixed symbols are static. They are meant to be assigned at * load time. Prefixed symbols are not static, so they can be used in * debugging. They are hidden anyways by register_symtab() unless * SPULL_DEBUG is defined. */static int major    = SPULL_MAJOR;static int devs     = SPULL_DEVS;static int rahead   = SPULL_RAHEAD;static int size     = SPULL_SIZE;static int irq      = 0; /* no interrupt driven by default */int spull_devs, spull_rahead, spull_size, spull_irq;/* The following items are obtained through kmalloc() in init_module() */Spull_Dev *spull_devices = NULL;int *spull_blksizes = NULL;int *spull_sizes = NULL;int spull_revalidate(kdev_t i_rdev);/* * Our generic hard disk */struct gendisk spull_gendisk = {    0,                /* Major number, assigned after dynamic retrieval */    "pd",             /* Major name */    SPULL_SHIFT,      /* Bits to shift to get real from partition */    1 << SPULL_SHIFT, /* Number of partitions per real */    SPULL_MAXNRDEV,   /* Maximum nr of devices */    NULL,             /* No init function (isn't called, anyways) */    NULL,             /* Partition array, allocated by init_module */    NULL,             /* Block sizes, allocated by init_module */    0,                /* Number of units: set by init_module */    NULL,             /* "real_devices" pointer: not used */    NULL              /* Next */};struct hd_struct *spull_partitions = NULL;/* * Open and close */int spull_open (struct inode *inode, struct file *filp){    Spull_Dev *dev; /* device information */    int num = DEVICE_NR(inode->i_rdev); /* the real device */    if (num >= spull_devs) return -ENODEV;    dev = spull_devices + num;    /* and use filp->private_data to point to the device data */    filp->private_data = dev;    /* kill the timer associated to the device: it might be active */    del_timer(&dev->timer);    /*     * If no data area is there, allocate it. Clear its head as     * well to prevent memory corruption due to bad partition info.     */    if (!dev->data) {        dev->data = vmalloc(dev->size);        memset(dev->data,0,2048);    }    if (!dev->data)        return -ENOMEM;    dev->usage++;    MOD_INC_USE_COUNT;    return 0;          /* success */}void spull_release (struct inode *inode, struct file *filp){    Spull_Dev *dev = spull_devices + DEVICE_NR(inode->i_rdev);    dev->usage--;    /*     * Leave one minute timeout before deallocating the device.     */    if (!dev->usage) {        dev->timer.expires = jiffies + 60 * HZ;        add_timer(&dev->timer);        /* but flush it right now */        fsync_dev(inode->i_rdev);        invalidate_buffers(inode->i_rdev);    }    fsync_dev(inode->i_rdev);    invalidate_buffers(inode->i_rdev);    MOD_DEC_USE_COUNT;}/* * The timer function. As argument it receives the device */void spull_expires(unsigned long data){    Spull_Dev *dev = (Spull_Dev *)data;    if (dev->usage || !dev->data) {        printk(KERN_WARNING "spull: timer mismatch for device %i\n",               dev - spull_devices);        return;    }    PDEBUG("freeing device %i\n",dev - spull_devices);    vfree(dev->data);    dev->data=0;    return;}    /* * The ioctl() implementation */int spull_ioctl (struct inode *inode, struct file *filp,                 unsigned int cmd, unsigned long arg){    int err, size;    struct hd_geometry *geo = (struct hd_geometry *)arg;    PDEBUG("ioctl 0x%x 0x%lx\n", cmd, arg);    switch(cmd) {      case BLKGETSIZE:        /* Return the device size, expressed in sectors */        if (!arg) return -EINVAL; /* NULL pointer: not valid */        err=verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));        if (err) return err;        size = spull_gendisk.part[MINOR(inode->i_rdev)].nr_sects;        put_user (size, (long *) arg);        return 0;      case BLKFLSBUF: /* flush */        if (!suser()) return -EACCES; /* only root */        fsync_dev(inode->i_rdev);        invalidate_buffers(inode->i_rdev);        return 0;      case BLKRAGET: /* return the readahead value */        if (!arg)  return -EINVAL;        err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));        if (err) return err;        put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);        return 0;      case BLKRASET: /* set the readahead value */        if (!suser()) return -EACCES;        if (arg > 0xff) return -EINVAL; /* limit it */        read_ahead[MAJOR(inode->i_rdev)] = arg;        return 0;      case BLKRRPART: /* re-read partition table: fake a disk change */        return spull_revalidate(inode->i_rdev);      RO_IOCTLS(inode->i_rdev, arg); /* the default RO operations */      case HDIO_GETGEO:        /*         * get geometry: we have to fake one...  trim the size to a         * multiple of 64 (32k): tell we have 16 sectors, 4 heads,         * whatever cylinders. Tell also that data starts at sector 4.         */        size = spull_size * 2; /* 2 sectors per kilobyte */        size &= ~0x3f; /* multiple of 64 */        if (geo==NULL) return -EINVAL;        err = verify_area(VERIFY_WRITE, geo, sizeof(*geo));        if (err) return err;        put_user(size >> 6, &geo->cylinders);        put_user(        4, &geo->heads);        put_user(       16, &geo->sectors);        put_user(        4, &geo->start);        return 0;    }    return -EINVAL; /* unknown command */}/* * Support for removable devices */int spull_check_change(kdev_t i_rdev){    int devnr = DEVICE_NR(i_rdev);    Spull_Dev *dev = spull_devices + devnr;    if (devnr >= spull_devs) /* paranoid */        return 0;    PDEBUG("check_change for dev %i\n",MINOR(i_rdev));    if (dev->data)        return 0; /* still valid */    return 1; /* expired */}int spull_revalidate(kdev_t i_rdev){    /* first partition, # of partitions */    int part1 = (DEVICE_NR(i_rdev) << SPULL_SHIFT) + 1;    int npart = (1 << SPULL_SHIFT) -1;    /* first clear old partition information */    memset(spull_gendisk.sizes+part1, 0, npart*sizeof(int));    memset(spull_gendisk.part +part1, 0, npart*sizeof(struct hd_struct));    /* then fill new info */    printk(KERN_INFO "Spull partition check: ");    resetup_one_dev(&spull_gendisk, DEVICE_NR(i_rdev));    return 0;}/* * The file operations */struct file_operations spull_fops = {    NULL,          /* lseek: default */    block_read,    block_write,    NULL,          /* spull_readdir */    NULL,          /* spull_select */    spull_ioctl,    NULL,          /* spull_mmap */    spull_open,    spull_release,    block_fsync,    NULL,          /* spull_fasync */    spull_check_change,    spull_revalidate};/*

⌨️ 快捷键说明

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