diff options
Diffstat (limited to 'drivers/block/amiflop.c')
| -rw-r--r-- | drivers/block/amiflop.c | 476 |
1 files changed, 274 insertions, 202 deletions
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 49908c74bfcb..2932b6653b6f 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/amiga/amiflop.c * @@ -60,12 +61,10 @@ #include <linux/hdreg.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/major.h> #include <linux/mutex.h> -#include <linux/amifdreg.h> -#include <linux/amifd.h> #include <linux/fs.h> -#include <linux/blkdev.h> -#include <linux/elevator.h> +#include <linux/blk-mq.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -87,6 +86,126 @@ */ /* + * CIAAPRA bits (read only) + */ + +#define DSKRDY (0x1<<5) /* disk ready when low */ +#define DSKTRACK0 (0x1<<4) /* head at track zero when low */ +#define DSKPROT (0x1<<3) /* disk protected when low */ +#define DSKCHANGE (0x1<<2) /* low when disk removed */ + +/* + * CIAAPRB bits (read/write) + */ + +#define DSKMOTOR (0x1<<7) /* motor on when low */ +#define DSKSEL3 (0x1<<6) /* select drive 3 when low */ +#define DSKSEL2 (0x1<<5) /* select drive 2 when low */ +#define DSKSEL1 (0x1<<4) /* select drive 1 when low */ +#define DSKSEL0 (0x1<<3) /* select drive 0 when low */ +#define DSKSIDE (0x1<<2) /* side selection: 0 = upper, 1 = lower */ +#define DSKDIREC (0x1<<1) /* step direction: 0=in, 1=out (to trk 0) */ +#define DSKSTEP (0x1) /* pulse low to step head 1 track */ + +/* + * DSKBYTR bits (read only) + */ + +#define DSKBYT (1<<15) /* register contains valid byte when set */ +#define DMAON (1<<14) /* disk DMA enabled */ +#define DISKWRITE (1<<13) /* disk write bit in DSKLEN enabled */ +#define WORDEQUAL (1<<12) /* DSKSYNC register match when true */ +/* bits 7-0 are data */ + +/* + * ADKCON/ADKCONR bits + */ + +#ifndef SETCLR +#define ADK_SETCLR (1<<15) /* control bit */ +#endif +#define ADK_PRECOMP1 (1<<14) /* precompensation selection */ +#define ADK_PRECOMP0 (1<<13) /* 00=none, 01=140ns, 10=280ns, 11=500ns */ +#define ADK_MFMPREC (1<<12) /* 0=GCR precomp., 1=MFM precomp. */ +#define ADK_WORDSYNC (1<<10) /* enable DSKSYNC auto DMA */ +#define ADK_MSBSYNC (1<<9) /* when 1, enable sync on MSbit (for GCR) */ +#define ADK_FAST (1<<8) /* bit cell: 0=2us (GCR), 1=1us (MFM) */ + +/* + * DSKLEN bits + */ + +#define DSKLEN_DMAEN (1<<15) +#define DSKLEN_WRITE (1<<14) + +/* + * INTENA/INTREQ bits + */ + +#define DSKINDEX (0x1<<4) /* DSKINDEX bit */ + +/* + * Misc + */ + +#define MFM_SYNC 0x4489 /* standard MFM sync value */ + +/* Values for FD_COMMAND */ +#define FD_RECALIBRATE 0x07 /* move to track 0 */ +#define FD_SEEK 0x0F /* seek track */ +#define FD_READ 0xE6 /* read with MT, MFM, SKip deleted */ +#define FD_WRITE 0xC5 /* write with MT, MFM */ +#define FD_SENSEI 0x08 /* Sense Interrupt Status */ +#define FD_SPECIFY 0x03 /* specify HUT etc */ +#define FD_FORMAT 0x4D /* format one track */ +#define FD_VERSION 0x10 /* get version code */ +#define FD_CONFIGURE 0x13 /* configure FIFO operation */ +#define FD_PERPENDICULAR 0x12 /* perpendicular r/w mode */ + +#define FD_MAX_UNITS 4 /* Max. Number of drives */ +#define FLOPPY_MAX_SECTORS 22 /* Max. Number of sectors per track */ + +struct fd_data_type { + char *name; /* description of data type */ + int sects; /* sectors per track */ + int (*read_fkt)(int); /* read whole track */ + void (*write_fkt)(int); /* write whole track */ +}; + +struct fd_drive_type { + unsigned long code; /* code returned from drive */ + char *name; /* description of drive */ + unsigned int tracks; /* number of tracks */ + unsigned int heads; /* number of heads */ + unsigned int read_size; /* raw read size for one track */ + unsigned int write_size; /* raw write size for one track */ + unsigned int sect_mult; /* sectors and gap multiplier (HD = 2) */ + unsigned int precomp1; /* start track for precomp 1 */ + unsigned int precomp2; /* start track for precomp 2 */ + unsigned int step_delay; /* time (in ms) for delay after step */ + unsigned int settle_time; /* time to settle after dir change */ + unsigned int side_time; /* time needed to change sides */ +}; + +struct amiga_floppy_struct { + struct fd_drive_type *type; /* type of floppy for this unit */ + struct fd_data_type *dtype; /* type of floppy for this unit */ + int track; /* current track (-1 == unknown) */ + unsigned char *trackbuf; /* current track (kmaloc()'d */ + + int blocks; /* total # blocks on disk */ + + int changed; /* true when not known */ + int disk; /* disk in drive (-1 == unknown) */ + int motor; /* true when motor is at speed */ + int busy; /* true when drive is active */ + int dirty; /* true when trackbuf is not on disk */ + int status; /* current error code for unit */ + struct gendisk *gendisk[2]; + struct blk_mq_tag_set tag_set; +}; + +/* * Error codes */ #define FD_OK 0 /* operation succeeded */ @@ -113,6 +232,7 @@ static DEFINE_MUTEX(amiflop_mutex); static unsigned long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */ module_param(fd_def_df0, ulong, 0); +MODULE_DESCRIPTION("Amiga floppy driver"); MODULE_LICENSE("GPL"); /* @@ -146,6 +266,7 @@ static struct amiga_floppy_struct unit[FD_MAX_UNITS]; static struct timer_list flush_track_timer[FD_MAX_UNITS]; static struct timer_list post_write_timer; +static unsigned long post_write_timer_drive; static struct timer_list motor_on_timer; static struct timer_list motor_off_timer[FD_MAX_UNITS]; static int on_attempts; @@ -163,7 +284,6 @@ static volatile int selected = -1; /* currently selected drive */ static int writepending; static int writefromint; static char *raw_buf; -static int fdc_queue; static DEFINE_SPINLOCK(amiflop_lock); @@ -323,7 +443,7 @@ static void fd_deselect (int drive) } -static void motor_on_callback(unsigned long nr) +static void motor_on_callback(struct timer_list *unused) { if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) { complete_all(&motor_on_completion); @@ -337,14 +457,13 @@ static int fd_motor_on(int nr) { nr &= 3; - del_timer(motor_off_timer + nr); + timer_delete(motor_off_timer + nr); if (!unit[nr].motor) { unit[nr].motor = 1; fd_select(nr); reinit_completion(&motor_on_completion); - motor_on_timer.data = nr; mod_timer(&motor_on_timer, jiffies + HZ/2); on_attempts = 10; @@ -356,7 +475,7 @@ static int fd_motor_on(int nr) on_attempts = -1; #if 0 printk (KERN_ERR "motor_on failed, turning motor off\n"); - fd_motor_off (nr); + fd_motor_off (motor_off_timer + nr); return 0; #else printk (KERN_WARNING "DSKRDY not set after 1.5 seconds - assuming drive is spinning notwithstanding\n"); @@ -366,20 +485,17 @@ static int fd_motor_on(int nr) return 1; } -static void fd_motor_off(unsigned long drive) +static void fd_motor_off(struct timer_list *timer) { - long calledfromint; -#ifdef MODULE - long decusecount; + unsigned long drive = ((unsigned long)timer - + (unsigned long)&motor_off_timer[0]) / + sizeof(motor_off_timer[0]); - decusecount = drive & 0x40000000; -#endif - calledfromint = drive & 0x80000000; drive&=3; - if (calledfromint && !try_fdc(drive)) { + if (!try_fdc(drive)) { /* We would be blocked in an interrupt, so try again later */ - motor_off_timer[drive].expires = jiffies + 1; - add_timer(motor_off_timer + drive); + timer->expires = jiffies + 1; + add_timer(timer); return; } unit[drive].motor = 0; @@ -393,8 +509,6 @@ static void floppy_off (unsigned int nr) int drive; drive = nr & 3; - /* called this way it is always from interrupt */ - motor_off_timer[drive].data = nr | 0x80000000; mod_timer(motor_off_timer + drive, jiffies + 3*HZ); } @@ -436,7 +550,7 @@ static int fd_calibrate(int drive) break; if (--n == 0) { printk (KERN_ERR "fd%d: calibrate failed, turning motor off\n", drive); - fd_motor_off (drive); + fd_motor_off (motor_off_timer + drive); unit[drive].track = -1; rel_fdc(); return 0; @@ -565,7 +679,7 @@ static irqreturn_t fd_block_done(int irq, void *dummy) if (block_flag == 2) { /* writing */ writepending = 2; post_write_timer.expires = jiffies + 1; /* at least 2 ms */ - post_write_timer.data = selected; + post_write_timer_drive = selected; add_timer(&post_write_timer); } else { /* reading */ @@ -652,6 +766,10 @@ static void post_write (unsigned long drive) rel_fdc(); /* corresponds to get_fdc() in raw_write */ } +static void post_write_callback(struct timer_list *timer) +{ + post_write(post_write_timer_drive); +} /* * The following functions are to convert the block contents into raw data @@ -1245,8 +1363,12 @@ static void dos_write(int disk) /* FIXME: this assumes the drive is still spinning - * which is only true if we complete writing a track within three seconds */ -static void flush_track_callback(unsigned long nr) +static void flush_track_callback(struct timer_list *timer) { + unsigned long nr = ((unsigned long)timer - + (unsigned long)&flush_track_timer[0]) / + sizeof(flush_track_timer[0]); + nr&=3; writefromint = 1; if (!try_fdc(nr)) { @@ -1271,7 +1393,7 @@ static int non_int_flush_track (unsigned long nr) nr&=3; writefromint = 0; - del_timer(&post_write_timer); + timer_delete(&post_write_timer); get_fdc(nr); if (!fd_motor_on(nr)) { writepending = 0; @@ -1313,7 +1435,7 @@ static int get_track(int drive, int track) } if (unit[drive].dirty == 1) { - del_timer (flush_track_timer + drive); + timer_delete(flush_track_timer + drive); non_int_flush_track (drive); } errcnt = 0; @@ -1334,76 +1456,20 @@ static int get_track(int drive, int track) return -1; } -/* - * Round-robin between our available drives, doing one request from each - */ -static struct request *set_next_request(void) -{ - struct request_queue *q; - int cnt = FD_MAX_UNITS; - struct request *rq = NULL; - - /* Find next queue we can dispatch from */ - fdc_queue = fdc_queue + 1; - if (fdc_queue == FD_MAX_UNITS) - fdc_queue = 0; - - for(cnt = FD_MAX_UNITS; cnt > 0; cnt--) { - - if (unit[fdc_queue].type->code == FD_NODRIVE) { - if (++fdc_queue == FD_MAX_UNITS) - fdc_queue = 0; - continue; - } - - q = unit[fdc_queue].gendisk->queue; - if (q) { - rq = blk_fetch_request(q); - if (rq) - break; - } - - if (++fdc_queue == FD_MAX_UNITS) - fdc_queue = 0; - } - - return rq; -} - -static void redo_fd_request(void) +static blk_status_t amiflop_rw_cur_segment(struct amiga_floppy_struct *floppy, + struct request *rq) { - struct request *rq; + int drive = floppy - unit; unsigned int cnt, block, track, sector; - int drive; - struct amiga_floppy_struct *floppy; char *data; - unsigned long flags; - blk_status_t err; -next_req: - rq = set_next_request(); - if (!rq) { - /* Nothing left to do */ - return; - } - - floppy = rq->rq_disk->private_data; - drive = floppy - unit; - -next_segment: - /* Here someone could investigate to be more efficient */ - for (cnt = 0, err = BLK_STS_OK; cnt < blk_rq_cur_sectors(rq); cnt++) { + for (cnt = 0; cnt < blk_rq_cur_sectors(rq); cnt++) { #ifdef DEBUG printk("fd: sector %ld + %d requested for %s\n", blk_rq_pos(rq), cnt, (rq_data_dir(rq) == READ) ? "read" : "write"); #endif block = blk_rq_pos(rq) + cnt; - if ((int)block > floppy->blocks) { - err = BLK_STS_IOERR; - break; - } - track = block / (floppy->dtype->sects * floppy->type->sect_mult); sector = block % (floppy->dtype->sects * floppy->type->sect_mult); data = bio_data(rq->bio) + 512 * cnt; @@ -1412,10 +1478,8 @@ next_segment: "0x%08lx\n", track, sector, data); #endif - if (get_track(drive, track) == -1) { - err = BLK_STS_IOERR; - break; - } + if (get_track(drive, track) == -1) + return BLK_STS_IOERR; if (rq_data_dir(rq) == READ) { memcpy(data, floppy->trackbuf + sector * 512, 512); @@ -1423,44 +1487,53 @@ next_segment: memcpy(floppy->trackbuf + sector * 512, data, 512); /* keep the drive spinning while writes are scheduled */ - if (!fd_motor_on(drive)) { - err = BLK_STS_IOERR; - break; - } + if (!fd_motor_on(drive)) + return BLK_STS_IOERR; /* * setup a callback to write the track buffer * after a short (1 tick) delay. */ - local_irq_save(flags); - floppy->dirty = 1; /* reset the timer */ mod_timer (flush_track_timer + drive, jiffies + 1); - local_irq_restore(flags); } } - if (__blk_end_request_cur(rq, err)) - goto next_segment; - goto next_req; + return BLK_STS_OK; } -static void do_fd_request(struct request_queue * q) +static blk_status_t amiflop_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - redo_fd_request(); + struct request *rq = bd->rq; + struct amiga_floppy_struct *floppy = rq->q->disk->private_data; + blk_status_t err; + + if (!spin_trylock_irq(&amiflop_lock)) + return BLK_STS_DEV_RESOURCE; + + blk_mq_start_request(rq); + + do { + err = amiflop_rw_cur_segment(floppy, rq); + } while (blk_update_request(rq, err, blk_rq_cur_bytes(rq))); + blk_mq_end_request(rq, err); + + spin_unlock_irq(&amiflop_lock); + return BLK_STS_OK; } -static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static int fd_getgeo(struct gendisk *disk, struct hd_geometry *geo) { - int drive = MINOR(bdev->bd_dev) & 3; + struct amiga_floppy_struct *p = disk->private_data; - geo->heads = unit[drive].type->heads; - geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult; - geo->cylinders = unit[drive].type->tracks; + geo->heads = p->type->heads; + geo->sectors = p->dtype->sects * p->type->sect_mult; + geo->cylinders = p->type->tracks; return 0; } -static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param) { struct amiga_floppy_struct *p = bdev->bd_disk->private_data; @@ -1475,7 +1548,6 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, rel_fdc(); return -EBUSY; } - fsync_bdev(bdev); if (fd_motor_on(drive) == 0) { rel_fdc(); return -ENODEV; @@ -1519,7 +1591,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, case FDDEFPRM: return -EINVAL; case FDFLUSH: /* unconditionally, even if not needed */ - del_timer (flush_track_timer + drive); + timer_delete(flush_track_timer + drive); non_int_flush_track(drive); break; #ifdef RAW_IOCTL @@ -1530,14 +1602,12 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, return p->type->read_size; #endif default: - printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.", - cmd, drive); return -ENOSYS; } return 0; } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param) { int ret; @@ -1584,10 +1654,10 @@ static void fd_probe(int dev) * /dev/PS0 etc), and disallows simultaneous access to the same * drive with different device numbers. */ -static int floppy_open(struct block_device *bdev, fmode_t mode) +static int floppy_open(struct gendisk *disk, blk_mode_t mode) { - int drive = MINOR(bdev->bd_dev) & 3; - int system = (MINOR(bdev->bd_dev) & 4) >> 2; + int drive = disk->first_minor & 3; + int system = (disk->first_minor & 4) >> 2; int old_dev; unsigned long flags; @@ -1599,9 +1669,13 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return -EBUSY; } - if (mode & (FMODE_READ|FMODE_WRITE)) { - check_disk_change(bdev); - if (mode & FMODE_WRITE) { + if (unit[drive].type->code == FD_NODRIVE) { + mutex_unlock(&amiflop_mutex); + return -ENXIO; + } + if (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE)) { + disk_check_media_change(disk); + if (mode & BLK_OPEN_WRITE) { int wrprot; get_fdc(drive); @@ -1616,7 +1690,6 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) } } } - local_irq_save(flags); fd_ref[drive]++; fd_device[drive] = system; @@ -1625,7 +1698,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) unit[drive].dtype=&data_types[system]; unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks* data_types[system].sects*unit[drive].type->sect_mult; - set_capacity(unit[drive].gendisk, unit[drive].blocks); + set_capacity(unit[drive].gendisk[system], unit[drive].blocks); printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive, unit[drive].type->name, data_types[system].name); @@ -1634,14 +1707,14 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return 0; } -static void floppy_release(struct gendisk *disk, fmode_t mode) +static void floppy_release(struct gendisk *disk) { struct amiga_floppy_struct *p = disk->private_data; int drive = p - unit; mutex_lock(&amiflop_mutex); if (unit[drive].dirty == 1) { - del_timer (flush_track_timer + drive); + timer_delete(flush_track_timer + drive); non_int_flush_track (drive); } @@ -1650,8 +1723,7 @@ static void floppy_release(struct gendisk *disk, fmode_t mode) fd_ref[drive] = 0; } #ifdef MODULE -/* the mod_use counter is handled this way */ - floppy_off (drive | 0x40000000); + floppy_off (drive); #endif mutex_unlock(&amiflop_mutex); } @@ -1699,66 +1771,101 @@ static const struct block_device_operations floppy_fops = { .check_events = amiga_check_events, }; +static const struct blk_mq_ops amiflop_mq_ops = { + .queue_rq = amiflop_queue_rq, +}; + +static int fd_alloc_disk(int drive, int system) +{ + struct queue_limits lim = { + .features = BLK_FEAT_ROTATIONAL, + }; + struct gendisk *disk; + int err; + + disk = blk_mq_alloc_disk(&unit[drive].tag_set, &lim, NULL); + if (IS_ERR(disk)) + return PTR_ERR(disk); + + disk->major = FLOPPY_MAJOR; + disk->first_minor = drive + system; + disk->minors = 1; + disk->fops = &floppy_fops; + disk->flags |= GENHD_FL_NO_PART; + disk->events = DISK_EVENT_MEDIA_CHANGE; + if (system) + sprintf(disk->disk_name, "fd%d_msdos", drive); + else + sprintf(disk->disk_name, "fd%d", drive); + disk->private_data = &unit[drive]; + set_capacity(disk, 880 * 2); + + unit[drive].gendisk[system] = disk; + err = add_disk(disk); + if (err) + put_disk(disk); + return err; +} + +static int fd_alloc_drive(int drive) +{ + unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL); + if (!unit[drive].trackbuf) + goto out; + + memset(&unit[drive].tag_set, 0, sizeof(unit[drive].tag_set)); + unit[drive].tag_set.ops = &amiflop_mq_ops; + unit[drive].tag_set.nr_hw_queues = 1; + unit[drive].tag_set.nr_maps = 1; + unit[drive].tag_set.queue_depth = 2; + unit[drive].tag_set.numa_node = NUMA_NO_NODE; + if (blk_mq_alloc_tag_set(&unit[drive].tag_set)) + goto out_cleanup_trackbuf; + + pr_cont(" fd%d", drive); + + if (fd_alloc_disk(drive, 0) || fd_alloc_disk(drive, 1)) + goto out_cleanup_tagset; + return 0; + +out_cleanup_tagset: + blk_mq_free_tag_set(&unit[drive].tag_set); +out_cleanup_trackbuf: + kfree(unit[drive].trackbuf); +out: + unit[drive].type->code = FD_NODRIVE; + return -ENOMEM; +} + static int __init fd_probe_drives(void) { int drive,drives,nomem; - printk(KERN_INFO "FD: probing units\nfound "); + pr_info("FD: probing units\nfound"); drives=0; nomem=0; for(drive=0;drive<FD_MAX_UNITS;drive++) { - struct gendisk *disk; fd_probe(drive); if (unit[drive].type->code == FD_NODRIVE) continue; - disk = alloc_disk(1); - if (!disk) { - unit[drive].type->code = FD_NODRIVE; - continue; - } - unit[drive].gendisk = disk; - disk->queue = blk_init_queue(do_fd_request, &amiflop_lock); - if (!disk->queue) { - unit[drive].type->code = FD_NODRIVE; + if (fd_alloc_drive(drive) < 0) { + pr_cont(" no mem for fd%d", drive); + nomem = 1; continue; } - drives++; - if ((unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL)) == NULL) { - printk("no mem for "); - unit[drive].type = &drive_types[num_dr_types - 1]; /* FD_NODRIVE */ - drives--; - nomem = 1; - } - printk("fd%d ",drive); - disk->major = FLOPPY_MAJOR; - disk->first_minor = drive; - disk->fops = &floppy_fops; - sprintf(disk->disk_name, "fd%d", drive); - disk->private_data = &unit[drive]; - set_capacity(disk, 880*2); - add_disk(disk); } if ((drives > 0) || (nomem == 0)) { if (drives == 0) - printk("no drives"); - printk("\n"); + pr_cont(" no drives"); + pr_cont("\n"); return drives; } - printk("\n"); + pr_cont("\n"); return -ENOMEM; } -static struct kobject *floppy_find(dev_t dev, int *part, void *data) -{ - int drive = *part & 3; - if (unit[drive].type->code == FD_NODRIVE) - return NULL; - *part = 0; - return get_disk(unit[drive].gendisk); -} - static int __init amiga_floppy_probe(struct platform_device *pdev) { int i, ret; @@ -1788,31 +1895,20 @@ static int __init amiga_floppy_probe(struct platform_device *pdev) if (fd_probe_drives() < 1) /* No usable drives */ goto out_probe; - blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, - floppy_find, NULL, NULL); - /* initialize variables */ - init_timer(&motor_on_timer); + timer_setup(&motor_on_timer, motor_on_callback, 0); motor_on_timer.expires = 0; - motor_on_timer.data = 0; - motor_on_timer.function = motor_on_callback; for (i = 0; i < FD_MAX_UNITS; i++) { - init_timer(&motor_off_timer[i]); + timer_setup(&motor_off_timer[i], fd_motor_off, 0); motor_off_timer[i].expires = 0; - motor_off_timer[i].data = i|0x80000000; - motor_off_timer[i].function = fd_motor_off; - init_timer(&flush_track_timer[i]); + timer_setup(&flush_track_timer[i], flush_track_callback, 0); flush_track_timer[i].expires = 0; - flush_track_timer[i].data = i; - flush_track_timer[i].function = flush_track_callback; unit[i].track = -1; } - init_timer(&post_write_timer); + timer_setup(&post_write_timer, post_write_callback, 0); post_write_timer.expires = 0; - post_write_timer.data = 0; - post_write_timer.function = post_write; for (i = 0; i < 128; i++) mfmdecode[i]=255; @@ -1837,30 +1933,6 @@ out_blkdev: return ret; } -#if 0 /* not safe to unload */ -static int __exit amiga_floppy_remove(struct platform_device *pdev) -{ - int i; - - for( i = 0; i < FD_MAX_UNITS; i++) { - if (unit[i].type->code != FD_NODRIVE) { - struct request_queue *q = unit[i].gendisk->queue; - del_gendisk(unit[i].gendisk); - put_disk(unit[i].gendisk); - kfree(unit[i].trackbuf); - if (q) - blk_cleanup_queue(q); - } - } - blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); - free_irq(IRQ_AMIGA_CIAA_TB, NULL); - free_irq(IRQ_AMIGA_DSKBLK, NULL); - custom.dmacon = DMAF_DISK; /* disable DMA */ - amiga_chip_free(raw_buf); - unregister_blkdev(FLOPPY_MAJOR, "fd"); -} -#endif - static struct platform_driver amiga_floppy_driver = { .driver = { .name = "amiga-floppy", |
