Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev Move most of the atabus layer into ata.c.
details: https://anonhg.NetBSD.org/src/rev/bde947b354a5
branches: trunk
changeset: 556919:bde947b354a5
user: thorpej <thorpej%NetBSD.org@localhost>
date: Tue Dec 30 16:28:37 2003 +0000
description:
Move most of the atabus layer into ata.c.
diffstat:
sys/dev/ata/ata.c | 301 +++++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/ata/atavar.h | 32 ++++-
sys/dev/ic/wdc.c | 315 +++-----------------------------------------------
sys/dev/ic/wdcvar.h | 11 +-
4 files changed, 352 insertions(+), 307 deletions(-)
diffs (truncated from 815 to 300 lines):
diff -r 398e6ef7c5aa -r bde947b354a5 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Tue Dec 30 14:29:30 2003 +0000
+++ b/sys/dev/ata/ata.c Tue Dec 30 16:28:37 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.22 2003/12/30 00:43:31 thorpej Exp $ */
+/* $NetBSD: ata.c,v 1.23 2003/12/30 16:28:37 thorpej 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.22 2003/12/30 00:43:31 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.23 2003/12/30 16:28:37 thorpej Exp $");
#ifndef WDCDEBUG
#define WDCDEBUG
@@ -39,11 +39,11 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
-#include <sys/file.h>
-#include <sys/stat.h>
#include <sys/malloc.h>
#include <sys/device.h>
-#include <sys/syslog.h>
+#include <sys/proc.h>
+#include <sys/kthread.h>
+#include <sys/errno.h>
#include <machine/intr.h>
#include <machine/bus.h>
@@ -53,8 +53,11 @@
#include <dev/ic/wdcreg.h>
#include <dev/ic/wdcvar.h>
+#include "locators.h"
+
#define DEBUG_FUNCS 0x08
#define DEBUG_PROBE 0x10
+#define DEBUG_DETACH 0x20
#ifdef WDCDEBUG
extern int wdcdebug_mask; /* init'ed in wdc.c */
#define WDCDEBUG_PRINT(args, level) \
@@ -64,6 +67,294 @@
#define WDCDEBUG_PRINT(args, level)
#endif
+/*****************************************************************************
+ * ATA bus layer.
+ *
+ * ATA controllers attach an atabus instance, which handles probing the bus
+ * for drives, etc.
+ *****************************************************************************/
+
+/*
+ * atabusprint:
+ *
+ * Autoconfiguration print routine used by ATA controllers when
+ * attaching an atabus instance.
+ */
+int
+atabusprint(void *aux, const char *pnp)
+{
+ struct channel_softc *chan = aux;
+
+ if (pnp)
+ aprint_normal("atabus at %s", pnp);
+ aprint_normal(" channel %d", chan->channel);
+
+ return (UNCONF);
+}
+
+/*
+ * ataprint:
+ *
+ * Autoconfiguration print routine.
+ */
+int
+ataprint(void *aux, const char *pnp)
+{
+ struct ata_device *adev = aux;
+
+ if (pnp)
+ aprint_normal("wd at %s", pnp);
+ aprint_normal(" drive %d", adev->adev_drv_data->drive);
+
+ return (UNCONF);
+}
+
+/*
+ * atabus_thread:
+ *
+ * Worker thread for the ATA bus.
+ */
+static void
+atabus_thread(void *arg)
+{
+ struct atabus_softc *sc = arg;
+ struct channel_softc *chp = sc->sc_chan;
+ struct wdc_xfer *xfer;
+ int s;
+
+ s = splbio();
+ chp->ch_flags |= WDCF_TH_RUN;
+ splx(s);
+
+ /* Configure the devices on the bus. */
+ atabusconfig(sc);
+
+ for (;;) {
+ s = splbio();
+ if ((chp->ch_flags & (WDCF_TH_RESET | WDCF_SHUTDOWN)) == 0 &&
+ ((chp->ch_flags & WDCF_ACTIVE) == 0 ||
+ chp->ch_queue->queue_freeze == 0)) {
+ chp->ch_flags &= ~WDCF_TH_RUN;
+ (void) tsleep(&chp->thread, PRIBIO, "atath", 0);
+ chp->ch_flags |= WDCF_TH_RUN;
+ }
+ splx(s);
+ if (chp->ch_flags & WDCF_SHUTDOWN)
+ break;
+ s = splbio();
+ if (chp->ch_flags & WDCF_TH_RESET) {
+ int drive;
+
+ (void) wdcreset(chp, RESET_SLEEP);
+ for (drive = 0; drive < 2; drive++)
+ chp->ch_drive[drive].state = 0;
+ chp->ch_flags &= ~WDCF_TH_RESET;
+ chp->ch_queue->queue_freeze--;
+ wdcstart(chp);
+ } else if ((chp->ch_flags & WDCF_ACTIVE) != 0 &&
+ chp->ch_queue->queue_freeze == 1) {
+ /*
+ * Caller has bumped queue_freeze, decrease it.
+ */
+ chp->ch_queue->queue_freeze--;
+ xfer = TAILQ_FIRST(&chp->ch_queue->sc_xfer);
+ KASSERT(xfer != NULL);
+ (*xfer->c_start)(chp, xfer);
+ } else if (chp->ch_queue->queue_freeze > 1)
+ panic("ata_thread: queue_freeze");
+ splx(s);
+ }
+ chp->thread = NULL;
+ wakeup(&chp->ch_flags);
+ kthread_exit(0);
+}
+
+/*
+ * atabus_create_thread:
+ *
+ * Helper routine to create the ATA bus worker thread.
+ */
+static void
+atabus_create_thread(void *arg)
+{
+ struct atabus_softc *sc = arg;
+ struct channel_softc *chp = sc->sc_chan;
+ int error;
+
+ if ((error = kthread_create1(atabus_thread, sc, &chp->thread,
+ "%s", sc->sc_dev.dv_xname)) != 0)
+ aprint_error("%s: unable to create kernel thread: error %d\n",
+ sc->sc_dev.dv_xname, error);
+}
+
+/*
+ * atabus_match:
+ *
+ * Autoconfiguration match routine.
+ */
+static int
+atabus_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct channel_softc *chp = aux;
+
+ if (chp == NULL)
+ return (0);
+
+ if (cf->cf_loc[ATACF_CHANNEL] != chp->channel &&
+ cf->cf_loc[ATACF_CHANNEL] != ATACF_CHANNEL_DEFAULT)
+ return (0);
+
+ return (1);
+}
+
+/*
+ * atabus_attach:
+ *
+ * Autoconfiguration attach routine.
+ */
+static void
+atabus_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct atabus_softc *sc = (void *) self;
+ struct channel_softc *chp = aux;
+ struct atabus_initq *initq;
+
+ sc->sc_chan = chp;
+
+ aprint_normal("\n");
+ aprint_naive("\n");
+
+ initq = malloc(sizeof(*initq), M_DEVBUF, M_WAITOK);
+ initq->atabus_sc = sc;
+ TAILQ_INSERT_TAIL(&atabus_initq_head, initq, atabus_initq);
+ config_pending_incr();
+ kthread_create(atabus_create_thread, sc);
+}
+
+/*
+ * atabus_activate:
+ *
+ * Autoconfiguration activation routine.
+ */
+static int
+atabus_activate(struct device *self, enum devact act)
+{
+ struct atabus_softc *sc = (void *) self;
+ struct channel_softc *chp = sc->sc_chan;
+ struct device *dev = NULL;
+ int s, i, error = 0;
+
+ s = splbio();
+ switch (act) {
+ case DVACT_ACTIVATE:
+ error = EOPNOTSUPP;
+ break;
+
+ case DVACT_DEACTIVATE:
+ /*
+ * We might deactivate the children of atapibus twice
+ * (once bia atapibus, once directly), but since the
+ * generic autoconfiguration code maintains the DVF_ACTIVE
+ * flag, it's safe.
+ */
+ if ((dev = chp->atapibus) != NULL) {
+ error = config_deactivate(dev);
+ if (error)
+ goto out;
+ }
+
+ for (i = 0; i < 2; i++) {
+ if ((dev = chp->ch_drive[i].drv_softc) != NULL) {
+ WDCDEBUG_PRINT(("atabus_activate: %s: "
+ "deactivating %s\n", sc->sc_dev.dv_xname,
+ dev->dv_xname),
+ DEBUG_DETACH);
+ error = config_deactivate(dev);
+ if (error)
+ goto out;
+ }
+ }
+ break;
+ }
+ out:
+ splx(s);
+
+#ifdef WDCDEBUG
+ if (dev != NULL && error != 0)
+ WDCDEBUG_PRINT(("atabus_activate: %s: "
+ "error %d deactivating %s\n", sc->sc_dev.dv_xname,
+ error, dev->dv_xname), DEBUG_DETACH);
+#endif /* WDCDEBUG */
+
+ return (error);
+}
+
+/*
+ * atabus_detach:
+ *
+ * Autoconfiguration detach routine.
+ */
+static int
+atabus_detach(struct device *self, int flags)
+{
+ struct atabus_softc *sc = (void *) self;
+ struct channel_softc *chp = sc->sc_chan;
+ struct device *dev = NULL;
+ int i, error = 0;
+
+ /* Shutdown the channel. */
+ /* XXX NEED AN INTERLOCK HERE. */
+ chp->ch_flags |= WDCF_SHUTDOWN;
+ wakeup(&chp->thread);
+ while (chp->thread != NULL)
+ (void) tsleep(&chp->ch_flags, PRIBIO, "atadown", 0);
+
+ /*
+ * Detach atapibus and its children.
+ */
+ if ((dev = chp->atapibus) != NULL) {
+ WDCDEBUG_PRINT(("atabus_detach: %s: detaching %s\n",
+ sc->sc_dev.dv_xname, dev->dv_xname), DEBUG_DETACH);
+ error = config_detach(dev, flags);
+ if (error)
+ goto out;
Home |
Main Index |
Thread Index |
Old Index