📄 spull.c
字号:
* 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 + -