Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Support detachment of ahcisata(4).



details:   https://anonhg.NetBSD.org/src/rev/fd227e02240a
branches:  trunk
changeset: 756663:fd227e02240a
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Tue Jul 27 22:07:50 2010 +0000

description:
Support detachment of ahcisata(4).
Use use 64-bit DMA tag (where available) for ahcisata(4) at jmide(4).
Beginnings of detach/resume support for jmide(4).
Sprinkle static.  Misc. little changes.

diffstat:

 sys/dev/ic/ahcisata_core.c |  211 +++++++++++++++++++++++++++++---------------
 sys/dev/ic/ahcisatavar.h   |   13 +-
 sys/dev/pci/ahcisata_pci.c |   99 +++++++++++++--------
 sys/dev/pci/jmide.c        |   49 +++++++++-
 4 files changed, 253 insertions(+), 119 deletions(-)

diffs (truncated from 840 to 300 lines):

diff -r d2f2dc2dfc00 -r fd227e02240a sys/dev/ic/ahcisata_core.c
--- a/sys/dev/ic/ahcisata_core.c        Tue Jul 27 21:48:41 2010 +0000
+++ b/sys/dev/ic/ahcisata_core.c        Tue Jul 27 22:07:50 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ahcisata_core.c,v 1.28 2010/07/20 19:24:11 jakllsch Exp $      */
+/*     $NetBSD: ahcisata_core.c,v 1.29 2010/07/27 22:07:50 jakllsch Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.28 2010/07/20 19:24:11 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.29 2010/07/27 22:07:50 jakllsch Exp $");
 
 #include <sys/types.h>
 #include <sys/malloc.h>
@@ -54,39 +54,39 @@
 int ahcidebug_mask = 0x0;
 #endif
 
-void ahci_probe_drive(struct ata_channel *);
-void ahci_setup_channel(struct ata_channel *);
+static void ahci_probe_drive(struct ata_channel *);
+static void ahci_setup_channel(struct ata_channel *);
 
-int  ahci_ata_bio(struct ata_drive_datas *, struct ata_bio *);
-void ahci_reset_drive(struct ata_drive_datas *, int);
-void ahci_reset_channel(struct ata_channel *, int);
-int  ahci_exec_command(struct ata_drive_datas *, struct ata_command *);
-int  ahci_ata_addref(struct ata_drive_datas *);
-void ahci_ata_delref(struct ata_drive_datas *);
-void ahci_killpending(struct ata_drive_datas *);
+static int  ahci_ata_bio(struct ata_drive_datas *, struct ata_bio *);
+static void ahci_reset_drive(struct ata_drive_datas *, int);
+static void ahci_reset_channel(struct ata_channel *, int);
+static int  ahci_exec_command(struct ata_drive_datas *, struct ata_command *);
+static int  ahci_ata_addref(struct ata_drive_datas *);
+static void ahci_ata_delref(struct ata_drive_datas *);
+static void ahci_killpending(struct ata_drive_datas *);
 
-void ahci_cmd_start(struct ata_channel *, struct ata_xfer *);
-int  ahci_cmd_complete(struct ata_channel *, struct ata_xfer *, int);
-void ahci_cmd_done(struct ata_channel *, struct ata_xfer *, int);
-void ahci_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;
-void ahci_bio_start(struct ata_channel *, struct ata_xfer *);
-int  ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int);
-void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;
-void ahci_channel_stop(struct ahci_softc *, struct ata_channel *, int);
-void ahci_channel_start(struct ahci_softc *, struct ata_channel *);
-void ahci_timeout(void *);
-int  ahci_dma_setup(struct ata_channel *, int, void *, size_t, int);
+static void ahci_cmd_start(struct ata_channel *, struct ata_xfer *);
+static int  ahci_cmd_complete(struct ata_channel *, struct ata_xfer *, int);
+static void ahci_cmd_done(struct ata_channel *, struct ata_xfer *, int);
+static void ahci_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;
+static void ahci_bio_start(struct ata_channel *, struct ata_xfer *);
+static int  ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int);
+static void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;
+static void ahci_channel_stop(struct ahci_softc *, struct ata_channel *, int);
+static void ahci_channel_start(struct ahci_softc *, struct ata_channel *);
+static void ahci_timeout(void *);
+static int  ahci_dma_setup(struct ata_channel *, int, void *, size_t, int);
 
 #if NATAPIBUS > 0
-void ahci_atapibus_attach(struct atabus_softc *);
-void ahci_atapi_kill_pending(struct scsipi_periph *);
-void ahci_atapi_minphys(struct buf *);
-void ahci_atapi_scsipi_request(struct scsipi_channel *,
+static void ahci_atapibus_attach(struct atabus_softc *);
+static void ahci_atapi_kill_pending(struct scsipi_periph *);
+static void ahci_atapi_minphys(struct buf *);
+static void ahci_atapi_scsipi_request(struct scsipi_channel *,
     scsipi_adapter_req_t, void *);
-void ahci_atapi_start(struct ata_channel *, struct ata_xfer *);
-int  ahci_atapi_complete(struct ata_channel *, struct ata_xfer *, int);
-void ahci_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
-void ahci_atapi_probe_device(struct atapibus_softc *, int);
+static void ahci_atapi_start(struct ata_channel *, struct ata_xfer *);
+static int  ahci_atapi_complete(struct ata_channel *, struct ata_xfer *, int);
+static void ahci_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
+static void ahci_atapi_probe_device(struct atapibus_softc *, int);
 
 static const struct scsipi_bustype ahci_atapi_bustype = {
        SCSIPI_BUSTYPE_ATAPI,
@@ -113,11 +113,10 @@
        ahci_killpending
 };
 
-void ahci_intr_port(struct ahci_softc *, struct ahci_channel *);
-
+static void ahci_intr_port(struct ahci_softc *, struct ahci_channel *);
 static void ahci_setup_port(struct ahci_softc *sc, int i);
 
-int
+static int
 ahci_reset(struct ahci_softc *sc)
 {
        int i;
@@ -139,7 +138,7 @@
        return 0;
 }
 
-void
+static void
 ahci_setup_ports(struct ahci_softc *sc)
 {
        uint32_t ahci_ports;
@@ -158,7 +157,7 @@
        }
 }
 
-void
+static void
 ahci_reprobe_drives(struct ahci_softc *sc)
 {
        uint32_t ahci_ports;
@@ -195,7 +194,7 @@
        AHCI_WRITE(sc, AHCI_P_FBU(i), (uint64_t)achp->ahcic_bus_rfis>>32);
 }
 
-void
+static void
 ahci_enable_intrs(struct ahci_softc *sc)
 {
 
@@ -213,8 +212,6 @@
        struct ahci_channel *achp;
        struct ata_channel *chp;
        int error;
-       bus_dma_segment_t seg;
-       int rseg;
        int dmasize;
        void *cmdhp;
        void *cmdtblp;
@@ -261,13 +258,14 @@
        dmasize =
            (AHCI_RFIS_SIZE + AHCI_CMDH_SIZE) * sc->sc_atac.atac_nchannels;
        error = bus_dmamem_alloc(sc->sc_dmat, dmasize, PAGE_SIZE, 0,
-           &seg, 1, &rseg, BUS_DMA_NOWAIT);
+           &sc->sc_cmd_hdr_seg, 1, &sc->sc_cmd_hdr_nseg, BUS_DMA_NOWAIT);
        if (error) {
                aprint_error("%s: unable to allocate command header memory"
                    ", error=%d\n", AHCINAME(sc), error);
                return;
        }
-       error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, dmasize,
+       error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_hdr_seg,
+           sc->sc_cmd_hdr_nseg, dmasize,
            &cmdhp, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
        if (error) {
                aprint_error("%s: unable to map command header memory"
@@ -302,7 +300,7 @@
                        break;
                }
                achp = &sc->sc_channels[i];
-               chp = (struct ata_channel *)achp;
+               chp = &achp->ata_channel;
                sc->sc_chanarray[i] = chp;
                chp->ch_channel = i;
                chp->ch_atac = &sc->sc_atac;
@@ -315,13 +313,15 @@
                }
                dmasize = AHCI_CMDTBL_SIZE * sc->sc_ncmds;
                error = bus_dmamem_alloc(sc->sc_dmat, dmasize, PAGE_SIZE, 0,
-                   &seg, 1, &rseg, BUS_DMA_NOWAIT);
+                   &achp->ahcic_cmd_tbl_seg, 1, &achp->ahcic_cmd_tbl_nseg,
+                   BUS_DMA_NOWAIT);
                if (error) {
                        aprint_error("%s: unable to allocate command table "
                            "memory, error=%d\n", AHCINAME(sc), error);
                        break;
                }
-               error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, dmasize,
+               error = bus_dmamem_map(sc->sc_dmat, &achp->ahcic_cmd_tbl_seg,
+                   achp->ahcic_cmd_tbl_nseg, dmasize,
                    &cmdtblp, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
                if (error) {
                        aprint_error("%s: unable to map command table memory"
@@ -409,6 +409,73 @@
 }
 
 int
+ahci_detach(struct ahci_softc *sc, int flags)
+{
+       struct atac_softc *atac;
+       struct ahci_channel *achp;
+       struct ata_channel *chp;
+       struct scsipi_adapter *adapt;
+       uint32_t ahci_ports;
+       int i, j;
+       int error;
+
+       atac = &sc->sc_atac;
+       adapt = &atac->atac_atapi_adapter._generic;
+
+       ahci_ports = AHCI_READ(sc, AHCI_PI);
+       for (i = 0; i < AHCI_MAX_PORTS; i++) {
+               achp = &sc->sc_channels[i];
+               chp = &achp->ata_channel;
+
+               if ((ahci_ports & (1 << i)) == 0)
+                       continue;
+               if (i >= sc->sc_atac.atac_nchannels) {
+                       aprint_error("%s: more ports than announced\n",
+                           AHCINAME(sc));
+                       break;
+               }
+
+               if (chp->atabus == NULL)
+                       continue;
+               if ((error = config_detach(chp->atabus, flags)) != 0)
+                       return error;
+
+               for (j = 0; j < sc->sc_ncmds; j++)
+                       bus_dmamap_destroy(sc->sc_dmat, achp->ahcic_datad[j]);
+
+               bus_dmamap_unload(sc->sc_dmat, achp->ahcic_cmd_tbld);
+               bus_dmamap_destroy(sc->sc_dmat, achp->ahcic_cmd_tbld);
+               bus_dmamem_unmap(sc->sc_dmat, achp->ahcic_cmd_tbl[0],
+                   AHCI_CMDTBL_SIZE * sc->sc_ncmds);
+               bus_dmamem_free(sc->sc_dmat, &achp->ahcic_cmd_tbl_seg,
+                   achp->ahcic_cmd_tbl_nseg);
+
+               free(chp->ch_queue, M_DEVBUF);
+               chp->atabus = NULL;
+       }
+
+       bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_hdrd);
+       bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmd_hdrd);
+       bus_dmamem_unmap(sc->sc_dmat, sc->sc_cmd_hdr,
+           (AHCI_RFIS_SIZE + AHCI_CMDH_SIZE) * sc->sc_atac.atac_nchannels);
+       bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_hdr_seg, sc->sc_cmd_hdr_nseg);
+
+       if (adapt->adapt_refcnt != 0)
+               return EBUSY;
+
+       return 0;
+}
+
+void
+ahci_resume(struct ahci_softc *sc)
+{
+       ahci_reset(sc);
+       ahci_setup_ports(sc);
+       ahci_reprobe_drives(sc);
+       ahci_enable_intrs(sc);
+}
+
+int
 ahci_intr(void *v)
 {
        struct ahci_softc *sc = v;
@@ -427,7 +494,7 @@
        return r;
 }
 
-void
+static void
 ahci_intr_port(struct ahci_softc *sc, struct ahci_channel *achp)
 {
        uint32_t is, tfd;
@@ -483,7 +550,7 @@
        }
 }
 
-void
+static void
 ahci_reset_drive(struct ata_drive_datas *drvp, int flags)
 {
        struct ata_channel *chp = drvp->chnl_softc;
@@ -491,7 +558,7 @@
        return;
 }
 
-void
+static void
 ahci_reset_channel(struct ata_channel *chp, int flags)
 {
        struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
@@ -532,25 +599,25 @@
        return;
 }
 
-int
+static int
 ahci_ata_addref(struct ata_drive_datas *drvp)
 {
        return 0;
 }
 
-void
+static void
 ahci_ata_delref(struct ata_drive_datas *drvp)
 {
        return;
 }
 
-void



Home | Main Index | Thread Index | Old Index