#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>
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 */
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 */
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)
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);
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);
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)
{
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;
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 */
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);
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");
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));
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);
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);
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)) {
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);
static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
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);
{
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);
--fs->wanted;
}
fs->state = state;
- restore_flags(flags);
+ spin_unlock_irqrestore(&fs->lock, flags);
return 0;
}
{
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)
break;
}
swim3_select(fs, RELAX);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
if (swim3_readbit(fs, DISK_IN) == 0)
break;
}
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:
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;
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);
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))
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);
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);
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;
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);
sprintf(disk->devfs_name, "floppy/%d", i);
set_capacity(disk, 2880);
{
struct device_node *mediabay;
struct floppy_state *fs = &floppy_states[floppy_count];
+ struct resource res_reg, res_dma;
- 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);
+ if (of_address_to_resource(swim, 0, &res_reg) ||
+ of_address_to_resource(swim, 1, &res_dma)) {
+ printk(KERN_ERR "swim3: Can't get addresses\n");
return -EINVAL;
}
-
- 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);
+ if (request_mem_region(res_reg.start, res_reg.end - res_reg.start + 1,
+ " (reg)") == NULL) {
+ printk(KERN_ERR "swim3: Can't request register space\n");
+ return -EINVAL;
+ }
+ if (request_mem_region(res_dma.start, res_dma.end - res_dma.start + 1,
+ " (dma)") == NULL) {
+ release_mem_region(res_reg.start,
+ res_reg.end - res_reg.start + 1);
+ printk(KERN_ERR "swim3: Can't request DMA space\n");
return -EINVAL;
}
- if (!request_OF_resource(swim, 0, NULL)) {
- printk(KERN_INFO "swim3: can't request IO resource !\n");
+ if (swim->n_intrs < 2) {
+ printk(KERN_INFO "swim3: expecting 2 intrs (n_intrs:%d)\n",
+ swim->n_intrs);
+ release_mem_region(res_reg.start,
+ res_reg.end - res_reg.start + 1);
+ release_mem_region(res_dma.start,
+ res_dma.end - res_dma.start + 1);
return -EINVAL;
}
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 = (struct swim3 __iomem *)ioremap(res_reg.start, 0x200);
+ fs->dma = (struct dbdma_regs __iomem *)ioremap(res_dma.start, 0x200);
fs->swim3_intr = swim->intrs[0].line;
fs->dma_intr = swim->intrs[1].line;
fs->cur_cyl = -1;
}
module_init(swim3_init)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul Mackerras");
+MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR);