Module Name: src
Committed By: jakllsch
Date: Tue Jul 27 22:07:51 UTC 2010
Modified Files:
src/sys/dev/ic: ahcisata_core.c ahcisatavar.h
src/sys/dev/pci: ahcisata_pci.c jmide.c
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/sys/dev/ic/ahcisata_core.c
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/ic/ahcisatavar.h
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/pci/ahcisata_pci.c
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/pci/jmide.c
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.28 src/sys/dev/ic/ahcisata_core.c:1.29
--- src/sys/dev/ic/ahcisata_core.c:1.28 Tue Jul 20 19:24:11 2010
+++ src/sys/dev/ic/ahcisata_core.c Tue Jul 27 22:07:50 2010
@@ -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 *);
-
-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 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 *);
+
+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
+static void
ahci_killpending(struct ata_drive_datas *drvp)
{
return;
}
-void
+static void
ahci_probe_drive(struct ata_channel *chp)
{
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
@@ -622,13 +689,13 @@
}
}
-void
+static void
ahci_setup_channel(struct ata_channel *chp)
{
return;
}
-int
+static int
ahci_exec_command(struct ata_drive_datas *drvp, struct ata_command *ata_c)
{
struct ata_channel *chp = drvp->chnl_softc;
@@ -679,7 +746,7 @@
return ret;
}
-void
+static void
ahci_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer)
{
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
@@ -762,7 +829,7 @@
AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
}
-void
+static void
ahci_cmd_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)
{
struct ata_command *ata_c = xfer->c_cmd;
@@ -783,7 +850,7 @@
ahci_cmd_done(chp, xfer, 0 /* XXX slot */);
}
-int
+static int
ahci_cmd_complete(struct ata_channel *chp, struct ata_xfer *xfer, int is)
{
int slot = 0; /* XXX slot */
@@ -824,7 +891,7 @@
return 0;
}
-void
+static void
ahci_cmd_done(struct ata_channel *chp, struct ata_xfer *xfer, int slot)
{
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
@@ -872,7 +939,7 @@
return;
}
-int
+static int
ahci_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
{
struct ata_channel *chp = drvp->chnl_softc;
@@ -899,7 +966,7 @@
return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED;
}
-void
+static void
ahci_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
{
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
@@ -981,7 +1048,7 @@
AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
}
-void
+static void
ahci_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)
{
int slot = 0; /* XXX slot */
@@ -1009,7 +1076,7 @@
(*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc);
}
-int
+static int
ahci_bio_complete(struct ata_channel *chp, struct ata_xfer *xfer, int is)
{
int slot = 0; /* XXX slot */
@@ -1071,7 +1138,7 @@
return 0;
}
-void
+static void
ahci_channel_stop(struct ahci_softc *sc, struct ata_channel *chp, int flags)
{
int i;
@@ -1095,7 +1162,7 @@
}
}
-void
+static void
ahci_channel_start(struct ahci_softc *sc, struct ata_channel *chp)
{
/* clear error */
@@ -1108,7 +1175,7 @@
AHCI_P_CMD_FRE | AHCI_P_CMD_ST);
}
-void
+static void
ahci_timeout(void *v)
{
struct ata_channel *chp = (struct ata_channel *)v;
@@ -1122,7 +1189,7 @@
splx(s);
}
-int
+static int
ahci_dma_setup(struct ata_channel *chp, int slot, void *data,
size_t count, int op)
{
@@ -1165,7 +1232,7 @@
}
#if NATAPIBUS > 0
-void
+static void
ahci_atapibus_attach(struct atabus_softc * ata_sc)
{
struct ata_channel *chp = ata_sc->sc_chan;
@@ -1197,7 +1264,7 @@
atapiprint);
}
-void
+static void
ahci_atapi_minphys(struct buf *bp)
{
if (bp->b_bcount > MAXPHYS)
@@ -1210,7 +1277,7 @@
*
* Must be called at splbio().
*/
-void
+static void
ahci_atapi_kill_pending(struct scsipi_periph *periph)
{
struct atac_softc *atac =
@@ -1221,7 +1288,7 @@
ata_kill_pending(&chp->ch_drive[periph->periph_target]);
}
-void
+static void
ahci_atapi_scsipi_request(struct scsipi_channel *chan,
scsipi_adapter_req_t req, void *arg)
{
@@ -1278,7 +1345,7 @@
}
}
-void
+static void
ahci_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
{
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
@@ -1360,7 +1427,7 @@
AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
}
-int
+static int
ahci_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
{
int slot = 0; /* XXX slot */
@@ -1419,7 +1486,7 @@
return 0;
}
-void
+static void
ahci_atapi_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)
{
struct scsipi_xfer *sc_xfer = xfer->c_cmd;
@@ -1444,7 +1511,7 @@
scsipi_done(sc_xfer);
}
-void
+static void
ahci_atapi_probe_device(struct atapibus_softc *sc, int target)
{
struct scsipi_channel *chan = sc->sc_channel;
Index: src/sys/dev/ic/ahcisatavar.h
diff -u src/sys/dev/ic/ahcisatavar.h:1.6 src/sys/dev/ic/ahcisatavar.h:1.7
--- src/sys/dev/ic/ahcisatavar.h:1.6 Tue Jul 20 18:50:48 2010
+++ src/sys/dev/ic/ahcisatavar.h Tue Jul 27 22:07:50 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisatavar.h,v 1.6 2010/07/20 18:50:48 jakllsch Exp $ */
+/* $NetBSD: ahcisatavar.h,v 1.7 2010/07/27 22:07:50 jakllsch Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -47,9 +47,12 @@
struct atac_softc sc_atac;
bus_space_tag_t sc_ahcit; /* ahci registers mapping */
bus_space_handle_t sc_ahcih;
+ bus_size_t sc_ahcis;
bus_dma_tag_t sc_dmat; /* DMA memory mappings: */
void *sc_cmd_hdr; /* command tables and received FIS */
bus_dmamap_t sc_cmd_hdrd;
+ bus_dma_segment_t sc_cmd_hdr_seg;
+ int sc_cmd_hdr_nseg;
int sc_atac_capflags;
int sc_ncmds; /* number of command slots */
@@ -66,6 +69,8 @@
bus_addr_t ahcic_bus_cmdh;
/* command tables (allocated per-channel) */
bus_dmamap_t ahcic_cmd_tbld;
+ bus_dma_segment_t ahcic_cmd_tbl_seg;
+ int ahcic_cmd_tbl_nseg;
struct ahci_cmd_tbl *ahcic_cmd_tbl[AHCI_MAX_CMDS];
bus_addr_t ahcic_bus_cmd_tbl[AHCI_MAX_CMDS];
bus_dmamap_t ahcic_datad[AHCI_MAX_CMDS];
@@ -93,10 +98,8 @@
void ahci_attach(struct ahci_softc *);
-void ahci_enable_intrs(struct ahci_softc *);
-int ahci_reset(struct ahci_softc *);
-void ahci_setup_ports(struct ahci_softc *);
-void ahci_reprobe_drives(struct ahci_softc *);
+int ahci_detach(struct ahci_softc *, int);
+void ahci_resume(struct ahci_softc *);
int ahci_intr(void *);
Index: src/sys/dev/pci/ahcisata_pci.c
diff -u src/sys/dev/pci/ahcisata_pci.c:1.19 src/sys/dev/pci/ahcisata_pci.c:1.20
--- src/sys/dev/pci/ahcisata_pci.c:1.19 Wed Feb 24 22:37:59 2010
+++ src/sys/dev/pci/ahcisata_pci.c Tue Jul 27 22:07:51 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisata_pci.c,v 1.19 2010/02/24 22:37:59 dyoung Exp $ */
+/* $NetBSD: ahcisata_pci.c,v 1.20 2010/07/27 22:07:51 jakllsch Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.19 2010/02/24 22:37:59 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.20 2010/07/27 22:07:51 jakllsch Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -44,9 +44,15 @@
#include <dev/pci/pciidevar.h>
#include <dev/ic/ahcisatavar.h>
-#define AHCI_PCI_QUIRK_FORCE 1 /* force attach */
+struct ahci_pci_quirk {
+ pci_vendor_id_t vendor; /* Vendor ID */
+ pci_product_id_t product; /* Product ID */
+ int quirks; /* quirks; see below */
+};
+
+#define AHCI_PCI_QUIRK_FORCE __BIT(0) /* force attach */
-static const struct pci_quirkdata ahci_pci_quirks[] = {
+static const struct ahci_pci_quirk ahci_pci_quirks[] = {
{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_SATA,
AHCI_PCI_QUIRK_FORCE },
{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_SATA2,
@@ -67,18 +73,30 @@
struct ahci_softc ah_sc;
pci_chipset_tag_t sc_pc;
pcitag_t sc_pcitag;
+ void * sc_ih;
};
-
+static bool ahci_pci_has_quirk(pci_vendor_id_t, pci_product_id_t, int);
static int ahci_pci_match(device_t, cfdata_t, void *);
static void ahci_pci_attach(device_t, device_t, void *);
-const struct pci_quirkdata *ahci_pci_lookup_quirkdata(pci_vendor_id_t,
- pci_product_id_t);
+static int ahci_pci_detach(device_t, int);
static bool ahci_pci_resume(device_t, const pmf_qual_t *);
CFATTACH_DECL_NEW(ahcisata_pci, sizeof(struct ahci_pci_softc),
- ahci_pci_match, ahci_pci_attach, NULL, NULL);
+ ahci_pci_match, ahci_pci_attach, ahci_pci_detach, NULL);
+
+static bool
+ahci_pci_has_quirk(pci_vendor_id_t vendor, pci_product_id_t product, int quirk)
+{
+ int i;
+
+ for (i = 0; i < __arraycount(ahci_pci_quirks); i++)
+ if (vendor == ahci_pci_quirks[i].vendor &&
+ product == ahci_pci_quirks[i].product)
+ return (ahci_pci_quirks[i].quirks & quirk) != 0;
+ return false;
+}
static int
ahci_pci_match(device_t parent, cfdata_t match, void *aux)
@@ -88,17 +106,18 @@
bus_space_handle_t regh;
bus_size_t size;
int ret = 0;
- const struct pci_quirkdata *quirks;
+ bool force;
- quirks = ahci_pci_lookup_quirkdata(PCI_VENDOR(pa->pa_id),
- PCI_PRODUCT(pa->pa_id));
+ force = ahci_pci_has_quirk(PCI_VENDOR(pa->pa_id),
+ PCI_PRODUCT(pa->pa_id),
+ AHCI_PCI_QUIRK_FORCE);
/* if wrong class and not forced by quirks, don't match */
if ((PCI_CLASS(pa->pa_class) != PCI_CLASS_MASS_STORAGE ||
((PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MASS_STORAGE_SATA ||
PCI_INTERFACE(pa->pa_class) != PCI_INTERFACE_SATA_AHCI) &&
PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MASS_STORAGE_RAID)) &&
- (quirks == NULL || (quirks->quirks & AHCI_PCI_QUIRK_FORCE) == 0))
+ (force == false))
return 0;
if (pci_mapreg_map(pa, AHCI_PCI_ABAR,
@@ -108,8 +127,8 @@
if ((PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_SATA &&
PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_SATA_AHCI) ||
- (quirks && quirks->quirks & AHCI_PCI_QUIRK_FORCE) ||
- (bus_space_read_4(regt, regh, AHCI_GHC) & AHCI_GHC_AE))
+ (bus_space_read_4(regt, regh, AHCI_GHC) & AHCI_GHC_AE) ||
+ (force == true))
ret = 3;
bus_space_unmap(regt, regh, size);
@@ -122,17 +141,15 @@
struct pci_attach_args *pa = aux;
struct ahci_pci_softc *psc = device_private(self);
struct ahci_softc *sc = &psc->ah_sc;
- bus_size_t size;
char devinfo[256];
const char *intrstr;
pci_intr_handle_t intrhandle;
- void *ih;
sc->sc_atac.atac_dev = self;
if (pci_mapreg_map(pa, AHCI_PCI_ABAR,
PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
- &sc->sc_ahcit, &sc->sc_ahcih, NULL, &size) != 0) {
+ &sc->sc_ahcit, &sc->sc_ahcih, NULL, &sc->sc_ahcis) != 0) {
aprint_error_dev(self, "can't map ahci registers\n");
return;
}
@@ -144,16 +161,16 @@
aprint_normal(": %s\n", devinfo);
if (pci_intr_map(pa, &intrhandle) != 0) {
- aprint_error("%s: couldn't map interrupt\n", AHCINAME(sc));
+ aprint_error_dev(self, "couldn't map interrupt\n");
return;
}
intrstr = pci_intr_string(pa->pa_pc, intrhandle);
- ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, ahci_intr, sc);
- if (ih == NULL) {
- aprint_error("%s: couldn't establish interrupt", AHCINAME(sc));
+ psc->sc_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, ahci_intr, sc);
+ if (psc->sc_ih == NULL) {
+ aprint_error_dev(self, "couldn't establish interrupt\n");
return;
}
- aprint_normal("%s: interrupting at %s\n", AHCINAME(sc),
+ aprint_normal_dev(self, "interrupting at %s\n",
intrstr ? intrstr : "unknown interrupt");
sc->sc_dmat = pa->pa_dmat;
@@ -170,6 +187,27 @@
aprint_error_dev(self, "couldn't establish power handler\n");
}
+static int
+ahci_pci_detach(device_t dv, int flags)
+{
+ struct ahci_pci_softc *psc;
+ struct ahci_softc *sc;
+ int rv;
+
+ psc = device_private(dv);
+ sc = &psc->ah_sc;
+
+ if ((rv = ahci_detach(sc, flags)))
+ return rv;
+
+ if (psc->sc_ih != NULL)
+ pci_intr_disestablish(psc->sc_pc, psc->sc_ih);
+
+ bus_space_unmap(sc->sc_ahcit, sc->sc_ahcih, sc->sc_ahcis);
+
+ return 0;
+}
+
static bool
ahci_pci_resume(device_t dv, const pmf_qual_t *qual)
{
@@ -178,23 +216,8 @@
int s;
s = splbio();
- ahci_reset(sc);
- ahci_setup_ports(sc);
- ahci_reprobe_drives(sc);
- ahci_enable_intrs(sc);
+ ahci_resume(sc);
splx(s);
return true;
}
-
-const struct pci_quirkdata *
-ahci_pci_lookup_quirkdata(pci_vendor_id_t vendor, pci_product_id_t product)
-{
- int i;
-
- for (i = 0; i < __arraycount(ahci_pci_quirks); i++)
- if (vendor == ahci_pci_quirks[i].vendor &&
- product == ahci_pci_quirks[i].product)
- return (&ahci_pci_quirks[i]);
- return (NULL);
-}
Index: src/sys/dev/pci/jmide.c
diff -u src/sys/dev/pci/jmide.c:1.7 src/sys/dev/pci/jmide.c:1.8
--- src/sys/dev/pci/jmide.c:1.7 Mon Oct 19 18:41:15 2009
+++ src/sys/dev/pci/jmide.c Tue Jul 27 22:07:51 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: jmide.c,v 1.7 2009/10/19 18:41:15 bouyer Exp $ */
+/* $NetBSD: jmide.c,v 1.8 2010/07/27 22:07:51 jakllsch Exp $ */
/*
* Copyright (c) 2007 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: jmide.c,v 1.7 2009/10/19 18:41:15 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: jmide.c,v 1.8 2010/07/27 22:07:51 jakllsch Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -431,9 +431,11 @@
#ifdef NJMAHCI
static int jmahci_match(device_t, cfdata_t, void *);
static void jmahci_attach(device_t, device_t, void *);
+static int jmahci_detach(device_t, int);
+static bool jmahci_resume(device_t, const pmf_qual_t *);
CFATTACH_DECL_NEW(jmahci, sizeof(struct ahci_softc),
- jmahci_match, jmahci_attach, NULL, NULL);
+ jmahci_match, jmahci_attach, jmahci_detach, NULL);
static int
jmahci_match(device_t parent, cfdata_t match, void *aux)
@@ -447,6 +449,7 @@
struct jmahci_attach_args *jma = aux;
struct pci_attach_args *pa = jma->jma_pa;
struct ahci_softc *sc = device_private(self);
+ uint32_t ahci_cap;
aprint_naive(": AHCI disk controller\n");
aprint_normal("\n");
@@ -454,11 +457,49 @@
sc->sc_atac.atac_dev = self;
sc->sc_ahcit = jma->jma_ahcit;
sc->sc_ahcih = jma->jma_ahcih;
- sc->sc_dmat = jma->jma_pa->pa_dmat;
+
+ ahci_cap = AHCI_READ(sc, AHCI_CAP);
+
+ if (pci_dma64_available(jma->jma_pa) && (ahci_cap & AHCI_CAP_64BIT))
+ sc->sc_dmat = jma->jma_pa->pa_dmat64;
+ else
+ sc->sc_dmat = jma->jma_pa->pa_dmat;
if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID)
sc->sc_atac_capflags = ATAC_CAP_RAID;
ahci_attach(sc);
+
+ if (!pmf_device_register(self, NULL, jmahci_resume))
+ aprint_error_dev(self, "couldn't establish power handler\n");
+}
+
+static int
+jmahci_detach(device_t dv, int flags)
+{
+ struct ahci_softc *sc;
+ sc = device_private(dv);
+
+ int rv;
+
+ if ((rv = ahci_detach(sc, flags)))
+ return rv;
+
+ return 0;
+}
+
+static bool
+jmahci_resume(device_t dv, const pmf_qual_t *qual)
+{
+ struct ahci_softc *sc;
+ int s;
+
+ sc = device_private(dv);
+
+ s = splbio();
+ ahci_resume(sc);
+ splx(s);
+
+ return true;
}
#endif