Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic - Only enable AHCI mode if it is not already enab...
details: https://anonhg.NetBSD.org/src/rev/94670241c5ff
branches: trunk
changeset: 326972:94670241c5ff
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Feb 24 12:19:05 2014 +0000
description:
- Only enable AHCI mode if it is not already enabled.
- Add support for capturing initial CAP/CAP2/PI regs before reset (and
restoring them afterwords)
- Add optional callbacks for channel_start / channel_stop.
diffstat:
sys/dev/ic/ahcisata_core.c | 53 ++++++++++++++++++++++++++++++++++++++++++---
sys/dev/ic/ahcisatavar.h | 12 +++++++++-
2 files changed, 60 insertions(+), 5 deletions(-)
diffs (135 lines):
diff -r 8ac6eb549ec5 -r 94670241c5ff sys/dev/ic/ahcisata_core.c
--- a/sys/dev/ic/ahcisata_core.c Mon Feb 24 11:56:01 2014 +0000
+++ b/sys/dev/ic/ahcisata_core.c Mon Feb 24 12:19:05 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisata_core.c,v 1.50 2013/09/08 11:47:16 matt Exp $ */
+/* $NetBSD: ahcisata_core.c,v 1.51 2014/02/24 12:19:05 jmcneill Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.50 2013/09/08 11:47:16 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.51 2014/02/24 12:19:05 jmcneill Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -119,6 +119,18 @@
static void ahci_intr_port(struct ahci_softc *, struct ahci_channel *);
static void ahci_setup_port(struct ahci_softc *sc, int i);
+static void
+ahci_enable(struct ahci_softc *sc)
+{
+ uint32_t ghc;
+
+ ghc = AHCI_READ(sc, AHCI_GHC);
+ if (!(ghc & AHCI_GHC_AE)) {
+ ghc |= AHCI_GHC_AE;
+ AHCI_WRITE(sc, AHCI_GHC, ghc);
+ }
+}
+
static int
ahci_reset(struct ahci_softc *sc)
{
@@ -137,7 +149,15 @@
return -1;
}
/* enable ahci mode */
- AHCI_WRITE(sc, AHCI_GHC, AHCI_GHC_AE);
+ ahci_enable(sc);
+
+ if (sc->sc_save_init_data) {
+ AHCI_WRITE(sc, AHCI_CAP, sc->sc_init_data.cap);
+ if (sc->sc_init_data.cap2)
+ AHCI_WRITE(sc, AHCI_CAP2, sc->sc_init_data.cap2);
+ AHCI_WRITE(sc, AHCI_PI, sc->sc_init_data.ports);
+ }
+
return 0;
}
@@ -216,6 +236,24 @@
void *cmdhp;
void *cmdtblp;
+ if (sc->sc_save_init_data) {
+ ahci_enable(sc);
+
+ sc->sc_init_data.cap = AHCI_READ(sc, AHCI_CAP);
+ sc->sc_init_data.ports = AHCI_READ(sc, AHCI_PI);
+
+ ahci_rev = AHCI_READ(sc, AHCI_VS);
+ if (AHCI_VS_MJR(ahci_rev) > 1 ||
+ (AHCI_VS_MJR(ahci_rev) == 1 && AHCI_VS_MNR(ahci_rev) >= 20)) {
+ sc->sc_init_data.cap2 = AHCI_READ(sc, AHCI_CAP2);
+ } else {
+ sc->sc_init_data.cap2 = 0;
+ }
+ if (sc->sc_init_data.ports == 0) {
+ sc->sc_init_data.ports = sc->sc_ahci_ports;
+ }
+ }
+
if (ahci_reset(sc) != 0)
return;
@@ -1330,6 +1368,9 @@
/* XXX controller reset ? */
return;
}
+
+ if (sc->sc_channel_stop)
+ sc->sc_channel_stop(sc, chp);
}
static void
@@ -1363,6 +1404,10 @@
return;
}
}
+
+ if (sc->sc_channel_start)
+ sc->sc_channel_start(sc, chp);
+
/* and start controller */
p_cmd = AHCI_P_CMD_ICC_AC | AHCI_P_CMD_POD | AHCI_P_CMD_SUD |
AHCI_P_CMD_FRE | AHCI_P_CMD_ST;
@@ -1382,7 +1427,7 @@
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
#endif
int s = splbio();
- AHCIDEBUG_PRINT(("ahci_timeout xfer %p intr %#x\n", xfer, AHCI_READ(sc, AHCI_P_IS(chp->ch_channel))), DEBUG_INTR);
+ AHCIDEBUG_PRINT(("ahci_timeout xfer %p intr %#x ghc %08x is %08x\n", xfer, AHCI_READ(sc, AHCI_P_IS(chp->ch_channel)), AHCI_READ(sc, AHCI_GHC), AHCI_READ(sc, AHCI_IS)), DEBUG_INTR);
if ((chp->ch_flags & ATACH_IRQ_WAIT) != 0) {
xfer->c_flags |= C_TIMEOU;
diff -r 8ac6eb549ec5 -r 94670241c5ff sys/dev/ic/ahcisatavar.h
--- a/sys/dev/ic/ahcisatavar.h Mon Feb 24 11:56:01 2014 +0000
+++ b/sys/dev/ic/ahcisatavar.h Mon Feb 24 12:19:05 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisatavar.h,v 1.15 2013/09/08 11:47:16 matt Exp $ */
+/* $NetBSD: ahcisatavar.h,v 1.16 2014/02/24 12:19:05 jmcneill Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -83,6 +83,16 @@
bus_dmamap_t ahcic_datad[AHCI_MAX_CMDS];
uint32_t ahcic_cmds_active; /* active commands */
} sc_channels[AHCI_MAX_PORTS];
+
+ void (*sc_channel_start)(struct ahci_softc *, struct ata_channel *);
+ void (*sc_channel_stop)(struct ahci_softc *, struct ata_channel *);
+
+ bool sc_save_init_data;
+ struct {
+ uint32_t cap;
+ uint32_t cap2;
+ uint32_t ports;
+ } sc_init_data;
};
#define AHCINAME(sc) (device_xname((sc)->sc_atac.atac_dev))
Home |
Main Index |
Thread Index |
Old Index