patch-2.1.129 linux/drivers/block/swim3.c
Next file: linux/drivers/block/via82c586.c
Previous file: linux/drivers/block/sl82c105.c
Back to the patch index
Back to the overall index
- Lines: 403
- Date:
Sun Nov 15 10:51:46 1998
- Orig file:
v2.1.128/linux/drivers/block/swim3.c
- Orig date:
Sun Nov 8 14:02:51 1998
diff -u --recursive --new-file v2.1.128/linux/drivers/block/swim3.c linux/drivers/block/swim3.c
@@ -22,12 +22,15 @@
#include <asm/prom.h>
#include <asm/uaccess.h>
#include <asm/mediabay.h>
+#include <asm/feature.h>
#define MAJOR_NR FLOPPY_MAJOR
#include <linux/blk.h>
-static int floppy_blocksizes[2] = {512};
-static int floppy_sizes[2] = {2880};
+static int floppy_blocksizes[2] = {512,512};
+static int floppy_sizes[2] = {2880,2880};
+
+#define MAX_FLOPPIES 2
enum swim_state {
idle,
@@ -139,11 +142,12 @@
int ejected;
struct wait_queue *wait;
int wanted;
- int in_media_bay;
+ struct device_node* media_bay; /* NULL when not in bay */
char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)];
};
-static struct floppy_state floppy_states[1];
+static struct floppy_state floppy_states[MAX_FLOPPIES];
+static int floppy_count = 0;
static unsigned short write_preamble[] = {
0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, /* gap field */
@@ -175,7 +179,7 @@
static void seek_timeout(unsigned long data);
static void xfer_timeout(unsigned long data);
static void 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, struct pt_regs *regs);*/
static int grab_drive(struct floppy_state *fs, enum swim_state state,
int interruptible);
static void release_drive(struct floppy_state *fs);
@@ -190,6 +194,7 @@
size_t count, loff_t *ppos);
static int floppy_check_change(kdev_t dev);
static int floppy_revalidate(kdev_t dev);
+static int swim3_add_device(struct device_node *swims);
int swim3_init(void);
#define IOCTL_MODE_BIT 8
@@ -212,11 +217,11 @@
volatile struct swim3 *sw = fs->swim3;
swim3_select(fs, action);
- udelay(1);
+ udelay(10);
sw->select |= LSTRB; eieio();
- udelay(2);
+ udelay(20);
sw->select &= ~LSTRB; eieio();
- udelay(1);
+ udelay(10);
out_8(&sw->select, RELAX);
}
@@ -226,7 +231,7 @@
int stat;
swim3_select(fs, bit);
- udelay(1);
+ udelay(10);
stat = in_8(&sw->status);
out_8(&sw->select, RELAX);
return (stat & DATA) == 0;
@@ -234,13 +239,19 @@
static void do_fd_request(void)
{
- start_request(&floppy_states[0]);
+ int i;
+ for(i=0;i<floppy_count;i++)
+ {
+ if (floppy_states[i].media_bay &&
+ check_media_bay(floppy_states[i].media_bay, MB_FD))
+ continue;
+ start_request(&floppy_states[i]);
+ }
sti();
}
static void start_request(struct floppy_state *fs)
{
- int drive;
unsigned long x;
if (fs->state == idle && fs->wanted) {
@@ -261,11 +272,6 @@
CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors);
#endif
- drive = MINOR(CURRENT->rq_dev);
- if (drive != 0) {
- end_request(0);
- continue;
- }
if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
end_request(0);
continue;
@@ -438,7 +444,7 @@
case settling:
/* wait for SEEK_COMPLETE to become true */
swim3_select(fs, SEEK_COMPLETE);
- udelay(1);
+ udelay(10);
out_8(&sw->intr_enable, ERROR | DATA_CHANGED);
in_8(&sw->intr); /* clear DATA_CHANGED */
if (in_8(&sw->status) & DATA) {
@@ -560,7 +566,7 @@
err = in_8(&sw->error);
intr = in_8(&sw->intr);
#if 0
- printk(KERN_DEBUG "swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err);
+ printk("swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err);
#endif
if ((intr & ERROR) && fs->state != do_transfer)
printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n",
@@ -685,9 +691,11 @@
}
}
+/*
static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
}
+*/
static int grab_drive(struct floppy_state *fs, enum swim_state state,
int interruptible)
@@ -755,12 +763,20 @@
{
struct floppy_state *fs;
int err;
+ int devnum = MINOR(inode->i_rdev);
+ if (devnum >= floppy_count)
+ return -ENODEV;
+
if (((cmd & 0x40) && !(filp && (filp->f_mode & IOCTL_MODE_BIT))) ||
((cmd & 0x80) && !suser()))
return -EPERM;
- fs = &floppy_states[0];
+ fs = &floppy_states[devnum];
+
+ if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
+ return -ENXIO;
+
switch (cmd) {
case FDEJECT:
if (fs->ref_count != 1)
@@ -780,19 +796,21 @@
struct floppy_state *fs;
volatile struct swim3 *sw;
int n, err;
+ int devnum = MINOR(inode->i_rdev);
- if (MINOR(inode->i_rdev) != 0)
+ if (devnum >= floppy_count)
return -ENODEV;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
sw = fs->swim3;
err = 0;
if (fs->ref_count == 0) {
- if (fs->in_media_bay && !check_media_bay(MB_FD))
+ if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
return -ENXIO;
out_8(&sw->mode, 0x95);
out_8(&sw->control_bic, 0xff);
out_8(&sw->reg5, 0x28);
- udelay(1);
+ udelay(10);
out_8(&sw->intr_enable, 0);
out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);
swim3_action(fs, MOTOR_ON);
@@ -856,9 +874,11 @@
{
struct floppy_state *fs;
volatile struct swim3 *sw;
+ int devnum = MINOR(inode->i_rdev);
+
+ if (devnum >= floppy_count)
+ return -ENODEV;
- if (MINOR(inode->i_rdev) != 0)
- return -ENXIO;
/*
* If filp is NULL, we're being called from blkdev_release
* or after a failed mount attempt. In the former case the
@@ -868,7 +888,7 @@
if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT)))
block_fsync (filp, filp->f_dentry);
- fs = &floppy_states[0];
+ fs = &floppy_states[devnum];
sw = fs->swim3;
if (fs->ref_count > 0 && --fs->ref_count == 0) {
swim3_action(fs, MOTOR_OFF);
@@ -880,10 +900,12 @@
static int floppy_check_change(kdev_t dev)
{
struct floppy_state *fs;
+ int devnum = MINOR(dev);
- if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0)
+ if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
return 0;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
return fs->ejected;
}
@@ -892,10 +914,16 @@
struct floppy_state *fs;
volatile struct swim3 *sw;
int ret, n;
+ int devnum = MINOR(dev);
- if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0)
+ if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count))
return 0;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
+
+ if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
+ return -ENXIO;
+
sw = fs->swim3;
grab_drive(fs, revalidating, 0);
out_8(&sw->intr_enable, 0);
@@ -929,10 +957,12 @@
{
struct inode *inode = filp->f_dentry->d_inode;
struct floppy_state *fs;
+ int devnum = MINOR(inode->i_rdev);
- if (MINOR(inode->i_rdev) != 0)
+ if (devnum >= floppy_count)
return -ENODEV;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
if (fs->ejected)
return -ENXIO;
return block_read(filp, buf, count, ppos);
@@ -943,10 +973,12 @@
{
struct inode * inode = filp->f_dentry->d_inode;
struct floppy_state *fs;
+ int devnum = MINOR(inode->i_rdev);
- if (MINOR(inode->i_rdev) != 0)
+ if (devnum >= floppy_count)
return -ENODEV;
- fs = &floppy_states[0];
+
+ fs = &floppy_states[devnum];
if (fs->ejected)
return -ENXIO;
return block_write(filp, buf, count, ppos);
@@ -975,50 +1007,72 @@
int swim3_init(void)
{
- struct device_node *swims;
- struct floppy_state *fs = &floppy_states[0];
- int is_3400 = 0;
-
- if (find_devices("media-bay") != NULL) {
- /* assume this is a PB3400 */
- swims = find_devices("floppy");
- is_3400 = 1;
- } else {
- swims = find_devices("swim3");
+ struct device_node *swim;
+
+ 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 > 0)
+ {
+ if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
+ printk(KERN_ERR "Unable to get major %d for floppy\n",
+ MAJOR_NR);
+ return -EBUSY;
+ }
+ blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blksize_size[MAJOR_NR] = floppy_blocksizes;
+ blk_size[MAJOR_NR] = floppy_sizes;
}
- if (swims == NULL)
- return 0;
+ return 0;
+}
- if (swims->next != NULL)
- printk(KERN_ERR "Warning: only using first SWIM3 floppy controller\n");
- if (swims->n_addrs != 2 || swims->n_intrs != 2) {
- printk(KERN_ERR "swim3: expecting 2 addrs and 2 intrs! (%d, %d)\n",
- swims->n_addrs, swims->n_intrs);
+static int swim3_add_device(struct device_node *swim)
+{
+ struct device_node *mediabay;
+ struct floppy_state *fs = &floppy_states[floppy_count];
+
+ 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;
}
- if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
- printk(KERN_ERR "Unable to get major %d for floppy\n",
- MAJOR_NR);
- return -EBUSY;
+ 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;
}
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- blksize_size[MAJOR_NR] = floppy_blocksizes;
- blk_size[MAJOR_NR] = floppy_sizes;
+ mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ? swim->parent : NULL;
+ if (mediabay == NULL)
+ feature_set(swim, FEATURE_SWIM3_enable);
+
memset(fs, 0, sizeof(*fs));
fs->state = idle;
- fs->swim3 = (volatile struct swim3 *) swims->addrs[0].address;
- fs->dma = (struct dbdma_regs *) swims->addrs[1].address;
- fs->swim3_intr = swims->intrs[0].line;
- fs->dma_intr = swims->intrs[1].line;
+ 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->cur_cyl = -1;
fs->cur_sector = -1;
fs->secpercyl = 36;
fs->secpertrack = 18;
fs->total_secs = 2880;
- fs->in_media_bay = is_3400;
+ fs->media_bay = mediabay;
fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space);
memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd));
@@ -1026,19 +1080,26 @@
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);
+ feature_clear(swim, FEATURE_SWIM3_enable);
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);
+ feature_clear(swim, FEATURE_SWIM3_enable);
return -EBUSY;
}
+*/
init_timer(&fs->timeout);
do_floppy = NULL;
- printk(KERN_INFO "fd0: SWIM3 floppy controller\n");
+ printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count,
+ mediabay ? "in media bay" : "");
+ floppy_count++;
+
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov