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