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

📄 spull.c

📁 LINUX设备驱动程序第二版配套源码 LINUX设备驱动程序第二版配套源码 Alessandro rubini&Jonathan corbet著 中国电力出版社 魏永明 骆刚 姜君译 69元
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Block-driver specific functions */void spull_request(void){    Spull_Dev *device;    u8 *ptr;    int size, minor, devnr;    while(1) {        INIT_REQUEST;        devnr = DEVICE_NR(CURRENT_DEV);        minor = MINOR(CURRENT_DEV);        /* Check if the minor number is in range */        if (devnr > spull_devs) {            static int count = 0;            if (count++ < 5) /* print the message at most five times */                printk(KERN_WARNING "spull: request for inexistent device\n");            end_request(0);            continue;        }        PDEBUGG("cmd %c for minor 0x%02x ( sec%li)\n",               CURRENT->cmd==READ ? 'r' : 'w', minor,CURRENT->sector);        device = spull_devices + devnr;	/* the sector size is 512 bytes */        ptr = device->data +            512 * (spull_partitions[minor].start_sect + CURRENT->sector);        size = CURRENT->current_nr_sectors * 512;        if (CURRENT->sector + CURRENT->current_nr_sectors >                spull_gendisk.part[minor].nr_sects) {            printk(KERN_WARNING "spull: request past end of device\n");            end_request(0);            continue;        }        switch(CURRENT->cmd) {          case READ:            memcpy(CURRENT->buffer, ptr, size); /* from spull to buffer */            break;          case WRITE:            memcpy(ptr, CURRENT->buffer, size); /* from buffer to spull */            break;          default:            /* can't happen */            end_request(0);            continue;        }        end_request(1); /* success */    }}/* * The fake interrupt-driven request */struct timer_list spull_timer; /* the engine for async invocation */void spull_irqdriven_request(void){    Spull_Dev *device;    u8 *ptr;    int size, minor, devnr;    /*     * Check for errors and start data transfer for the current request.     * The spull ramdisk performs the transfer right ahead,     * but delays acknolegment using a kernel timer.     */    while(1) {        INIT_REQUEST;        devnr = DEVICE_NR(CURRENT_DEV);        minor = MINOR(CURRENT_DEV);        /* then the core of the function is unchanged.... */        /* Check if the minor number is in range */        if (devnr > spull_devs) {            static int count = 0;            if (count++ < 5) /* print the message at most five times */                printk(KERN_WARNING "spull: request for inexistent device\n");            end_request(0);            continue;        }        PDEBUGG("cmd %c for minor 0x%02x ( sec%li)\n",               CURRENT->cmd==READ ? 'r' : 'w', minor,CURRENT->sector);        device = spull_devices + devnr;        ptr = device->data +            512 * (spull_partitions[minor].start_sect + CURRENT->sector);        size = CURRENT->current_nr_sectors * 512;        if (CURRENT->sector + CURRENT->current_nr_sectors >                spull_gendisk.part[minor].nr_sects) {            printk(KERN_WARNING "spull: request past end of device\n");            end_request(0);            continue;        }	/* ... and this is how the function completes: xfer now ... */        switch(CURRENT->cmd) {          case READ:            memcpy(CURRENT->buffer, ptr, size);            break;          case WRITE:            memcpy(ptr, CURRENT->buffer, size);            break;          default: /* should't happen */            end_request(0);            continue;        }        /* ... and wait for the timer to expire -- no end_request(1) */        spull_timer.expires = jiffies + spull_irq;        add_timer(&spull_timer);        return;    }}/* this is invoked when the timer expires */void spull_interrupt(unsigned long unused){     /*      * arg to end_request(), default to success, a real device might      * signal a failure, if it detects one      */    int fulfilled = 1;    end_request(fulfilled);    /* done one */    if (CURRENT) /* more of them? */        spull_irqdriven_request();  /* schedule the next */}/* * Finally, the module stuff */int init_module(void){    int result, i;    /*     * Copy the (static) cfg variables to public prefixed ones to allow     * snoozing with a debugger.     */    spull_major    = major;    spull_devs     = devs;    spull_rahead   = rahead;    spull_size     = size;    /*     * Register your major, and accept a dynamic number     */    result = register_blkdev(spull_major, "spull", &spull_fops);    if (result < 0) {        printk(KERN_WARNING "spull: can't get major %d\n",spull_major);        return result;    }    if (spull_major == 0) spull_major = result; /* dynamic */    major = spull_major; /* Use `major' later on to save typing */    spull_gendisk.major = major; /* was unknown at load time */    /*      * allocate the devices -- we can't have them static, as the number     * can be specified at load time     */    spull_devices = kmalloc(spull_devs * sizeof (Spull_Dev), GFP_KERNEL);    if (!spull_devices)        goto fail_malloc;    memset(spull_devices, 0, spull_devs * sizeof (Spull_Dev));    for (i=0; i < spull_devs; i++) {        /* data and usage remain zeroed */        spull_devices[i].size = 1024 * spull_size;        init_timer(&(spull_devices[i].timer));        spull_devices[i].timer.data = (unsigned long)(spull_devices+i);        spull_devices[i].timer.function = spull_expires;    }    blk_dev[major].request_fn = spull_request;    read_ahead[major] = spull_rahead;    result = -ENOMEM; /* for the possible errors */    /* Prepare the `size' array and zero it. */    spull_sizes = kmalloc( (spull_devs << SPULL_SHIFT) * sizeof(int),                          GFP_KERNEL);    if (!spull_sizes)        goto fail_malloc;    /* Start with zero-sized partitions, and correctly sized units */    memset(spull_sizes, 0, (spull_devs << SPULL_SHIFT) * sizeof(int));    for (i=0; i< spull_devs; i++)        spull_sizes[i<<SPULL_SHIFT] = spull_size;    blk_size[MAJOR_NR] = spull_gendisk.sizes = spull_sizes;    /* Allocate the partitions, and refer the array in spull_gendisk. */    spull_partitions = kmalloc( (spull_devs << SPULL_SHIFT) *                               sizeof(struct hd_struct), GFP_KERNEL);    if (!spull_partitions)        goto fail_malloc;    memset(spull_partitions, 0, (spull_devs << SPULL_SHIFT) *           sizeof(struct hd_struct));    /* fill whole-disk entries */    for (i=0; i < spull_devs; i++) {        /* start_sect is already 0, and sects are 512 bytes long */        spull_partitions[i << SPULL_SHIFT].nr_sects = 2 * spull_size;    }    spull_gendisk.part = spull_partitions;#if 0    /*     * Well, now a *real* driver should call resetup_one_dev().     * Avoid it here, as there's no allocated data in spull yet.     */    for (i=0; i< spull_devs; i++) {        printk(KERN INFO "Spull partition check: ");        resetup_one_dev(&spull_gendisk, i);    }#endif    /* dump the partition table to see it */    for (i=0; i < spull_devs << SPULL_SHIFT; i++)        PDEBUGG("part %i: beg %lx, size %lx\n", i,               spull_partitions[i].start_sect,               spull_partitions[i].nr_sects);#ifndef SPULL_DEBUG    register_symtab(NULL); /* otherwise, leave global symbols visible */#endif    /*     * Allow interrupt-driven operation, if "irq=" has been specified     */    spull_irq = irq; /* copy the static variable to the visible one */    if (spull_irq) {        PDEBUG("setting timer\n");        spull_timer.function = spull_interrupt;        blk_dev[major].request_fn = spull_irqdriven_request;    }        return 0; /* succeed */  fail_malloc:    read_ahead[major] = 0;    if (spull_sizes) kfree(spull_sizes);    blk_size[major] = NULL;    if (spull_partitions) kfree(spull_partitions);    if (spull_devices) kfree(spull_devices);    unregister_chrdev(major, "spull");    return result;}void cleanup_module(void){    int i;    /* first of all, flush it all and reset all the data structures */    for (i = 0; i < (spull_devs << SPULL_SHIFT); i++)        fsync_dev(MKDEV(spull_major, i)); /* flush the devices */    blk_dev[major].request_fn = NULL;    read_ahead[major] = 0;    kfree(blk_size[major]); /* which is gendisk->sizes as well */    blk_size[major] = NULL;    kfree(spull_gendisk.part);    /* finally, the usual cleanup */    unregister_blkdev(major, "spull");    for (i=0; i < spull_devs; i++) {        if (spull_devices[i].data)            vfree(spull_devices[i].data);        del_timer(&spull_devices[i].timer);    }    kfree(spull_devices);}

⌨️ 快捷键说明

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