Subject: Re: strange behaviour of apmd
To: Thorsten Frueauf <frueauf@ira.uka.de>
From: Chris G. Demetriou <cgd@CS.cmu.edu>
List: current-users
Date: 01/14/1997 14:23:21
> And even more strange, sometimes (not always!) the /etc/apm/resume script is
> trashed! It has the same size as before, but does only conatin 0 chars!
So, there have been several failure modes reported with the 'wd'
driver in combination with suspend/resume on laptops.
The patch below fixed all of them for me. If it fixes the problem for
you, please let me know. The patch is what I sent to the i386 port
maintainers >2 months ago. There have been few (one 8-) changes to
the wd driver since then, but that change is unrelated and this patch
should apply relatively cleanly.
At the time i sent it to the i386 port maintainers, i specifically
said:
>thoughts? If this patch is inappropriate, i'd appreciate knowing why,
>and being given enough information so that I might be able to fix it.
>Without this patch, my laptop was unusable after suspends...
I've yet to get _any_ reply. (Other mail that i sent at the same
time, e.g. the NKPDE "fixes," was responded to soon after, so it's not
clear that "you should have sent a PR" is a reasonable response...)
cgd
===================================================================
Index: wd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/wd.c,v
retrieving revision 1.154
diff -c -r1.154 wd.c
*** wd.c 1996/11/07 05:23:07 1.154
--- wd.c 1996/11/09 00:29:27
***************
*** 96,102 ****
#define GEOMETRY_WAIT 3 /* done uploading geometry */
#define MULTIMODE 4 /* set multiple mode */
#define MULTIMODE_WAIT 5 /* done setting multiple mode */
! #define OPEN 6 /* done with open */
int sc_mode; /* transfer mode */
#define WDM_PIOSINGLE 0 /* single-sector PIO */
#define WDM_PIOMULTI 1 /* multi-sector PIO */
--- 96,102 ----
#define GEOMETRY_WAIT 3 /* done uploading geometry */
#define MULTIMODE 4 /* set multiple mode */
#define MULTIMODE_WAIT 5 /* done setting multiple mode */
! #define READY 6 /* ready for use */
int sc_mode; /* transfer mode */
#define WDM_PIOSINGLE 0 /* single-sector PIO */
#define WDM_PIOMULTI 1 /* multi-sector PIO */
***************
*** 547,553 ****
bp = wd->sc_q.b_actf;
if (wdc->sc_errors >= WDIORETRIES) {
! wderror(wd, bp, "hard error");
bp->b_error = EIO;
bp->b_flags |= B_ERROR;
wdfinish(wd, bp);
--- 547,553 ----
bp = wd->sc_q.b_actf;
if (wdc->sc_errors >= WDIORETRIES) {
! wderror(wd, bp, "wdcstart hard error");
bp->b_error = EIO;
bp->b_flags |= B_ERROR;
wdfinish(wd, bp);
***************
*** 555,561 ****
}
/* Do control operations specially. */
! if (wd->sc_state < OPEN) {
/*
* Actually, we want to be careful not to mess with the control
* state if the device is currently busy, but we can assume
--- 555,561 ----
}
/* Do control operations specially. */
! if (wd->sc_state < READY) {
/*
* Actually, we want to be careful not to mess with the control
* state if the device is currently busy, but we can assume
***************
*** 783,789 ****
}
/* Is it not a transfer, but a control operation? */
! if (wd->sc_state < OPEN) {
if (wdcontrol(wd) == 0) {
/* The drive is busy. Wait. */
return 1;
--- 783,789 ----
}
/* Is it not a transfer, but a control operation? */
! if (wd->sc_state < READY) {
if (wdcontrol(wd) == 0) {
/* The drive is busy. Wait. */
return 1;
***************
*** 811,821 ****
if (bp->b_flags & B_FORMAT)
goto bad;
#endif
-
- if (++wdc->sc_errors < WDIORETRIES)
- goto restart;
- wderror(wd, bp, "hard error");
#ifdef B_FORMAT
bad:
#endif
--- 811,828 ----
if (bp->b_flags & B_FORMAT)
goto bad;
#endif
+ if (++wdc->sc_errors < WDIORETRIES) {
+ if (wdc->sc_errors == (WDIORETRIES + 1) / 2) {
+ #if 0
+ wderror(wd, NULL, "wedgie");
+ #endif
+ wdcunwedge(wdc);
+ return 1;
+ }
+ goto restart;
+ }
+ wderror(wd, bp, "wdcintr hard error");
#ifdef B_FORMAT
bad:
#endif
***************
*** 1129,1135 ****
case MULTIMODE:
multimode:
if (wd->sc_mode != WDM_PIOMULTI)
! goto open;
outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple);
if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
--- 1136,1142 ----
case MULTIMODE:
multimode:
if (wd->sc_mode != WDM_PIOMULTI)
! goto ready;
outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple);
if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
***************
*** 1144,1153 ****
goto bad;
}
/* fall through */
! case OPEN:
! open:
wdc->sc_errors = 0;
! wd->sc_state = OPEN;
/*
* The rest of the initialization can be done by normal means.
*/
--- 1151,1160 ----
goto bad;
}
/* fall through */
! case READY:
! ready:
wdc->sc_errors = 0;
! wd->sc_state = READY;
/*
* The rest of the initialization can be done by normal means.
*/
***************
*** 1500,1506 ****
part = WDPART(dev);
/* Make sure it was initialized. */
! if (wd->sc_state < OPEN)
return ENXIO;
wdc = (void *)wd->sc_dev.dv_parent;
--- 1507,1513 ----
part = WDPART(dev);
/* Make sure it was initialized. */
! if (wd->sc_state < READY)
return ENXIO;
wdc = (void *)wd->sc_dev.dv_parent;