Linux 块设备驱动 实例(3)

static int sbull_open(struct inode *inode, struct file *filp)
{
    struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data;
    //printk("<0>" "fdfjdlksjfdlkj\n");   
    del_timer_sync(&dev->timer);
    filp->private_data = dev;
    spin_lock(&dev->lock);
    if (! dev->users)
        check_disk_change(inode->i_bdev);
    dev->users++;
    spin_unlock(&dev->lock);
    return 0;
}

static int sbull_release(struct inode *inode, struct file *filp)
{
    struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data;

spin_lock(&dev->lock);
    dev->users--;

if (!dev->users) {
        dev->timer.expires = jiffies + INVALIDATE_DELAY;
        add_timer(&dev->timer);
    }
    spin_unlock(&dev->lock);

return 0;
}

/*
 * Look for a (simulated) media change.
 */
int sbull_media_changed(struct gendisk *gd)
{
    struct sbull_dev *dev = gd->private_data;
   
    return dev->media_change;
}

/*
 * Revalidate.  WE DO NOT TAKE THE LOCK HERE, for fear of deadlocking
 * with open.  That needs to be reevaluated.
 */
int sbull_revalidate(struct gendisk *gd)
{
    struct sbull_dev *dev = gd->private_data;
   
    if (dev->media_change) {
        dev->media_change = 0;
        memset (dev->data, 0, dev->size);
    }
    return 0;
}

/*
 * The "invalidate" function runs out of the device timer; it sets
 * a flag to simulate the removal of the media.
 */
void sbull_invalidate(unsigned long ldev)
{
    struct sbull_dev *dev = (struct sbull_dev *) ldev;

spin_lock(&dev->lock);
    if (dev->users || !dev->data)
        printk (KERN_WARNING "sbull: timer sanity check failed\n");
    else
        dev->media_change = 1;
    spin_unlock(&dev->lock);
}

/*
 * The ioctl() implementation
 */

int sbull_ioctl (struct inode *inode, struct file *filp,
                 unsigned int cmd, unsigned long arg)
{
    long size;
    struct hd_geometry geo;
    struct sbull_dev *dev = filp->private_data;

switch(cmd) {
        case HDIO_GETGEO:
            /*
         * Get geometry: since we are a virtual device, we have to make
         * up something plausible.  So we claim 16 sectors, four heads,
         * and calculate the corresponding number of cylinders.  We set the
         * start of data at sector four.
         */
        //printk("<0>""-------------size=%d\n",size);
        /****************for early version************/
        //size = dev->size*(hardsect_size/KERNEL_SECTOR_SIZE);
        //printk("<0>""-------------size=%d\n",size);
        //geo.cylinders = (size & ~0x3f) >> 6;
        //geo.cylinders=2000;
        //geo.heads = 4;
        //geo.sectors = 16;
        //geo.sectors=2560;
        //geo.start = 0;
        //if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
        //    return -EFAULT;
        return 0;
    }

return -ENOTTY; /* unknown command */
}

static int sbull_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
    unsigned long size;
    struct sbull_dev *pdev = bdev->bd_disk->private_data;

size = pdev->size;
    geo->cylinders = (size & ~0x3f) >> 6;
    geo->heads    = 4;
    geo->sectors = 16;
    geo->start = 0;
    return 0;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwsdjs.html