summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorjmcneill <jmcneill@NetBSD.org>2005-01-26 21:51:40 +0000
committerjmcneill <jmcneill@NetBSD.org>2005-01-26 21:51:40 +0000
commit3ab5a3900dda19c7c9a3462b85e59cd8b811b669 (patch)
treeb391c598d3ae4f9ac557e946acfb4733e8013217 /sys/dev
parent5a6c12cd3bafedac8fbea35b275f260dbc046a44 (diff)
Add powerhook for atabus.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/ata.c48
-rw-r--r--sys/dev/ata/atavar.h4
2 files changed, 48 insertions, 4 deletions
diff --git a/sys/dev/ata/ata.c b/sys/dev/ata/ata.c
index f330eb36039..4dae497778f 100644
--- a/sys/dev/ata/ata.c
+++ b/sys/dev/ata/ata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.63 2004/11/14 15:25:11 soren Exp $ */
+/* $NetBSD: ata.c,v 1.64 2005/01/26 21:51:40 jmcneill Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.63 2004/11/14 15:25:11 soren Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.64 2005/01/26 21:51:40 jmcneill Exp $");
#ifndef ATADEBUG
#define ATADEBUG
@@ -105,6 +105,7 @@ const struct cdevsw atabus_cdevsw = {
extern struct cfdriver atabus_cd;
+static void atabus_powerhook(int, void *);
/*
* atabusprint:
@@ -321,7 +322,11 @@ atabus_thread(void *arg)
splx(s);
/* Configure the devices on the bus. */
- atabusconfig(sc);
+ if (sc->sc_sleeping == 1) {
+ printf("%s: resuming...\n", sc->sc_dev.dv_xname);
+ sc->sc_sleeping = 0;
+ } else
+ atabusconfig(sc);
for (;;) {
s = splbio();
@@ -424,6 +429,12 @@ atabus_attach(struct device *parent, struct device *self, void *aux)
TAILQ_INSERT_TAIL(&atabus_initq_head, initq, atabus_initq);
config_pending_incr();
kthread_create(atabus_create_thread, sc);
+
+ sc->sc_sleeping = 0;
+ sc->sc_powerhook = powerhook_establish(atabus_powerhook, sc);
+ if (sc->sc_powerhook == NULL)
+ printf("%s: WARNING: unable to establish power hook\n",
+ sc->sc_dev.dv_xname);
}
/*
@@ -1396,3 +1407,34 @@ atabusioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
}
return (error);
};
+
+static void
+atabus_powerhook(int why, void *hdl)
+{
+ struct atabus_softc *sc = (struct atabus_softc *)hdl;
+ struct ata_channel *chp = sc->sc_chan;
+ int s;
+
+ switch (why) {
+ case PWR_SOFTSUSPEND:
+ case PWR_SOFTSTANDBY:
+ sc->sc_sleeping = 1;
+ s = splbio();
+ chp->ch_flags = ATACH_SHUTDOWN;
+ splx(s);
+ wakeup(&chp->ch_thread);
+ while (chp->ch_thread != NULL)
+ (void) tsleep((void *)&chp->ch_flags, PRIBIO,
+ "atadown", 0);
+ break;
+ case PWR_RESUME:
+ atabus_create_thread(sc);
+ break;
+ case PWR_SUSPEND:
+ case PWR_STANDBY:
+ case PWR_SOFTRESUME:
+ break;
+ }
+
+ return;
+}
diff --git a/sys/dev/ata/atavar.h b/sys/dev/ata/atavar.h
index a994e83b682..2cafd65c02c 100644
--- a/sys/dev/ata/atavar.h
+++ b/sys/dev/ata/atavar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.65 2004/10/30 23:10:37 bouyer Exp $ */
+/* $NetBSD: atavar.h,v 1.66 2005/01/26 21:51:40 jmcneill Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -96,6 +96,8 @@ struct atabus_softc {
struct ata_channel *sc_chan;
int sc_flags;
#define ATABUSCF_OPEN 0x01
+ void *sc_powerhook;
+ int sc_sleeping;
};
/*