Subject: Re: wdc0:0:0 lost interrupt
To: None <mw@blobulent.com>
From: Andrew Cagney <cagney@mac.com>
List: port-macppc
Date: 07/25/2001 12:40:05
This is a multi-part message in MIME format.
--------------090203080106070409080706
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
> Y'all,
>
> I'm still trying to get my PowerBook (FireWire) working again after
> upgrading to -current, and haven't gotten a satisfactory kernel built.
>
> My latest failure was with sources updated today failing to mount /:
>
> wdc0:0:0 lost interrupt
> type: ata tc_bcount: 512 tc_skip: 0
> wdc0:0:0 recal timed out
> wd0c: device timedout reading fsbn 0 (wd0 bn 0; cn 0 tn 0 sn 0), retrying
>
> I thought we had this wdc0 lost interrupt business licked?
I got sufficiently curious to try and figure this out.
Exhibit A is diff from a merge in progress between 1.12+exhibit.c (the
original patch that ``worked'') and 1.13 (the committed broken change).
Exhibit B is the dmesg output from an earlier 1.13-exibit.a.
Exhibit C is the original wdc patch (slightly white space munged) that
wasn't committed.
So, having confused everyone ...
The file with the original patch contained something like:
*** 265,294 ****
dmamode = drvp->DMA_mode;
}
}
- printf ("piomode %d, dmamode %d\n", piomode, dmamode);
- if (dmamode == -1)
- /* No active DMA mode is found... Do nothing. */
- return;
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
if (drvp->drive_flags & DRIVE) {
while the new file had that test moved to near the end of the function.
Looking at my dmesg:
cd0(wdc1:0:0): using PIO mode 4, DMA mode 2 (using DMA data transfers)
wdc2 at obio0 offset 0x21000 irq 21: DMA transfer
piomode -1, dmamode -1
one begins to suspect that the code might have been doing something
useful. Examining 1.13, you find that it is going to eventually execute
the statements:
min_cycle = pio_timing[piomode].cycle;
min_active = pio_timing[piomode].active;
where piomode==-1. Er, outch!!
Well, thats my theory at least :-)
Andrew
--------------090203080106070409080706
Content-Type: text/plain;
name="exhibit.a"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="exhibit.a"
*** wdc_obio.c Wed Jul 25 12:10:29 2001
--- wdc_obio.c,1.13 Wed Jul 18 21:42:19 2001
***************
*** 223,229 ****
int cycle; /* minimum cycle time [ns] */
int active; /* minimum command active time [ns] */
};
- #if 0
static struct ide_timings pio_timing[5] = {
{ 600, 165 }, /* Mode 0 */
{ 383, 125 }, /* 1 */
--- 223,228 ----
***************
*** 231,237 ****
{ 180, 80 }, /* 3 */
{ 120, 70 } /* 4 */
};
- #endif
static struct ide_timings dma_timing[3] = {
{ 480, 215 }, /* Mode 0 */
{ 150, 80 }, /* Mode 1 */
--- 230,235 ----
***************
*** 265,294 ****
dmamode = drvp->DMA_mode;
}
}
- printf ("piomode %d, dmamode %d\n", piomode, dmamode);
- if (dmamode == -1)
- /* No active DMA mode is found... Do nothing. */
- return;
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
if (drvp->drive_flags & DRIVE) {
! printf ("drvp->PIO_mode = piomode; [%d->%d = %d]\n", drive, drvp->PIO_mode, piomode);
! printf ("if (drvp->drive_flags & DRIVE_DMA) [%d->%x & %x]\n", drive, drvp->drive_flags, DRIVE_DMA);
drvp->DMA_mode = dmamode;
}
}
! min_cycle = dma_timing[dmamode].cycle;
! min_active = dma_timing[dmamode].active;
cycle_tick = TIME_TO_TICK(min_cycle);
act_tick = TIME_TO_TICK(min_active);
inact_tick = cycle_tick - act_tick - 1;
if (inact_tick < 1)
inact_tick = 1;
!
! half_tick = 0; /* XXX */
! conf = (half_tick << 21) | (inact_tick << 16) | (act_tick << 11);
! if (dmamode != -1 && 0) {
/* there are active DMA mode */
min_cycle = dma_timing[dmamode].cycle;
--- 263,286 ----
dmamode = drvp->DMA_mode;
}
}
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
if (drvp->drive_flags & DRIVE) {
! drvp->PIO_mode = piomode;
! if (drvp->drive_flags & DRIVE_DMA)
drvp->DMA_mode = dmamode;
}
}
! min_cycle = pio_timing[piomode].cycle;
! min_active = pio_timing[piomode].active;
cycle_tick = TIME_TO_TICK(min_cycle);
act_tick = TIME_TO_TICK(min_active);
inact_tick = cycle_tick - act_tick - 1;
if (inact_tick < 1)
inact_tick = 1;
! conf = (inact_tick << 5) | act_tick;
! if (dmamode != -1) {
/* there are active DMA mode */
min_cycle = dma_timing[dmamode].cycle;
--------------090203080106070409080706
Content-Type: text/plain;
name="exhibit.b"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="exhibit.b"
wdc0 at obio0 offset 0x1f000 irq 19: DMA transfer
wd0 at wdc0 channel 0 drive 0: <IBM-DJSA-220>
wd0: drive supports 16-sector PIO transfers, LBA addressing
wd0: 19077 MB, 16383 cyl, 16 head, 63 sec, 512 bytes/sect x 39070080 sectors
wd0: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 4 (Ultra/66)
piomode 4, dmamode 2
drvp->PIO_mode = piomode;
if (drvp->drive_flags & DRIVE_DMA)
wd0(wdc0:0:0): using PIO mode 4, DMA mode 2 (using DMA data transfers)
wdc1 at obio0 offset 0x20000 irq 20: DMA transfer
atapibus0 at wdc1 channel 0: 2 targets
cd0 at atapibus0 drive 0: <MATSHITADVD-ROM SR-8187, , HA18> type 5 cdrom removable
cd0: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 2 (Ultra/33)
piomode 4, dmamode 2
drvp->PIO_mode = piomode;
if (drvp->drive_flags & DRIVE_DMA)
cd0(wdc1:0:0): using PIO mode 4, DMA mode 2 (using DMA data transfers)
wdc2 at obio0 offset 0x21000 irq 21: DMA transfer
piomode -1, dmamode -1
--------------090203080106070409080706
Content-Type: text/plain;
name="exhibit.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="exhibit.c"
Index: wdc_obio.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/macppc/dev/wdc_obio.c,v
retrieving revision 1.12
diff -u -r1.12 wdc_obio.c
--- wdc_obio.c 2001/06/08 00:32:02 1.12
+++ wdc_obio.c 2001/06/12 13:15:56
@@ -167,10 +167,13 @@
sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20);
sc->sc_dmareg = mapiodev(ca->ca_baseaddr + ca->ca_reg[2],
ca->ca_reg[3]);
- sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_MODE;
+ sc->sc_wdcdev.PIO_cap = 4;
+ sc->sc_wdcdev.DMA_cap = 2;
+ } else {
+ sc->sc_wdcdev.PIO_cap = 0;
}
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16;
- sc->sc_wdcdev.PIO_cap = 0;
sc->wdc_chanptr = chp;
sc->sc_wdcdev.channels = &sc->wdc_chanptr;
sc->sc_wdcdev.nchannels = 1;
@@ -178,6 +181,7 @@
sc->sc_wdcdev.dma_init = wdc_obio_dma_init;
sc->sc_wdcdev.dma_start = wdc_obio_dma_start;
sc->sc_wdcdev.dma_finish = wdc_obio_dma_finish;
+ sc->sc_wdcdev.set_modes = adjust_timing;
chp->channel = 0;
chp->wdc = &sc->sc_wdcdev;
chp->ch_queue = malloc(sizeof(struct channel_queue),
@@ -207,7 +211,6 @@
if (use_dma)
adjust_timing(chp);
- wdc_print_modes(chp);
}
/* Multiword DMA transfer timings */
@@ -228,24 +231,34 @@
adjust_timing(chp)
struct channel_softc *chp;
{
- struct ataparams params;
- struct ata_drive_datas *drvp = &chp->ch_drive[0]; /* XXX */
+ struct ata_drive_datas *drvp;
u_int conf;
- int mode;
- int cycle, active, min_cycle, min_active;
+ int drive;
+ int mode = -1;
+ int min_cycle, min_active;
int cycle_tick, act_tick, inact_tick, half_tick;
- if (ata_get_params(drvp, AT_POLL, ¶ms) != CMD_OK)
- return;
- for (mode = 2; mode >= 0; mode--)
- if (params.atap_dmamode_act & (1 << mode))
- goto found;
+ for (drive = 0; drive < 2; drive++) {
+ drvp = &chp->ch_drive[drive];
+ if ((drvp->drive_flags & DRIVE) == 0)
+ continue;
+ if (drvp->drive_flags & DRIVE_DMA) {
+ if (mode == -1 || mode > drvp->DMA_mode)
+ mode = drvp->DMA_mode;
+ }
+ }
+ if (mode == -1)
+ /* No active DMA mode is found... Do nothing. */
+ return;
- /* No active DMA mode is found... Do nothing. */
- return;
+ for (drive = 0; drive < 2; drive++) {
+ drvp = &chp->ch_drive[drive];
+ if (drvp->drive_flags & DRIVE)
+ drvp->DMA_mode = mode;
+ }
-found:
+
min_cycle = dma_timing[mode].cycle;
min_active = dma_timing[mode].active;
@@ -254,11 +267,8 @@
if (ohare && params.atap_dmatiming_recom < 150)
params.atap_dmatiming_recom = 150;
#endif
- cycle = max(min_cycle, params.atap_dmatiming_recom);
- active = min_active + (cycle - min_cycle); /* XXX */
-
- cycle_tick = TIME_TO_TICK(cycle);
- act_tick = TIME_TO_TICK(active);
+ cycle_tick = TIME_TO_TICK(min_cycle);
+ act_tick = TIME_TO_TICK(min_active);
inact_tick = cycle_tick - act_tick - 1;
if (inact_tick < 1)
inact_tick = 1;
@@ -267,8 +277,9 @@
bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf);
#if 0
printf("conf = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
- conf, cycle_tick, cycle, act_tick, active, inact_tick);
+ conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
#endif
+ wdc_print_modes(chp);
}
int
--------------090203080106070409080706--