lkml.org 
[lkml]   [2003]   [Nov]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: PowerMac floppy (SWIM-3) doesn't compile
From
Date
On Sun, 2003-11-30 at 22:25, Mikael Pettersson wrote:
> On Sun, 30 Nov 2003 10:19:07 +0100 (MET), Sebastiaan <S.Breedveld@ewi.tudelft.nl> wrote:
> >I am trying to build the 2.6.0-test11 kernel for my PowerMac 7300/166, but
> >the floppy controller doesn't want to compile. I have:
>
> Known problem. Has been reported several times, but the PPC
> maintainers haven't bothered merging the fix yet.

The maintainer did bother, but along with a bunch of other PPC
driver updates, the fix is on hold until after 2.6.0. Code
freeze...

Also, the swim3 drivers, even with that fix, isn't in a very
good shape. It needs to be cleaned up and ported to the new
driver model.

> I'm using the patch below since the 2.5.7x kernels.
> (Paul Mackerras' 2.4 swim3 rework forward-ported to 2.5 by me.)
> There's also an "official" powermac tree somewhere which
> includes some swim3 patch, but I don't know if it's the same
> as this one.

Please test and let me know. It's at
bk://ppc.bkbits.net/linuxppc-2.5-benh or rsync from
source.mvista.com::linuxppc-2.5-benh.

> As for the boot problem you reported, please try a newer gcc
> like 3.2.3 or 3.3.2. I had lots of wierd problems with 2.95.3
> and the 2.4 kernels on ppc before I switched to gcc-3.x.x.
>
> 2.6.0-test11 works just fine on my PM4400.
>
> /Mikael
>
> diff -ruN linux-2.6.0-test11/drivers/block/swim3.c linux-2.6.0-test11.swim3-fixes/drivers/block/swim3.c
> --- linux-2.6.0-test11/drivers/block/swim3.c 2003-08-09 11:54:06.000000000 +0200
> +++ linux-2.6.0-test11.swim3-fixes/drivers/block/swim3.c 2003-11-26 23:50:36.000000000 +0100
> @@ -24,7 +24,10 @@
> #include <linux/delay.h>
> #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 <asm/io.h>
> #include <asm/dbdma.h>
> #include <asm/prom.h>
> @@ -144,7 +147,7 @@
> #define RELAX 3 /* also eject in progress */
> #define READ_DATA_0 4
> #define TWOMEG_DRIVE 5
> -#define SINGLE_SIDED 6
> +#define SINGLE_SIDED 6 /* drive or diskette is 4MB type? */
> #define DRIVE_PRESENT 7
> #define DISK_IN 8
> #define WRITE_PROT 9
> @@ -184,6 +187,7 @@
> int req_sector; /* sector number ditto */
> int scount; /* # sectors we're transferring at present */
> int retries;
> + int settle_time;
> int secpercyl; /* disk geometry information */
> int secpertrack;
> int total_secs;
> @@ -232,8 +236,9 @@
> static void act(struct floppy_state *fs);
> 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 void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
> +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 int grab_drive(struct floppy_state *fs, enum swim_state state,
> int interruptible);
> @@ -274,7 +279,6 @@
> udelay(2);
> out_8(&sw->select, sw->select & ~LSTRB);
> udelay(1);
> - out_8(&sw->select, RELAX);
> }
>
> static int swim3_readbit(struct floppy_state *fs, int bit)
> @@ -283,9 +287,8 @@
> int stat;
>
> swim3_select(fs, bit);
> - udelay(10);
> + udelay(1);
> stat = in_8(&sw->status);
> - out_8(&sw->select, RELAX);
> return (stat & DATA) == 0;
> }
>
> @@ -374,13 +377,13 @@
> static inline void scan_track(struct floppy_state *fs)
> {
> volatile struct swim3 *sw = fs->swim3;
> - int xx;
>
> swim3_select(fs, READ_DATA_0);
> - xx = sw->intr; /* clear SEEN_SECTOR bit */
> + in_8(&sw->intr); /* clear SEEN_SECTOR bit */
> + in_8(&sw->error);
> + out_8(&sw->intr_enable, SEEN_SECTOR);
> out_8(&sw->control_bis, DO_ACTION);
> /* enable intr when track found */
> - out_8(&sw->intr_enable, ERROR_INTR | SEEN_SECTOR);
> set_timeout(fs, HZ, scan_timeout); /* enable timeout */
> }
>
> @@ -395,12 +398,14 @@
> swim3_action(fs, SEEK_NEGATIVE);
> sw->nseek = -n;
> }
> - fs->expect_cyl = (fs->cur_cyl > 0)? fs->cur_cyl + n: -1;
> + fs->expect_cyl = (fs->cur_cyl >= 0)? fs->cur_cyl + n: -1;
> swim3_select(fs, STEP);
> - out_8(&sw->control_bis, DO_SEEK);
> + in_8(&sw->error);
> /* enable intr when seek finished */
> - out_8(&sw->intr_enable, ERROR_INTR | SEEK_DONE);
> - set_timeout(fs, HZ/2, seek_timeout); /* enable timeout */
> + out_8(&sw->intr_enable, SEEK_DONE);
> + out_8(&sw->control_bis, DO_SEEK);
> + set_timeout(fs, 3*HZ, seek_timeout); /* enable timeout */
> + fs->settle_time = 0;
> }
>
> static inline void init_dma(struct dbdma_cmd *cp, int cmd,
> @@ -448,18 +453,21 @@
> }
> ++cp;
> out_le16(&cp->command, DBDMA_STOP);
> + out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
> + in_8(&sw->error);
> + out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
> + if (rq_data_dir(fd_req) == WRITE)
> + out_8(&sw->control_bis, WRITE_SECTORS);
> + in_8(&sw->intr);
> out_le32(&dr->control, (RUN << 16) | RUN);
> - out_8(&sw->control_bis,
> - (rq_data_dir(fd_req) == WRITE? WRITE_SECTORS: 0) | DO_ACTION);
> /* enable intr when transfer complete */
> - out_8(&sw->intr_enable, ERROR_INTR | TRANSFER_DONE);
> + out_8(&sw->intr_enable, TRANSFER_DONE);
> + out_8(&sw->control_bis, DO_ACTION);
> set_timeout(fs, 2*HZ, xfer_timeout); /* enable timeout */
> }
>
> static void act(struct floppy_state *fs)
> {
> - volatile struct swim3 *sw = fs->swim3;
> -
> for (;;) {
> switch (fs->state) {
> case idle:
> @@ -492,20 +500,10 @@
> return;
>
> case settling:
> - /* wait for SEEK_COMPLETE to become true */
> - swim3_select(fs, SEEK_COMPLETE);
> - udelay(10);
> - out_8(&sw->intr_enable, ERROR_INTR | DATA_CHANGED);
> - in_8(&sw->intr); /* clear DATA_CHANGED */
> - if (in_8(&sw->status) & DATA) {
> - /* seek_complete is not yet true */
> - set_timeout(fs, HZ/2, seek_timeout);
> - return;
> - }
> - out_8(&sw->intr_enable, 0);
> - in_8(&sw->intr);
> - fs->state = locating;
> - break;
> + /* check for SEEK_COMPLETE after 30ms */
> + fs->settle_time = (HZ + 32) / 33;
> + set_timeout(fs, fs->settle_time, settle_timeout);
> + return;
>
> case do_transfer:
> if (fs->cur_cyl != fs->req_cyl) {
> @@ -537,7 +535,7 @@
> volatile struct swim3 *sw = fs->swim3;
>
> fs->timeout_pending = 0;
> - out_8(&sw->control_bic, DO_ACTION);
> + out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
> out_8(&sw->select, RELAX);
> out_8(&sw->intr_enable, 0);
> fs->cur_cyl = -1;
> @@ -557,20 +555,34 @@
> volatile struct swim3 *sw = fs->swim3;
>
> fs->timeout_pending = 0;
> - if (fs->state == settling) {
> - printk(KERN_ERR "swim3: MSI sel=%x ctrl=%x stat=%x intr=%x ie=%x\n",
> - sw->select, sw->control, sw->status, sw->intr, sw->intr_enable);
> - }
> out_8(&sw->control_bic, DO_SEEK);
> out_8(&sw->select, RELAX);
> out_8(&sw->intr_enable, 0);
> - if (fs->state == settling && swim3_readbit(fs, SEEK_COMPLETE)) {
> - /* printk(KERN_DEBUG "swim3: missed settling interrupt\n"); */
> + printk(KERN_ERR "swim3: seek timeout\n");
> + end_request(fd_req, 0);
> + fs->state = idle;
> + start_request(fs);
> +}
> +
> +static void settle_timeout(unsigned long data)
> +{
> + struct floppy_state *fs = (struct floppy_state *) data;
> + volatile struct swim3 *sw = fs->swim3;
> +
> + fs->timeout_pending = 0;
> + if (swim3_readbit(fs, SEEK_COMPLETE)) {
> + out_8(&sw->select, RELAX);
> fs->state = locating;
> act(fs);
> return;
> }
> - printk(KERN_ERR "swim3: seek timeout\n");
> + out_8(&sw->select, RELAX);
> + if (fs->settle_time < 2*HZ) {
> + ++fs->settle_time;
> + set_timeout(fs, 1, settle_timeout);
> + return;
> + }
> + printk(KERN_ERR "swim3: seek settle timeout\n");
> end_request(fd_req, 0);
> fs->state = idle;
> start_request(fs);
> @@ -583,9 +595,13 @@
> struct dbdma_regs *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);
> + /* We must wait a bit for dbdma to stop */
> + for (n = 0; (in_le32(&dr->status) & ACTIVE) && n < 1000; n++)
> + udelay(1);
> out_8(&sw->intr_enable, 0);
> out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
> out_8(&sw->select, RELAX);
> @@ -604,7 +620,7 @@
> start_request(fs);
> }
>
> -static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
> +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;
> @@ -613,18 +629,15 @@
> struct dbdma_regs *dr;
> struct dbdma_cmd *cp;
>
> - err = in_8(&sw->error);
> intr = in_8(&sw->intr);
> -#if 0
> - printk("swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err);
> -#endif
> + 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",
> fs->state, rq_data_dir(fd_req), intr, err);
> switch (fs->state) {
> case locating:
> if (intr & SEEN_SECTOR) {
> - out_8(&sw->control_bic, DO_ACTION);
> + out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
> out_8(&sw->select, RELAX);
> out_8(&sw->intr_enable, 0);
> del_timer(&fs->timeout);
> @@ -674,19 +687,33 @@
> case do_transfer:
> if ((intr & (ERROR_INTR | TRANSFER_DONE)) == 0)
> break;
> - dr = fs->dma;
> - cp = fs->dma_cmd;
> - /* We must wait a bit for dbdma to complete */
> - for (n=0; (in_le32(&dr->status) & ACTIVE) && n < 1000; n++)
> - udelay(10);
> - DBDMA_DO_STOP(dr);
> out_8(&sw->intr_enable, 0);
> out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
> out_8(&sw->select, RELAX);
> del_timer(&fs->timeout);
> fs->timeout_pending = 0;
> + dr = fs->dma;
> + cp = fs->dma_cmd;
> if (rq_data_dir(fd_req) == WRITE)
> ++cp;
> + /*
> + * Check that the main data transfer has finished.
> + * On writing, the swim3 sometimes doesn't use
> + * up all the bytes of the postamble, so we can still
> + * see DMA active here. That doesn't matter as long
> + * as all the sector data has been transferred.
> + */
> + if ((intr & ERROR_INTR) == 0 && cp->xfer_status == 0) {
> + /* wait a little while for DMA to complete */
> + for (n = 0; n < 100; ++n) {
> + if (cp->xfer_status != 0)
> + break;
> + udelay(1);
> + barrier();
> + }
> + }
> + /* turn off DMA */
> + out_le32(&dr->control, (RUN | PAUSE) << 16);
> stat = ld_le16(&cp->xfer_status);
> resid = ld_le16(&cp->res_count);
> if (intr & ERROR_INTR) {
> @@ -742,6 +769,7 @@
> default:
> printk(KERN_ERR "swim3: don't know what to do in state %d\n", fs->state);
> }
> + return IRQ_HANDLED;
> }
>
> /*
> @@ -793,16 +821,19 @@
> if (err)
> return err;
> swim3_action(fs, EJECT);
> - for (n = 2*HZ; n > 0; --n) {
> - if (swim3_readbit(fs, RELAX))
> - break;
> + for (n = 20; n > 0; --n) {
> if (signal_pending(current)) {
> err = -EINTR;
> break;
> }
> + swim3_select(fs, RELAX);
> current->state = TASK_INTERRUPTIBLE;
> schedule_timeout(1);
> + if (swim3_readbit(fs, DISK_IN) == 0)
> + break;
> }
> + swim3_select(fs, RELAX);
> + udelay(150);
> fs->ejected = 1;
> release_drive(fs);
> return err;
> @@ -847,29 +878,31 @@
> if (fs->ref_count == 0) {
> 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->setup, S_IBM_DRIVE | S_FCLK_DIV2);
> + out_8(&sw->control_bic, 0xff);
> + out_8(&sw->mode, 0x95);
> udelay(10);
> out_8(&sw->intr_enable, 0);
> out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);
> swim3_action(fs, MOTOR_ON);
> fs->write_prot = -1;
> fs->cur_cyl = -1;
> - for (n = HZ; n > 0; --n) {
> - if (swim3_readbit(fs, SEEK_COMPLETE))
> + for (n = 0; n < 2 * HZ; ++n) {
> + if (n >= HZ/30 && swim3_readbit(fs, SEEK_COMPLETE))
> break;
> if (signal_pending(current)) {
> err = -EINTR;
> break;
> }
> + swim3_select(fs, RELAX);
> current->state = TASK_INTERRUPTIBLE;
> schedule_timeout(1);
> }
> if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0
> || swim3_readbit(fs, DISK_IN) == 0))
> err = -ENXIO;
> - swim3_action(fs, 9);
> + swim3_action(fs, SETMFM);
> + swim3_select(fs, RELAX);
>
> } else if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
> return -EBUSY;
> @@ -892,6 +925,7 @@
> if (fs->ref_count == 0) {
> swim3_action(fs, MOTOR_OFF);
> out_8(&sw->control_bic, DRIVE_ENABLE | INTR_ENABLE);
> + swim3_select(fs, RELAX);
> }
> return err;
> }
> @@ -911,6 +945,7 @@
> if (fs->ref_count > 0 && --fs->ref_count == 0) {
> swim3_action(fs, MOTOR_OFF);
> out_8(&sw->control_bic, 0xff);
> + swim3_select(fs, RELAX);
> }
> return 0;
> }
> @@ -933,15 +968,17 @@
> sw = fs->swim3;
> grab_drive(fs, revalidating, 0);
> out_8(&sw->intr_enable, 0);
> - out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);
> - swim3_action(fs, MOTOR_ON);
> + out_8(&sw->control_bis, DRIVE_ENABLE);
> + swim3_action(fs, MOTOR_ON); /* necessary? */
> fs->write_prot = -1;
> fs->cur_cyl = -1;
> + mdelay(1);
> for (n = HZ; n > 0; --n) {
> if (swim3_readbit(fs, SEEK_COMPLETE))
> break;
> if (signal_pending(current))
> break;
> + swim3_select(fs, RELAX);
> current->state = TASK_INTERRUPTIBLE;
> schedule_timeout(1);
> }
> @@ -951,17 +988,14 @@
> swim3_action(fs, MOTOR_OFF);
> else {
> fs->ejected = 0;
> - swim3_action(fs, 9);
> + swim3_action(fs, SETMFM);
> }
> + swim3_select(fs, RELAX);
>
> release_drive(fs);
> return ret;
> }
>
> -static void floppy_off(unsigned int nr)
> -{
> -}
> -
> static struct block_device_operations floppy_fops = {
> .open = floppy_open,
> .release = floppy_release,
> @@ -1104,3 +1138,5 @@
>
> return 0;
> }
> +
> +module_init(swim3_init)
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
Benjamin Herrenschmidt <benh@kernel.crashing.org>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:59    [W:0.043 / U:0.168 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site