Module Name: src Committed By: jmcneill Date: Mon Feb 24 12:19:05 UTC 2014
Modified Files: src/sys/dev/ic: ahcisata_core.c ahcisatavar.h Log Message: - 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. To generate a diff of this commit: cvs rdiff -u -r1.50 -r1.51 src/sys/dev/ic/ahcisata_core.c cvs rdiff -u -r1.15 -r1.16 src/sys/dev/ic/ahcisatavar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/ahcisata_core.c diff -u src/sys/dev/ic/ahcisata_core.c:1.50 src/sys/dev/ic/ahcisata_core.c:1.51 --- src/sys/dev/ic/ahcisata_core.c:1.50 Sun Sep 8 11:47:16 2013 +++ src/sys/dev/ic/ahcisata_core.c Mon Feb 24 12:19:05 2014 @@ -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 @@ const struct ata_bustype ahci_ata_bustyp 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 @@ ahci_reset(struct ahci_softc *sc) 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 @@ ahci_attach(struct ahci_softc *sc) 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 @@ ahci_channel_stop(struct ahci_softc *sc, /* XXX controller reset ? */ return; } + + if (sc->sc_channel_stop) + sc->sc_channel_stop(sc, chp); } static void @@ -1363,6 +1404,10 @@ ahci_channel_start(struct ahci_softc *sc 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 @@ ahci_timeout(void *v) 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; Index: src/sys/dev/ic/ahcisatavar.h diff -u src/sys/dev/ic/ahcisatavar.h:1.15 src/sys/dev/ic/ahcisatavar.h:1.16 --- src/sys/dev/ic/ahcisatavar.h:1.15 Sun Sep 8 11:47:16 2013 +++ src/sys/dev/ic/ahcisatavar.h Mon Feb 24 12:19:05 2014 @@ -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 @@ struct ahci_softc { 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))