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