* features to asm/floppy.h.
*/
+/*
+ * 1998/1/21 -- Richard Gooch <rgooch@atnf.csiro.au> -- devfs support
+ */
+
/*
* 1998/05/07 -- Russell King -- More portability cleanups; moved definition of
* interrupt and dma channel to asm/floppy.h. Cleaned up some formatting &
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
-#include <linux/version.h>
#define FDPATCHES
#include <linux/fdreg.h>
-/*
- * 1998/1/21 -- Richard Gooch <rgooch@atnf.csiro.au> -- devfs support
- */
-
#include <linux/fd.h>
#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/buffer_head.h> /* for invalidate_buffers() */
/*
* record each buffers capabilities
*/
-static spinlock_t floppy_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(floppy_lock);
static struct completion device_release;
static unsigned short virtual_dma_port = 0x3f0;
static int irqdma_allocated;
-#define LOCAL_END_REQUEST
#define DEVICE_NAME "floppy"
#include <linux/blkdev.h>
{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
};
-#define NUMBER(x) (sizeof(x) / sizeof(*(x)))
#define SECTSIZE (_FD_SECTSIZE(*floppy))
/* Auto-detection: Disk type used until the next media change occurs. */
static sector_t floppy_sizes[256];
+static char floppy_device_name[] = "floppy";
+
/*
* The driver is trying to determine the correct media format
* while probing is set. rw_interrupt() clears it after a
}
#endif
-#ifdef DEBUGT
-static long unsigned debugtimer;
-#endif
-
/*
* Debugging
* =========
*/
+#ifdef DEBUGT
+static long unsigned debugtimer;
+
static inline void set_debugt(void)
{
-#ifdef DEBUGT
debugtimer = jiffies;
-#endif
}
static inline void debugt(const char *message)
{
-#ifdef DEBUGT
if (DP->flags & DEBUGT)
printk("%s dtime=%lu\n", message, jiffies - debugtimer);
-#endif
}
+#else
+static inline void set_debugt(void) { }
+static inline void debugt(const char *message) { }
+#endif /* DEBUGT */
typedef void (*timeout_fn) (unsigned long);
-static struct timer_list fd_timeout = TIMER_INITIALIZER(floppy_shutdown, 0, 0);
+static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
static const char *timeout_message;
{
unsigned long flags;
- raw_cmd = 0;
+ raw_cmd = NULL;
if (!test_bit(0, &fdc_busy))
DPRINT("FDC access conflict!\n");
schedule_work(&floppy_work);
}
-static struct timer_list fd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(fd_timer, NULL, 0, 0);
static void cancel_activity(void)
{
return 0;
}
-static spinlock_t floppy_hlt_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(floppy_hlt_lock);
static int hlt_disabled;
static void floppy_disable_hlt(void)
{
for (i = 0; i < raw_cmd->cmd_count; i++)
r |= output_byte(raw_cmd->cmd[i]);
-#ifdef DEBUGT
debugt("rw_command: ");
-#endif
+
if (r) {
cont->error();
reset_fdc();
*/
static void seek_interrupt(void)
{
-#ifdef DEBUGT
debugt("seek interrupt:");
-#endif
if (inr != 2 || (ST0 & 0xF8) != 0x20) {
DPRINT("seek failed\n");
DRS->track = NEED_2_RECAL;
output_byte(FD_SEEK);
output_byte(UNIT(current_drive));
LAST_OUT(track);
-#ifdef DEBUGT
debugt("seek command:");
-#endif
}
static void recal_interrupt(void)
{
-#ifdef DEBUGT
debugt("recal interrupt:");
-#endif
if (inr != 2)
FDCS->reset = 1;
else if (ST0 & ST0_ECE) {
switch (DRS->track) {
case NEED_1_RECAL:
-#ifdef DEBUGT
debugt("recal interrupt need 1 recal:");
-#endif
/* after a second recalibrate, we still haven't
* reached track 0. Probably no drive. Raise an
* error, as failing immediately might upset
cont->redo();
return;
case NEED_2_RECAL:
-#ifdef DEBUGT
debugt("recal interrupt need 2 recal:");
-#endif
/* If we already did a recalibrate,
* and we are not at track 0, this
* means we have moved. (The only way
DRS->select_date = jiffies;
/* fall through */
default:
-#ifdef DEBUGT
debugt("recal interrupt default:");
-#endif
/* Recalibrate moves the head by at
* most 80 steps. If after one
* recalibrate we don't have reached
} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2
&& max_sensei);
}
- if (handler)
- schedule_bh(handler);
- else
+ if (!handler) {
FDCS->reset = 1;
+ return IRQ_NONE;
+ }
+ schedule_bh(handler);
is_alive("normal interrupt end");
/* FIXME! Was it really for us? */
static void recalibrate_floppy(void)
{
-#ifdef DEBUGT
debugt("recalibrate floppy:");
-#endif
do_floppy = recal_interrupt;
output_byte(FD_RECALIBRATE);
LAST_OUT(UNIT(current_drive));
*/
static void reset_interrupt(void)
{
-#ifdef DEBUGT
debugt("reset interrupt:");
-#endif
result(); /* get the status ready for set_fdc */
if (FDCS->reset) {
printk("reset set in interrupt, calling %p\n", cont->error);
static void do_wakeup(void)
{
reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
- cont = 0;
+ cont = NULL;
command_status += 2;
wake_up(&command_done);
}
buffer_track = -1;
setup_format_params(format_req.track << STRETCH(_floppy));
floppy_start();
-#ifdef DEBUGT
debugt("queue format request");
-#endif
}
static struct cont_t format_cont = {
add_disk_randomness(req->rq_disk);
floppy_off((long)req->rq_disk->private_data);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
/* We're done with the request */
current_req = NULL;
if (TESTF(FD_NEED_TWADDLE))
twaddle();
schedule_bh(floppy_start);
-#ifdef DEBUGT
debugt("queue fd request");
-#endif
return;
}
#undef REPEAT
* Misc Ioctl's and support
* ========================
*/
-static inline int fd_copyout(void *param, const void *address,
+static inline int fd_copyout(void __user *param, const void *address,
unsigned long size)
{
return copy_to_user(param, address, size) ? -EFAULT : 0;
}
-static inline int fd_copyin(void *param, void *address, unsigned long size)
+static inline int fd_copyin(void __user *param, void *address, unsigned long size)
{
return copy_from_user(address, param, size) ? -EFAULT : 0;
}
-#define _COPYOUT(x) (copy_to_user((void *)param, &(x), sizeof(x)) ? -EFAULT : 0)
-#define _COPYIN(x) (copy_from_user(&(x), (void *)param, sizeof(x)) ? -EFAULT : 0)
+#define _COPYOUT(x) (copy_to_user((void __user *)param, &(x), sizeof(x)) ? -EFAULT : 0)
+#define _COPYIN(x) (copy_from_user(&(x), (void __user *)param, sizeof(x)) ? -EFAULT : 0)
#define COPYOUT(x) ECALL(_COPYOUT(x))
#define COPYIN(x) ECALL(_COPYIN(x))
.done = raw_cmd_done
};
-static inline int raw_cmd_copyout(int cmd, char *param,
+static inline int raw_cmd_copyout(int cmd, char __user *param,
struct floppy_raw_cmd *ptr)
{
int ret;
struct floppy_raw_cmd *next, *this;
this = *ptr;
- *ptr = 0;
+ *ptr = NULL;
while (this) {
if (this->buffer_length) {
fd_dma_mem_free((unsigned long)this->kernel_data,
}
}
-static inline int raw_cmd_copyin(int cmd, char *param,
+static inline int raw_cmd_copyin(int cmd, char __user *param,
struct floppy_raw_cmd **rcmd)
{
struct floppy_raw_cmd *ptr;
int ret;
int i;
- *rcmd = 0;
+ *rcmd = NULL;
while (1) {
ptr = (struct floppy_raw_cmd *)
kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
return -ENOMEM;
*rcmd = ptr;
COPYIN(*ptr);
- ptr->next = 0;
+ ptr->next = NULL;
ptr->buffer_length = 0;
param += sizeof(struct floppy_raw_cmd);
if (ptr->cmd_count > 33)
for (i = 0; i < 16; i++)
ptr->reply[i] = 0;
ptr->resultcode = 0;
- ptr->kernel_data = 0;
+ ptr->kernel_data = NULL;
if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
if (ptr->length <= 0)
}
}
-static int raw_cmd_ioctl(int cmd, void *param)
+static int raw_cmd_ioctl(int cmd, void __user *param)
{
int drive, ret, ret2;
struct floppy_raw_cmd *my_raw_cmd;
return 0;
}
-static inline void clear_write_error(int drive)
-{
- CLEARSTRUCT(UDRWE);
-}
-
static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
int drive, int type, struct block_device *bdev)
{
struct block_device *bdev = opened_bdev[cnt];
if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
continue;
- __invalidate_device(bdev, 0);
+ __invalidate_device(bdev);
}
up(&open_lock);
} else {
return 0;
}
+static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ int drive = (long)bdev->bd_disk->private_data;
+ int type = ITYPE(drive_state[drive].fd_device);
+ struct floppy_struct *g;
+ int ret;
+
+ ret = get_floppy_geometry(drive, type, &g);
+ if (ret)
+ return ret;
+
+ geo->heads = g->head;
+ geo->sectors = g->sect;
+ geo->cylinders = g->track;
+ return 0;
+}
+
static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long param)
{
cmd = FDEJECT;
}
- /* generic block device ioctls */
- switch (cmd) {
- /* the following have been inspired by the corresponding
- * code for other block devices. */
- struct floppy_struct *g;
- case HDIO_GETGEO:
- {
- struct hd_geometry loc;
- ECALL(get_floppy_geometry(drive, type, &g));
- loc.heads = g->head;
- loc.sectors = g->sect;
- loc.cylinders = g->track;
- loc.start = 0;
- return _COPYOUT(loc);
- }
- }
-
/* convert the old style command into a new style command */
if ((cmd & 0xff00) == 0x0200) {
ECALL(normalize_ioctl(&cmd, &size));
/* copyin */
CLEARSTRUCT(&inparam);
if (_IOC_DIR(cmd) & _IOC_WRITE)
- ECALL(fd_copyin((void *)param, &inparam, size))
+ ECALL(fd_copyin((void __user *)param, &inparam, size))
switch (cmd) {
case FDEJECT:
return -EINVAL;
LOCK_FDC(drive, 1);
set_floppy(drive);
- CALL(i = raw_cmd_ioctl(cmd, (void *)param));
+ CALL(i = raw_cmd_ioctl(cmd, (void __user *)param));
process_fd_request();
return i;
}
if (_IOC_DIR(cmd) & _IOC_READ)
- return fd_copyout((void *)param, outparam, size);
+ return fd_copyout((void __user *)param, outparam, size);
else
return 0;
#undef OUT
const char *name = NULL;
static char temparea[32];
- if (type < NUMBER(default_drive_params)) {
+ if (type < ARRAY_SIZE(default_drive_params)) {
params = &default_drive_params[type].params;
if (type) {
name = default_drive_params[type].name;
/* Allow ioctls if we have write-permissions even if read-only open.
* Needed so that programs such as fdrawcmd still can work on write
* protected disks */
- if (filp->f_mode & 2
- || permission(filp->f_dentry->d_inode, 2, NULL) == 0)
+ if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE))
filp->private_data = (void *)8;
if (UFDCS->rawcmd == 1)
.open = floppy_open,
.release = floppy_release,
.ioctl = fd_ioctl,
+ .getgeo = fd_getgeo,
.media_changed = check_floppy_change,
.revalidate_disk = floppy_revalidate,
};
{
int base_minor = (drive < 4) ? drive : (124 + drive);
- if (UDP->cmos < NUMBER(default_drive_params)) {
+ if (UDP->cmos < ARRAY_SIZE(default_drive_params)) {
int i = 0;
do {
int minor = base_minor + (table_sup[UDP->cmos][i] << 2);
int *var;
int def_param;
int param2;
-} config_params[] = {
- {"allowed_drive_mask", 0, &allowed_drive_mask, 0xff, 0}, /* obsolete */
- {"all_drives", 0, &allowed_drive_mask, 0xff, 0}, /* obsolete */
- {"asus_pci", 0, &allowed_drive_mask, 0x33, 0},
- {"irq", 0, &FLOPPY_IRQ, 6, 0},
- {"dma", 0, &FLOPPY_DMA, 2, 0},
- {"daring", daring, 0, 1, 0},
+} config_params[] __initdata = {
+ {"allowed_drive_mask", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
+ {"all_drives", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
+ {"asus_pci", NULL, &allowed_drive_mask, 0x33, 0},
+ {"irq", NULL, &FLOPPY_IRQ, 6, 0},
+ {"dma", NULL, &FLOPPY_DMA, 2, 0},
+ {"daring", daring, NULL, 1, 0},
#if N_FDC > 1
- {"two_fdc", 0, &FDC2, 0x370, 0},
- {"one_fdc", 0, &FDC2, 0, 0},
+ {"two_fdc", NULL, &FDC2, 0x370, 0},
+ {"one_fdc", NULL, &FDC2, 0, 0},
#endif
- {"thinkpad", floppy_set_flags, 0, 1, FD_INVERTED_DCL},
- {"broken_dcl", floppy_set_flags, 0, 1, FD_BROKEN_DCL},
- {"messages", floppy_set_flags, 0, 1, FTD_MSG},
- {"silent_dcl_clear", floppy_set_flags, 0, 1, FD_SILENT_DCL_CLEAR},
- {"debug", floppy_set_flags, 0, 1, FD_DEBUG},
- {"nodma", 0, &can_use_virtual_dma, 1, 0},
- {"omnibook", 0, &can_use_virtual_dma, 1, 0},
- {"yesdma", 0, &can_use_virtual_dma, 0, 0},
- {"fifo_depth", 0, &fifo_depth, 0xa, 0},
- {"nofifo", 0, &no_fifo, 0x20, 0},
- {"usefifo", 0, &no_fifo, 0, 0},
- {"cmos", set_cmos, 0, 0, 0},
- {"slow", 0, &slow_floppy, 1, 0},
- {"unexpected_interrupts", 0, &print_unex, 1, 0},
- {"no_unexpected_interrupts", 0, &print_unex, 0, 0},
- {"L40SX", 0, &print_unex, 0, 0}
+ {"thinkpad", floppy_set_flags, NULL, 1, FD_INVERTED_DCL},
+ {"broken_dcl", floppy_set_flags, NULL, 1, FD_BROKEN_DCL},
+ {"messages", floppy_set_flags, NULL, 1, FTD_MSG},
+ {"silent_dcl_clear", floppy_set_flags, NULL, 1, FD_SILENT_DCL_CLEAR},
+ {"debug", floppy_set_flags, NULL, 1, FD_DEBUG},
+ {"nodma", NULL, &can_use_virtual_dma, 1, 0},
+ {"omnibook", NULL, &can_use_virtual_dma, 1, 0},
+ {"yesdma", NULL, &can_use_virtual_dma, 0, 0},
+ {"fifo_depth", NULL, &fifo_depth, 0xa, 0},
+ {"nofifo", NULL, &no_fifo, 0x20, 0},
+ {"usefifo", NULL, &no_fifo, 0, 0},
+ {"cmos", set_cmos, NULL, 0, 0},
+ {"slow", NULL, &slow_floppy, 1, 0},
+ {"unexpected_interrupts", NULL, &print_unex, 1, 0},
+ {"no_unexpected_interrupts", NULL, &print_unex, 0, 0},
+ {"L40SX", NULL, &print_unex, 0, 0}
EXTRA_FLOPPY_PARAMS
};
printk("\n");
} else
DPRINT("botched floppy option\n");
- DPRINT("Read linux/Documentation/floppy.txt\n");
+ DPRINT("Read Documentation/floppy.txt\n");
return 0;
}
static int have_no_fdc = -ENODEV;
+static ssize_t floppy_cmos_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *p;
+ int drive;
+
+ p = container_of(dev, struct platform_device,dev);
+ drive = p->id;
+ return sprintf(buf, "%X\n", UDP->cmos);
+}
+DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
+
static void floppy_device_release(struct device *dev)
{
complete(&device_release);
}
-static struct platform_device floppy_device = {
- .name = "floppy",
- .id = 0,
- .dev = {
- .release = floppy_device_release,
- }
-};
+static struct platform_device floppy_device[N_DRIVE];
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
{
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return NULL;
- if (((*part >> 2) & 0x1f) >= NUMBER(floppy_type))
+ if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
return NULL;
*part = 0;
return get_disk(disks[drive]);
}
-int __init floppy_init(void)
+static int __init floppy_init(void)
{
int i, unit, drive;
- int err;
+ int err, dr;
raw_cmd = NULL;
- for (i = 0; i < N_DRIVE; i++) {
- disks[i] = alloc_disk(1);
- if (!disks[i])
- goto Enomem;
+ for (dr = 0; dr < N_DRIVE; dr++) {
+ disks[dr] = alloc_disk(1);
+ if (!disks[dr]) {
+ err = -ENOMEM;
+ goto out_put_disk;
+ }
- disks[i]->major = FLOPPY_MAJOR;
- disks[i]->first_minor = TOMINOR(i);
- disks[i]->fops = &floppy_fops;
- sprintf(disks[i]->disk_name, "fd%d", i);
+ disks[dr]->major = FLOPPY_MAJOR;
+ disks[dr]->first_minor = TOMINOR(dr);
+ disks[dr]->fops = &floppy_fops;
+ sprintf(disks[dr]->disk_name, "fd%d", dr);
- init_timer(&motor_off_timer[i]);
- motor_off_timer[i].data = i;
- motor_off_timer[i].function = motor_off_callback;
+ init_timer(&motor_off_timer[dr]);
+ motor_off_timer[dr].data = dr;
+ motor_off_timer[dr].function = motor_off_callback;
}
devfs_mk_dir("floppy");
- if ((err = register_blkdev(FLOPPY_MAJOR, "fd")))
- goto out;
+
+ err = register_blkdev(FLOPPY_MAJOR, "fd");
+ if (err)
+ goto out_devfs_remove;
floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
- blk_queue_max_sectors(floppy_queue, 64);
if (!floppy_queue) {
err = -ENOMEM;
- goto fail_queue;
+ goto out_unreg_blkdev;
}
+ blk_queue_max_sectors(floppy_queue, 64);
blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
floppy_find, NULL, NULL);
}
use_virtual_dma = can_use_virtual_dma & 1;
+#if defined(CONFIG_PPC64)
+ if (check_legacy_ioport(FDC1)) {
+ del_timer(&fd_timeout);
+ err = -ENODEV;
+ goto out_unreg_region;
+ }
+#endif
fdc_state[0].address = FDC1;
if (fdc_state[0].address == -1) {
+ del_timer(&fd_timeout);
err = -ENODEV;
- goto out1;
+ goto out_unreg_region;
}
#if N_FDC > 1
fdc_state[1].address = FDC2;
#endif
fdc = 0; /* reset fdc in case of unexpected interrupt */
- if (floppy_grab_irq_and_dma()) {
+ err = floppy_grab_irq_and_dma();
+ if (err) {
+ del_timer(&fd_timeout);
err = -EBUSY;
- goto out1;
+ goto out_unreg_region;
}
/* initialise drive state */
floppy_track_buffer = NULL;
max_buffer_sectors = 0;
}
+ /*
+ * Small 10 msec delay to let through any interrupt that
+ * initialization might have triggered, to not
+ * confuse detection:
+ */
+ msleep(10);
for (i = 0; i < N_FDC; i++) {
fdc = i;
initialising = 0;
if (have_no_fdc) {
DPRINT("no floppy controllers found\n");
- flush_scheduled_work();
- if (usage_count)
- floppy_release_irq_and_dma();
err = have_no_fdc;
- goto out2;
+ goto out_flush_work;
}
for (drive = 0; drive < N_DRIVE; drive++) {
continue;
if (fdc_state[FDC(drive)].version == FDC_NONE)
continue;
+
+ floppy_device[drive].name = floppy_device_name;
+ floppy_device[drive].id = drive;
+ floppy_device[drive].dev.release = floppy_device_release;
+
+ err = platform_device_register(&floppy_device[drive]);
+ if (err)
+ goto out_flush_work;
+
+ device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
/* to be cleaned up... */
disks[drive]->private_data = (void *)(long)drive;
disks[drive]->queue = floppy_queue;
disks[drive]->flags |= GENHD_FL_REMOVABLE;
+ disks[drive]->driverfs_dev = &floppy_device[drive].dev;
add_disk(disks[drive]);
}
- platform_device_register(&floppy_device);
return 0;
-out1:
- del_timer(&fd_timeout);
-out2:
+out_flush_work:
+ flush_scheduled_work();
+ if (usage_count)
+ floppy_release_irq_and_dma();
+out_unreg_region:
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
blk_cleanup_queue(floppy_queue);
-fail_queue:
+out_unreg_blkdev:
unregister_blkdev(FLOPPY_MAJOR, "fd");
-out:
- for (i = 0; i < N_DRIVE; i++)
- put_disk(disks[i]);
+out_devfs_remove:
devfs_remove("floppy");
+out_put_disk:
+ while (dr--) {
+ del_timer(&motor_off_timer[dr]);
+ put_disk(disks[dr]);
+ }
return err;
-
-Enomem:
- while (i--)
- put_disk(disks[i]);
- return -ENOMEM;
}
-static spinlock_t floppy_usage_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(floppy_usage_lock);
static int floppy_grab_irq_and_dma(void)
{
#ifdef MODULE
-char *floppy;
+static char *floppy;
static void unregister_devfs_entries(int drive)
{
int i;
- if (UDP->cmos < NUMBER(default_drive_params)) {
+ if (UDP->cmos < ARRAY_SIZE(default_drive_params)) {
i = 0;
do {
devfs_remove("floppy/%d%s", drive,
int init_module(void)
{
- printk(KERN_INFO "inserting floppy driver for " UTS_RELEASE "\n");
-
if (floppy)
parse_floppy_cfg_string(floppy);
return floppy_init();
int drive;
init_completion(&device_release);
- platform_device_unregister(&floppy_device);
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
unregister_blkdev(FLOPPY_MAJOR, "fd");
fdc_state[FDC(drive)].version != FDC_NONE) {
del_gendisk(disks[drive]);
unregister_devfs_entries(drive);
+ device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+ platform_device_unregister(&floppy_device[drive]);
}
put_disk(disks[drive]);
}
wait_for_completion(&device_release);
}
-MODULE_PARM(floppy, "s");
-MODULE_PARM(FLOPPY_IRQ, "i");
-MODULE_PARM(FLOPPY_DMA, "i");
+module_param(floppy, charp, 0);
+module_param(FLOPPY_IRQ, int, 0);
+module_param(FLOPPY_DMA, int, 0);
MODULE_AUTHOR("Alain L. Knaff");
MODULE_SUPPORTED_DEVICE("fd");
MODULE_LICENSE("GPL");