Linux 块设备驱动 实例(4)


/*
 * The device operations structure.
 */
static struct block_device_operations sbull_ops = {
    .owner           = THIS_MODULE,
    .open              = sbull_open,
    .release      = sbull_release,
    .media_changed   = sbull_media_changed,
    .revalidate_disk = sbull_revalidate,
    .ioctl             = sbull_ioctl,
    .getgeo            = sbull_getgeo,
};


/*
 * Set up our internal device.
 */
// 初始化设备结构体 static struct sbull_dev *Devices中的成员
static void setup_device(struct sbull_dev *dev, int which)
{
    /*
     * Get some memory.
     */
    memset (dev, 0, sizeof (struct sbull_dev));
    dev->size = nsectors*hardsect_size;
    // 分配一片虚拟地址连续的内存空间,作为块设备。
    dev->data = vmalloc(dev->size);  
    if (dev->data == NULL) {
        printk (KERN_NOTICE "vmalloc failure.\n");
        return;
    }
    spin_lock_init(&dev->lock);
   
    /*
     * The timer which "invalidates" the device.
     */
    init_timer(&dev->timer);
    dev->timer.data = (unsigned long) dev;
    dev->timer.function = sbull_invalidate;
   
    /*
     * The I/O queue, depending on whether we are using our own
     * make_request function or not.
     */
    switch (request_mode) {
        case RM_NOQUEUE:
        dev->queue = blk_alloc_queue(GFP_KERNEL);
        if (dev->queue == NULL)
            goto out_vfree;
        blk_queue_make_request(dev->queue, sbull_make_request);
        break;

case RM_FULL:
        dev->queue = blk_init_queue(sbull_full_request, &dev->lock);
        if (dev->queue == NULL)
            goto out_vfree;
        break;

default:
        printk(KERN_NOTICE "Bad request mode %d, using simple\n", request_mode);
            /* fall into.. */
   
        case RM_SIMPLE:
        dev->queue = blk_init_queue(sbull_request, &dev->lock);
        if (dev->queue == NULL)
            goto out_vfree;
        break;
    }
    blk_queue_hardsect_size(dev->queue, hardsect_size);
    dev->queue->queuedata = dev;
    /*
     * And the gendisk structure.
     */
    dev->gd = alloc_disk(SBULL_MINORS);
    if (! dev->gd) {
        printk (KERN_NOTICE "alloc_disk failure\n");
        goto out_vfree;
    }
    dev->gd->major = sbull_major;
    dev->gd->first_minor = which*SBULL_MINORS;
    dev->gd->fops = &sbull_ops;
    dev->gd->queue = dev->queue;
    dev->gd->private_data = dev;
    snprintf (dev->gd->disk_name, 32, "sbull%c", which + 'a');
    set_capacity(dev->gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));
    add_disk(dev->gd);
    return;

out_vfree:
    if (dev->data)
        vfree(dev->data);
}

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

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