fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / block / swim3.c
index 8337eeb..1a65979 100644 (file)
@@ -16,7 +16,6 @@
  * handle GCR disks
  */
 
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -25,9 +24,9 @@
 #include <linux/fd.h>
 #include <linux/ioctl.h>
 #include <linux/blkdev.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/spinlock.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
 #include <asm/prom.h>
@@ -176,8 +175,9 @@ struct swim3 {
 
 struct floppy_state {
        enum swim_state state;
-       volatile struct swim3 *swim3;   /* hardware registers */
-       struct dbdma_regs *dma; /* DMA controller registers */
+       spinlock_t lock;
+       struct swim3 __iomem *swim3;    /* hardware registers */
+       struct dbdma_regs __iomem *dma; /* DMA controller registers */
        int     swim3_intr;     /* interrupt number for SWIM3 */
        int     dma_intr;       /* interrupt number for DMA channel */
        int     cur_cyl;        /* cylinder head is on, or -1 */
@@ -206,7 +206,7 @@ struct floppy_state {
 
 static struct floppy_state floppy_states[MAX_FLOPPIES];
 static int floppy_count = 0;
-static spinlock_t swim3_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(swim3_lock);
 
 static unsigned short write_preamble[] = {
        0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, /* gap field */
@@ -238,8 +238,8 @@ static void scan_timeout(unsigned long data);
 static void seek_timeout(unsigned long data);
 static void settle_timeout(unsigned long data);
 static void xfer_timeout(unsigned long data);
-static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-/*static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs);*/
+static irqreturn_t swim3_interrupt(int irq, void *dev_id);
+/*static void fd_dma_interrupt(int irq, void *dev_id);*/
 static int grab_drive(struct floppy_state *fs, enum swim_state state,
                      int interruptible);
 static void release_drive(struct floppy_state *fs);
@@ -250,16 +250,14 @@ static int floppy_open(struct inode *inode, struct file *filp);
 static int floppy_release(struct inode *inode, struct file *filp);
 static int floppy_check_change(struct gendisk *disk);
 static int floppy_revalidate(struct gendisk *disk);
-static int swim3_add_device(struct device_node *swims);
-int swim3_init(void);
 
-#ifndef CONFIG_PMAC_PBOOK
+#ifndef CONFIG_PMAC_MEDIABAY
 #define check_media_bay(which, what)   1
 #endif
 
 static void swim3_select(struct floppy_state *fs, int sel)
 {
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
 
        out_8(&sw->select, RELAX);
        if (sel & 8)
@@ -271,7 +269,7 @@ static void swim3_select(struct floppy_state *fs, int sel)
 
 static void swim3_action(struct floppy_state *fs, int action)
 {
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
 
        swim3_select(fs, action);
        udelay(1);
@@ -283,7 +281,7 @@ static void swim3_action(struct floppy_state *fs, int action)
 
 static int swim3_readbit(struct floppy_state *fs, int bit)
 {
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
        int stat;
 
        swim3_select(fs, bit);
@@ -297,12 +295,13 @@ static void do_fd_request(request_queue_t * q)
        int i;
        for(i=0;i<floppy_count;i++)
        {
+#ifdef CONFIG_PMAC_MEDIABAY
                if (floppy_states[i].media_bay &&
                        check_media_bay(floppy_states[i].media_bay, MB_FD))
                        continue;
+#endif /* CONFIG_PMAC_MEDIABAY */
                start_request(&floppy_states[i]);
        }
-       sti();
 }
 
 static void start_request(struct floppy_state *fs)
@@ -320,8 +319,8 @@ static void start_request(struct floppy_state *fs)
                printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
                       req->rq_disk->disk_name, req->cmd,
                       (long)req->sector, req->nr_sectors, req->buffer);
-               printk("           rq_status=%d errors=%d current_nr_sectors=%ld\n",
-                      req->rq_status, req->errors, req->current_nr_sectors);
+               printk("           errors=%d current_nr_sectors=%ld\n",
+                      req->errors, req->current_nr_sectors);
 #endif
 
                if (req->sector < 0 || req->sector >= fs->total_secs) {
@@ -368,7 +367,7 @@ static void set_timeout(struct floppy_state *fs, int nticks,
 {
        unsigned long flags;
 
-       save_flags(flags); cli();
+       spin_lock_irqsave(&fs->lock, flags);
        if (fs->timeout_pending)
                del_timer(&fs->timeout);
        fs->timeout.expires = jiffies + nticks;
@@ -376,12 +375,12 @@ static void set_timeout(struct floppy_state *fs, int nticks,
        fs->timeout.data = (unsigned long) fs;
        add_timer(&fs->timeout);
        fs->timeout_pending = 1;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&fs->lock, flags);
 }
 
 static inline void scan_track(struct floppy_state *fs)
 {
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
 
        swim3_select(fs, READ_DATA_0);
        in_8(&sw->intr);                /* clear SEEN_SECTOR bit */
@@ -394,7 +393,7 @@ static inline void scan_track(struct floppy_state *fs)
 
 static inline void seek_track(struct floppy_state *fs, int n)
 {
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
 
        if (n >= 0) {
                swim3_action(fs, SEEK_POSITIVE);
@@ -425,9 +424,9 @@ static inline void init_dma(struct dbdma_cmd *cp, int cmd,
 static inline void setup_transfer(struct floppy_state *fs)
 {
        int n;
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
        struct dbdma_cmd *cp = fs->dma_cmd;
-       struct dbdma_regs *dr = fs->dma;
+       struct dbdma_regs __iomem *dr = fs->dma;
 
        if (fd_req->current_nr_sectors <= 0) {
                printk(KERN_ERR "swim3: transfer 0 sectors?\n");
@@ -445,7 +444,7 @@ static inline void setup_transfer(struct floppy_state *fs)
        out_8(&sw->sector, fs->req_sector);
        out_8(&sw->nsect, n);
        out_8(&sw->gap3, 0);
-       st_le32(&dr->cmdptr, virt_to_bus(cp));
+       out_le32(&dr->cmdptr, virt_to_bus(cp));
        if (rq_data_dir(fd_req) == WRITE) {
                /* Set up 3 dma commands: write preamble, data, postamble */
                init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble));
@@ -537,7 +536,7 @@ static void act(struct floppy_state *fs)
 static void scan_timeout(unsigned long data)
 {
        struct floppy_state *fs = (struct floppy_state *) data;
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
 
        fs->timeout_pending = 0;
        out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
@@ -557,7 +556,7 @@ static void scan_timeout(unsigned long data)
 static void seek_timeout(unsigned long data)
 {
        struct floppy_state *fs = (struct floppy_state *) data;
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
 
        fs->timeout_pending = 0;
        out_8(&sw->control_bic, DO_SEEK);
@@ -572,7 +571,7 @@ static void seek_timeout(unsigned long data)
 static void settle_timeout(unsigned long data)
 {
        struct floppy_state *fs = (struct floppy_state *) data;
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
 
        fs->timeout_pending = 0;
        if (swim3_readbit(fs, SEEK_COMPLETE)) {
@@ -596,14 +595,14 @@ static void settle_timeout(unsigned long data)
 static void xfer_timeout(unsigned long data)
 {
        struct floppy_state *fs = (struct floppy_state *) data;
-       volatile struct swim3 *sw = fs->swim3;
-       struct dbdma_regs *dr = fs->dma;
+       struct swim3 __iomem *sw = fs->swim3;
+       struct dbdma_regs __iomem *dr = fs->dma;
        struct dbdma_cmd *cp = fs->dma_cmd;
        unsigned long s;
        int n;
 
        fs->timeout_pending = 0;
-       st_le32(&dr->control, RUN << 16);
+       out_le32(&dr->control, RUN << 16);
        /* We must wait a bit for dbdma to stop */
        for (n = 0; (in_le32(&dr->status) & ACTIVE) && n < 1000; n++)
                udelay(1);
@@ -625,19 +624,19 @@ static void xfer_timeout(unsigned long data)
        start_request(fs);
 }
 
-static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t swim3_interrupt(int irq, void *dev_id)
 {
        struct floppy_state *fs = (struct floppy_state *) dev_id;
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
        int intr, err, n;
        int stat, resid;
-       struct dbdma_regs *dr;
+       struct dbdma_regs __iomem *dr;
        struct dbdma_cmd *cp;
 
        intr = in_8(&sw->intr);
        err = (intr & ERROR_INTR)? in_8(&sw->error): 0;
        if ((intr & ERROR_INTR) && fs->state != do_transfer)
-               printk(KERN_ERR "swim3_interrupt, state=%d, dir=%lx, intr=%x, err=%x\n",
+               printk(KERN_ERR "swim3_interrupt, state=%d, dir=%x, intr=%x, err=%x\n",
                       fs->state, rq_data_dir(fd_req), intr, err);
        switch (fs->state) {
        case locating:
@@ -743,7 +742,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        if ((stat & ACTIVE) == 0 || resid != 0) {
                                /* musta been an error */
                                printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid);
-                               printk(KERN_ERR "  state=%d, dir=%lx, intr=%x, err=%x\n",
+                               printk(KERN_ERR "  state=%d, dir=%x, intr=%x, err=%x\n",
                                       fs->state, rq_data_dir(fd_req), intr, err);
                                end_request(fd_req, 0);
                                fs->state = idle;
@@ -778,7 +777,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 }
 
 /*
-static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void fd_dma_interrupt(int irq, void *dev_id)
 {
 }
 */
@@ -788,14 +787,13 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state,
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&fs->lock, flags);
        if (fs->state != idle) {
                ++fs->wanted;
                while (fs->state != available) {
                        if (interruptible && signal_pending(current)) {
                                --fs->wanted;
-                               restore_flags(flags);
+                               spin_unlock_irqrestore(&fs->lock, flags);
                                return -EINTR;
                        }
                        interruptible_sleep_on(&fs->wait);
@@ -803,7 +801,7 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state,
                --fs->wanted;
        }
        fs->state = state;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&fs->lock, flags);
        return 0;
 }
 
@@ -811,11 +809,10 @@ static void release_drive(struct floppy_state *fs)
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&fs->lock, flags);
        fs->state = idle;
        start_request(fs);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&fs->lock, flags);
 }
 
 static int fd_eject(struct floppy_state *fs)
@@ -832,8 +829,7 @@ static int fd_eject(struct floppy_state *fs)
                        break;
                }
                swim3_select(fs, RELAX);
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1);
+               schedule_timeout_interruptible(1);
                if (swim3_readbit(fs, DISK_IN) == 0)
                        break;
        }
@@ -856,8 +852,10 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
        if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+#ifdef CONFIG_PMAC_MEDIABAY
        if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
                return -ENXIO;
+#endif
 
        switch (cmd) {
        case FDEJECT:
@@ -866,7 +864,7 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
                err = fd_eject(fs);
                return err;
        case FDGETPRM:
-               if (copy_to_user((void *) param, (void *)&floppy_type,
+               if (copy_to_user((void __user *) param, &floppy_type,
                                 sizeof(struct floppy_struct)))
                        return -EFAULT;
                return 0;
@@ -877,12 +875,14 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
 static int floppy_open(struct inode *inode, struct file *filp)
 {
        struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
        int n, err = 0;
 
        if (fs->ref_count == 0) {
+#ifdef CONFIG_PMAC_MEDIABAY
                if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
                        return -ENXIO;
+#endif
                out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2);
                out_8(&sw->control_bic, 0xff);
                out_8(&sw->mode, 0x95);
@@ -900,8 +900,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
                                break;
                        }
                        swim3_select(fs, RELAX);
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(1);
+                       schedule_timeout_interruptible(1);
                }
                if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0
                                 || swim3_readbit(fs, DISK_IN) == 0))
@@ -946,7 +945,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
 static int floppy_release(struct inode *inode, struct file *filp)
 {
        struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
-       volatile struct swim3 *sw = fs->swim3;
+       struct swim3 __iomem *sw = fs->swim3;
        if (fs->ref_count > 0 && --fs->ref_count == 0) {
                swim3_action(fs, MOTOR_OFF);
                out_8(&sw->control_bic, 0xff);
@@ -964,11 +963,13 @@ static int floppy_check_change(struct gendisk *disk)
 static int floppy_revalidate(struct gendisk *disk)
 {
        struct floppy_state *fs = disk->private_data;
-       volatile struct swim3 *sw;
+       struct swim3 __iomem *sw;
        int ret, n;
 
+#ifdef CONFIG_PMAC_MEDIABAY
        if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
                return -ENXIO;
+#endif
 
        sw = fs->swim3;
        grab_drive(fs, revalidating, 0);
@@ -984,8 +985,7 @@ static int floppy_revalidate(struct gendisk *disk)
                if (signal_pending(current))
                        break;
                swim3_select(fs, RELAX);
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1);
+               schedule_timeout_interruptible(1);
        }
        ret = swim3_readbit(fs, SEEK_COMPLETE) == 0
                || swim3_readbit(fs, DISK_IN) == 0;
@@ -1009,105 +1009,63 @@ static struct block_device_operations floppy_fops = {
        .revalidate_disk= floppy_revalidate,
 };
 
-int swim3_init(void)
-{
-       struct device_node *swim;
-       int err = -ENOMEM;
-       int i;
-
-       devfs_mk_dir("floppy");
-
-       swim = find_devices("floppy");
-       while (swim && (floppy_count < MAX_FLOPPIES))
-       {
-               swim3_add_device(swim);
-               swim = swim->next;
-       }
-
-       swim = find_devices("swim3");
-       while (swim && (floppy_count < MAX_FLOPPIES))
-       {
-               swim3_add_device(swim);
-               swim = swim->next;
-       }
-
-       if (!floppy_count)
-               return -ENODEV;
-
-       for (i = 0; i < floppy_count; i++) {
-               disks[i] = alloc_disk(1);
-               if (!disks[i])
-                       goto out;
-       }
-
-       if (register_blkdev(FLOPPY_MAJOR, "fd")) {
-               err = -EBUSY;
-               goto out;
-       }
-
-       swim3_queue = blk_init_queue(do_fd_request, &swim3_lock);
-       if (!swim3_queue) {
-               err = -ENOMEM;
-               goto out_queue;
-       }
-
-       for (i = 0; i < floppy_count; i++) {
-               struct gendisk *disk = disks[i];
-               disk->major = FLOPPY_MAJOR;
-               disk->first_minor = i;
-               disk->fops = &floppy_fops;
-               disk->private_data = &floppy_states[i];
-               disk->queue = swim3_queue;
-               sprintf(disk->disk_name, "fd%d", i);
-               sprintf(disk->devfs_name, "floppy/%d", i);
-               set_capacity(disk, 2880);
-               add_disk(disk);
-       }
-       return 0;
-
-out_queue:
-       unregister_blkdev(FLOPPY_MAJOR, "fd");
-out:
-       while (i--)
-               put_disk(disks[i]);
-       /* shouldn't we do something with results of swim_add_device()? */
-       return err;
-}
-
-static int swim3_add_device(struct device_node *swim)
+static int swim3_add_device(struct macio_dev *mdev, int index)
 {
+       struct device_node *swim = mdev->ofdev.node;
        struct device_node *mediabay;
-       struct floppy_state *fs = &floppy_states[floppy_count];
+       struct floppy_state *fs = &floppy_states[index];
+       int rc = -EBUSY;
 
-       if (swim->n_addrs < 2)
-       {
-               printk(KERN_INFO "swim3: expecting 2 addrs (n_addrs:%d, n_intrs:%d)\n",
-                      swim->n_addrs, swim->n_intrs);
-               return -EINVAL;
+       /* Check & Request resources */
+       if (macio_resource_count(mdev) < 2) {
+               printk(KERN_WARNING "ifd%d: no address for %s\n",
+                      index, swim->full_name);
+               return -ENXIO;
        }
-
-       if (swim->n_intrs < 2)
-       {
-               printk(KERN_INFO "swim3: expecting 2 intrs (n_addrs:%d, n_intrs:%d)\n",
-                      swim->n_addrs, swim->n_intrs);
-               return -EINVAL;
+       if (macio_irq_count(mdev) < 2) {
+               printk(KERN_WARNING "fd%d: no intrs for device %s\n",
+                       index, swim->full_name);
        }
-
-       if (!request_OF_resource(swim, 0, NULL)) {
-               printk(KERN_INFO "swim3: can't request IO resource !\n");
-               return -EINVAL;
+       if (macio_request_resource(mdev, 0, "swim3 (mmio)")) {
+               printk(KERN_ERR "fd%d: can't request mmio resource for %s\n",
+                      index, swim->full_name);
+               return -EBUSY;
+       }
+       if (macio_request_resource(mdev, 1, "swim3 (dma)")) {
+               printk(KERN_ERR "fd%d: can't request dma resource for %s\n",
+                      index, swim->full_name);
+               macio_release_resource(mdev, 0);
+               return -EBUSY;
        }
+       dev_set_drvdata(&mdev->ofdev.dev, fs);
 
-       mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ? swim->parent : NULL;
+       mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ?
+               swim->parent : NULL;
        if (mediabay == NULL)
                pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1);
        
        memset(fs, 0, sizeof(*fs));
+       spin_lock_init(&fs->lock);
        fs->state = idle;
-       fs->swim3 = (volatile struct swim3 *) ioremap(swim->addrs[0].address, 0x200);
-       fs->dma = (struct dbdma_regs *) ioremap(swim->addrs[1].address, 0x200);
-       fs->swim3_intr = swim->intrs[0].line;
-       fs->dma_intr = swim->intrs[1].line;
+       fs->swim3 = (struct swim3 __iomem *)
+               ioremap(macio_resource_start(mdev, 0), 0x200);
+       if (fs->swim3 == NULL) {
+               printk("fd%d: couldn't map registers for %s\n",
+                      index, swim->full_name);
+               rc = -ENOMEM;
+               goto out_release;
+       }
+       fs->dma = (struct dbdma_regs __iomem *)
+               ioremap(macio_resource_start(mdev, 1), 0x200);
+       if (fs->dma == NULL) {
+               printk("fd%d: couldn't map DMA for %s\n",
+                      index, swim->full_name);
+               iounmap(fs->swim3);
+               rc = -ENOMEM;
+               goto out_release;
+       }
+       fs->swim3_intr = macio_irq(mdev, 0);
+       fs->dma_intr = macio_irq(mdev, 1);;
        fs->cur_cyl = -1;
        fs->cur_sector = -1;
        fs->secpercyl = 36;
@@ -1121,15 +1079,16 @@ static int swim3_add_device(struct device_node *swim)
        st_le16(&fs->dma_cmd[1].command, DBDMA_STOP);
 
        if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) {
-               printk(KERN_ERR "Couldn't get irq %d for SWIM3\n", fs->swim3_intr);
+               printk(KERN_ERR "fd%d: couldn't request irq %d for %s\n",
+                      index, fs->swim3_intr, swim->full_name);
                pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0);
+               goto out_unmap;
                return -EBUSY;
        }
 /*
        if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) {
                printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA",
                       fs->dma_intr);
-               pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0);
                return -EBUSY;
        }
 */
@@ -1139,9 +1098,95 @@ static int swim3_add_device(struct device_node *swim)
        printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count,
                mediabay ? "in media bay" : "");
 
-       floppy_count++;
-       
+       return 0;
+
+ out_unmap:
+       iounmap(fs->dma);
+       iounmap(fs->swim3);
+
+ out_release:
+       macio_release_resource(mdev, 0);
+       macio_release_resource(mdev, 1);
+
+       return rc;
+}
+
+static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device_id *match)
+{
+       int i, rc;
+       struct gendisk *disk;
+
+       /* Add the drive */
+       rc = swim3_add_device(mdev, floppy_count);
+       if (rc)
+               return rc;
+
+       /* Now create the queue if not there yet */
+       if (swim3_queue == NULL) {
+               /* If we failed, there isn't much we can do as the driver is still
+                * too dumb to remove the device, just bail out
+                */
+               if (register_blkdev(FLOPPY_MAJOR, "fd"))
+                       return 0;
+               swim3_queue = blk_init_queue(do_fd_request, &swim3_lock);
+               if (swim3_queue == NULL) {
+                       unregister_blkdev(FLOPPY_MAJOR, "fd");
+                       return 0;
+               }
+       }
+
+       /* Now register that disk. Same comment about failure handling */
+       i = floppy_count++;
+       disk = disks[i] = alloc_disk(1);
+       if (disk == NULL)
+               return 0;
+
+       disk->major = FLOPPY_MAJOR;
+       disk->first_minor = i;
+       disk->fops = &floppy_fops;
+       disk->private_data = &floppy_states[i];
+       disk->queue = swim3_queue;
+       disk->flags |= GENHD_FL_REMOVABLE;
+       sprintf(disk->disk_name, "fd%d", i);
+       set_capacity(disk, 2880);
+       add_disk(disk);
+
+       return 0;
+}
+
+static struct of_device_id swim3_match[] =
+{
+       {
+       .name           = "swim3",
+       },
+       {
+       .compatible     = "ohare-swim3"
+       },
+       {
+       .compatible     = "swim3"
+       },
+};
+
+static struct macio_driver swim3_driver =
+{
+       .name           = "swim3",
+       .match_table    = swim3_match,
+       .probe          = swim3_attach,
+#if 0
+       .suspend        = swim3_suspend,
+       .resume         = swim3_resume,
+#endif
+};
+
+
+int swim3_init(void)
+{
+       macio_register_driver(&swim3_driver);
        return 0;
 }
 
 module_init(swim3_init)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul Mackerras");
+MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR);