Subject: Re: port-i386/21531 (ACPI enabled kernel enforces stressful
To: None <tech-kern@netbsd.org>
From: Takayoshi Kochi <kochi@netbsd.org>
List: tech-kern
Date: 08/16/2003 02:59:25
----Next_Part(Sat_Aug_16_02:59:25_2003_725)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Hi,
It seems that no one is actively looking at this PR...
I updated the proposed patch in PR/21531 to -current and tested
on my laptop (ThinkPad X31), which worked fine.
Can someone familiar with ATA (Manuel or Jason?) look at the
patch and commit if it's ok?
---
Takayoshi Kochi
----Next_Part(Sat_Aug_16_02:59:25_2003_725)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="wd.c.patch3"
--- wd.c.orig 2003-08-10 01:29:29.000000000 +0900
+++ wd.c 2003-08-16 02:24:41.000000000 +0900
@@ -190,6 +190,7 @@
void __wdstart(struct wd_softc*, struct buf *);
void wdrestart(void *);
int wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *);
+int wd_pm_command(struct wd_softc *, u_int8_t, int);
void wd_flushcache(struct wd_softc *, int);
void wd_shutdown(void *);
@@ -1725,11 +1726,72 @@
*/
}
+int
+wd_pm_command(struct wd_softc *wd, u_int8_t cmd, int flags)
+{
+ struct wdc_command wdc_c;
+ struct ataparams params;
+ char const *verb;
+
+ if (wd_get_params(wd, AT_WAIT, ¶ms) != 0)
+ return EIO;
+ if (params.atap_cmd_set1 == 0x0000 ||
+ params.atap_cmd_set1 == 0xffff ||
+ (params.atap_cmd_set1 & WDC_CMD1_PM) == 0)
+ return EOPNOTSUPP;
+ switch (cmd) {
+ case WDCC_IDLE_IMMED :
+ verb = "idle";
+ break;
+ case WDCC_STANDBY_IMMED :
+ verb = "standby";
+ break;
+ case WDCC_SLEEP :
+ verb = "sleep";
+ break;
+ default :
+ verb = "unknown";
+#ifdef DIAGNOSTIC
+ panic("wd_pm_command: unknown command\n");
+#endif
+ }
+ memset(&wdc_c, 0, sizeof(struct wdc_command));
+ wdc_c.r_command = cmd;
+ wdc_c.r_st_bmask = WDCS_DRDY;
+ wdc_c.r_st_pmask = WDCS_DRDY;
+ wdc_c.flags = flags;
+ wdc_c.timeout = 30000; /* 30s timeout -- XXX too long? */
+ if (wd->atabus->ata_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) {
+ printf("%s: %s command didn't complete\n",
+ wd->sc_dev.dv_xname, verb);
+ return EIO;
+ }
+ if (wdc_c.flags & AT_TIMEOU) {
+ printf("%s: %s command timeout\n",
+ wd->sc_dev.dv_xname, verb);
+ return EIO;
+ }
+ if (wdc_c.flags & AT_DF) {
+ printf("%s: %s command: drive fault\n",
+ wd->sc_dev.dv_xname, verb);
+ return EIO;
+ }
+ /*
+ * Error register shouldn't report anything else than COMMAND ABORTED,
+ * which means the device doesn't support given command.
+ */
+ if (wdc_c.flags & AT_ERROR)
+ return EOPNOTSUPP;
+ return (0);
+}
+
void
wd_shutdown(void *arg)
{
struct wd_softc *wd = arg;
- wd_flushcache(wd, AT_POLL);
+
+ if (wd_pm_command(wd, WDCC_STANDBY_IMMED, AT_POLL) != 0)
+ wd_flushcache(wd, AT_POLL);
}
/*
----Next_Part(Sat_Aug_16_02:59:25_2003_725)----