static bool ahci_pci_resume(device_t dv PMF_FN_ARGS) { struct ahci_pci_softc *psc = device_private(dv); struct ahci_softc *sc = &psc->ah_sc; int s; s = splbio(); ahci_reset(sc); ahci_setup_ports(sc); ahci_reprobe_drives(sc); ahci_enable_intrs(sc); splx(s); return true; }
static void pci_ich9_reset(DeviceState *dev) { struct AHCIPCIState *d = DO_UPCAST(struct AHCIPCIState, card.qdev, dev); ahci_reset(&d->ahci); }
void arch_preboot_os(void) { ahci_reset((void __iomem *)DWC_AHSATA_BASE); }
static void pci_ich9_reset(DeviceState *dev) { AHCIPCIState *d = ICH_AHCI(dev); ahci_reset(&d->ahci); }
void ahci_attach(struct ahci_softc *sc) { u_int32_t ahci_cap, ahci_rev, ahci_ports; int i, j, port; struct ahci_channel *achp; struct ata_channel *chp; int error; bus_dma_segment_t seg; int rseg; int dmasize; void *cmdhp; void *cmdtblp; if (ahci_reset(sc) != 0) return; ahci_cap = AHCI_READ(sc, AHCI_CAP); sc->sc_atac.atac_nchannels = (ahci_cap & AHCI_CAP_NPMASK) + 1; sc->sc_ncmds = ((ahci_cap & AHCI_CAP_NCS) >> 8) + 1; ahci_rev = AHCI_READ(sc, AHCI_VS); aprint_normal("%s: AHCI revision ", AHCINAME(sc)); switch(ahci_rev) { case AHCI_VS_10: aprint_normal("1.0"); break; case AHCI_VS_11: aprint_normal("1.1"); break; case AHCI_VS_12: aprint_normal("1.2"); break; default: aprint_normal("0x%x", ahci_rev); break; } aprint_normal(", %d ports, %d command slots, features 0x%x\n", sc->sc_atac.atac_nchannels, sc->sc_ncmds, ahci_cap & ~(AHCI_CAP_NPMASK|AHCI_CAP_NCS)); sc->sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DMA | ATAC_CAP_UDMA; sc->sc_atac.atac_cap |= sc->sc_atac_capflags; sc->sc_atac.atac_pio_cap = 4; sc->sc_atac.atac_dma_cap = 2; sc->sc_atac.atac_udma_cap = 6; sc->sc_atac.atac_channels = sc->sc_chanarray; sc->sc_atac.atac_probe = ahci_probe_drive; sc->sc_atac.atac_bustype_ata = &ahci_ata_bustype; sc->sc_atac.atac_set_modes = ahci_setup_channel; #if NATAPIBUS > 0 sc->sc_atac.atac_atapibus_attach = ahci_atapibus_attach; #endif 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); 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, &cmdhp, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); if (error) { aprint_error("%s: unable to map command header memory" ", error=%d\n", AHCINAME(sc), error); return; } error = bus_dmamap_create(sc->sc_dmat, dmasize, 1, dmasize, 0, BUS_DMA_NOWAIT, &sc->sc_cmd_hdrd); if (error) { aprint_error("%s: unable to create command header map" ", error=%d\n", AHCINAME(sc), error); return; } error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmd_hdrd, cmdhp, dmasize, NULL, BUS_DMA_NOWAIT); if (error) { aprint_error("%s: unable to load command header map" ", error=%d\n", AHCINAME(sc), error); return; } sc->sc_cmd_hdr = cmdhp; ahci_enable_intrs(sc); ahci_ports = AHCI_READ(sc, AHCI_PI); for (i = 0, port = 0; i < AHCI_MAX_PORTS; i++) { if ((ahci_ports & (1 << i)) == 0) continue; if (port >= sc->sc_atac.atac_nchannels) { aprint_error("%s: more ports than announced\n", AHCINAME(sc)); break; } achp = &sc->sc_channels[i]; chp = (struct ata_channel *)achp; sc->sc_chanarray[i] = chp; chp->ch_channel = i; chp->ch_atac = &sc->sc_atac; chp->ch_queue = malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); if (chp->ch_queue == NULL) { aprint_error("%s port %d: can't allocate memory for " "command queue", AHCINAME(sc), i); break; } dmasize = AHCI_CMDTBL_SIZE * sc->sc_ncmds; error = bus_dmamem_alloc(sc->sc_dmat, dmasize, PAGE_SIZE, 0, &seg, 1, &rseg, 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, &cmdtblp, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); if (error) { aprint_error("%s: unable to map command table memory" ", error=%d\n", AHCINAME(sc), error); break; } error = bus_dmamap_create(sc->sc_dmat, dmasize, 1, dmasize, 0, BUS_DMA_NOWAIT, &achp->ahcic_cmd_tbld); if (error) { aprint_error("%s: unable to create command table map" ", error=%d\n", AHCINAME(sc), error); break; } error = bus_dmamap_load(sc->sc_dmat, achp->ahcic_cmd_tbld, cmdtblp, dmasize, NULL, BUS_DMA_NOWAIT); if (error) { aprint_error("%s: unable to load command table map" ", error=%d\n", AHCINAME(sc), error); break; } achp->ahcic_cmdh = (struct ahci_cmd_header *) ((char *)cmdhp + AHCI_CMDH_SIZE * port); achp->ahcic_bus_cmdh = sc->sc_cmd_hdrd->dm_segs[0].ds_addr + AHCI_CMDH_SIZE * port; achp->ahcic_rfis = (struct ahci_r_fis *) ((char *)cmdhp + AHCI_CMDH_SIZE * sc->sc_atac.atac_nchannels + AHCI_RFIS_SIZE * port); achp->ahcic_bus_rfis = sc->sc_cmd_hdrd->dm_segs[0].ds_addr + AHCI_CMDH_SIZE * sc->sc_atac.atac_nchannels + AHCI_RFIS_SIZE * port; AHCIDEBUG_PRINT(("port %d cmdh %p (0x%x) rfis %p (0x%x)\n", i, achp->ahcic_cmdh, (u_int)achp->ahcic_bus_cmdh, achp->ahcic_rfis, (u_int)achp->ahcic_bus_rfis), DEBUG_PROBE); for (j = 0; j < sc->sc_ncmds; j++) { achp->ahcic_cmd_tbl[j] = (struct ahci_cmd_tbl *) ((char *)cmdtblp + AHCI_CMDTBL_SIZE * j); achp->ahcic_bus_cmd_tbl[j] = achp->ahcic_cmd_tbld->dm_segs[0].ds_addr + AHCI_CMDTBL_SIZE * j; achp->ahcic_cmdh[j].cmdh_cmdtba = htole32(achp->ahcic_bus_cmd_tbl[j]); achp->ahcic_cmdh[j].cmdh_cmdtbau = htole32(0); AHCIDEBUG_PRINT(("port %d/%d tbl %p (0x%x)\n", i, j, achp->ahcic_cmd_tbl[j], (u_int)achp->ahcic_bus_cmd_tbl[j]), DEBUG_PROBE); /* The xfer DMA map */ error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, AHCI_NPRD, 0x400000 /* 4MB */, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &achp->ahcic_datad[j]); if (error) { aprint_error("%s: couldn't alloc xfer DMA map, " "error=%d\n", AHCINAME(sc), error); goto end; } } ahci_setup_port(sc, i); chp->ch_ndrive = 1; if (bus_space_subregion(sc->sc_ahcit, sc->sc_ahcih, AHCI_P_SSTS(i), 1, &achp->ahcic_sstatus) != 0) { aprint_error("%s: couldn't map channel %d " "sata_status regs\n", AHCINAME(sc), i); break; } if (bus_space_subregion(sc->sc_ahcit, sc->sc_ahcih, AHCI_P_SCTL(i), 1, &achp->ahcic_scontrol) != 0) { aprint_error("%s: couldn't map channel %d " "sata_control regs\n", AHCINAME(sc), i); break; } if (bus_space_subregion(sc->sc_ahcit, sc->sc_ahcih, AHCI_P_SERR(i), 1, &achp->ahcic_serror) != 0) { aprint_error("%s: couldn't map channel %d " "sata_error regs\n", AHCINAME(sc), i); break; } ata_channel_attach(chp); port++; end: continue; } }