static void via_mapchan(const struct pci_attach_args *pa, struct pciide_channel *cp, pcireg_t interface, int (*pci_intr)(void *)) { struct ata_channel *wdc_cp; struct pciide_softc *sc; prop_bool_t compat_nat_enable; wdc_cp = &cp->ata_channel; sc = CHAN_TO_PCIIDE(&cp->ata_channel); compat_nat_enable = prop_dictionary_get( device_properties(sc->sc_wdcdev.sc_atac.atac_dev), "use-compat-native-irq"); if (interface & PCIIDE_INTERFACE_PCI(wdc_cp->ch_channel)) { /* native mode with irq 14/15 requested? */ if (compat_nat_enable != NULL && prop_bool_true(compat_nat_enable)) via_mapregs_compat_native(pa, cp); else pciide_mapregs_native(pa, cp, pci_intr); } else { pciide_mapregs_compat(pa, cp, wdc_cp->ch_channel); if ((cp->ata_channel.ch_flags & ATACH_DISABLED) == 0) pciide_map_compat_intr(pa, cp, wdc_cp->ch_channel); } wdcattach(wdc_cp); }
/* * At least under certain (mis)configurations (e.g. on the "Pegasos" board) * the VT8231-IDE's native mode only works with irq 14/15, and cannot be * programmed to use a single native PCI irq alone. So we install an interrupt * handler for each channel, as in compatibility mode. */ static void via_mapregs_compat_native(const struct pci_attach_args *pa, struct pciide_channel *cp) { struct ata_channel *wdc_cp; struct pciide_softc *sc; wdc_cp = &cp->ata_channel; sc = CHAN_TO_PCIIDE(&cp->ata_channel); /* XXX prevent pciide_mapregs_native from installing a handler */ if (sc->sc_pci_ih == NULL) sc->sc_pci_ih = (void *)~0; pciide_mapregs_native(pa, cp, NULL); /* interrupts are fixed to 14/15, as in compatibility mode */ cp->compat = 1; if ((wdc_cp->ch_flags & ATACH_DISABLED) == 0) { #ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH cp->ih = pciide_machdep_compat_intr_establish( sc->sc_wdcdev.sc_atac.atac_dev, pa, wdc_cp->ch_channel, pciide_compat_intr, cp); if (cp->ih == NULL) { #endif aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "no compatibility interrupt for " "use by %s channel\n", cp->name); wdc_cp->ch_flags |= ATACH_DISABLED; #ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH } sc->sc_pci_ih = cp->ih; /* XXX */ #endif } }
static void stpc_setup_channel(struct ata_channel *chp) { struct atac_softc *atac = chp->ch_atac; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); int channel = chp->ch_channel; struct ata_drive_datas *drvp; u_int32_t idedma_ctl, idetim; int drive, bits[2], s; /* setup DMA if needed */ pciide_channel_dma_setup(cp); idedma_ctl = 0; bits[0] = bits[1] = 0x7F60; /* assume PIO2/DMA0 */ /* Per drive settings */ for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; /* add timing values, setup DMA if needed */ if ((atac->atac_cap & ATAC_CAP_DMA) && (drvp->drive_flags & ATA_DRIVE_DMA)) { /* use Multiword DMA */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_UDMA; splx(s); idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); bits[drive] = 0xe; /* IOCHRDY,wr/post,rd/prefetch */ } else { /* PIO only */ s = splbio(); drvp->drive_flags &= ~(ATA_DRIVE_UDMA | ATA_DRIVE_DMA); splx(s); bits[drive] = 0x8; /* IOCHRDY */ } bits[drive] |= dmatbl[drvp->DMA_mode] | piotbl[drvp->PIO_mode]; } #if 0 idetim = pci_conf_read(sc->sc_pc, sc->sc_tag, (channel == 0) ? 0x40 : 0x44); aprint_normal("wdc%d: IDETIM %08x -> %08x\n", channel, idetim, (bits[1] << 16) | bits[0]); #endif idetim = (bits[1] << 16) | bits[0]; pci_conf_write(sc->sc_pc, sc->sc_tag, (channel == 0) ? 0x40 : 0x44, idetim); if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } }
static void jmpata_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; int drive, s; u_int32_t idedma_ctl; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); struct jmide_softc *jmidesc = (struct jmide_softc *)sc; int ide80p; /* setup DMA if needed */ pciide_channel_dma_setup(cp); idedma_ctl = 0; /* cable type detect */ ide80p = 1; if (chp->ch_channel == (jmidesc->sc_chan_swap ? 1 : 0)) { if (jmidesc->sc_chan_type[chp->ch_channel] == TYPE_PATA && (pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_JM_CONTROL1) & JM_CONTROL1_PATA1_40P)) ide80p = 0; } else { if (jmidesc->sc_chan_type[chp->ch_channel] == TYPE_PATA && (pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_JM_CONTROL0) & JM_CONTROL0_PATA0_40P)) ide80p = 0; } for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; if (drvp->drive_flags & ATA_DRIVE_UDMA) { /* use Ultra/DMA */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_DMA; if (drvp->UDMA_mode > 2 && ide80p == 0) drvp->UDMA_mode = 2; splx(s); idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else if (drvp->drive_flags & ATA_DRIVE_DMA) { idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } } /* nothing to do to setup modes, the controller snoop SET_FEATURE cmd */ if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } }
static void acer_do_reset(struct ata_channel *chp, int poll) { struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); struct aceride_softc *acer_sc = (struct aceride_softc *)sc; u_int8_t reg; /* * From OpenSolaris: after a reset we need to disable/enable the * corresponding channel, or data corruption will occur in * UltraDMA modes */ wdc_do_reset(chp, poll); reg = pciide_pci_read(acer_sc->pcib_pa.pa_pc, acer_sc->pcib_pa.pa_tag, ACER_PCIB_CTRL); pciide_pci_write(acer_sc->pcib_pa.pa_pc, acer_sc->pcib_pa.pa_tag, ACER_PCIB_CTRL, reg & ~ACER_PCIB_CTRL_ENCHAN(chp->ch_channel)); delay(1000); pciide_pci_write(acer_sc->pcib_pa.pa_pc, acer_sc->pcib_pa.pa_tag, ACER_PCIB_CTRL, reg); }
static void via_setup_channel(struct ata_channel *chp) { u_int32_t udmatim_reg, datatim_reg; u_int8_t idedma_ctl; int mode, drive, s; struct ata_drive_datas *drvp; struct atac_softc *atac = chp->ch_atac; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); #ifndef PCIIDE_AMD756_ENABLEDMA int rev = PCI_REVISION( pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG)); #endif idedma_ctl = 0; datatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, APO_DATATIM(sc)); udmatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, APO_UDMA(sc)); datatim_reg &= ~APO_DATATIM_MASK(chp->ch_channel); udmatim_reg &= ~APO_UDMA_MASK(chp->ch_channel); /* setup DMA if needed */ pciide_channel_dma_setup(cp); for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; /* add timing values, setup DMA if needed */ if (((drvp->drive_flags & ATA_DRIVE_DMA) == 0 && (drvp->drive_flags & ATA_DRIVE_UDMA) == 0)) { mode = drvp->PIO_mode; goto pio; } if ((atac->atac_cap & ATAC_CAP_UDMA) && (drvp->drive_flags & ATA_DRIVE_UDMA)) { /* use Ultra/DMA */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_DMA; splx(s); udmatim_reg |= APO_UDMA_EN(chp->ch_channel, drive) | APO_UDMA_EN_MTH(chp->ch_channel, drive); switch (PCI_VENDOR(sc->sc_pci_id)) { case PCI_VENDOR_VIATECH: if (sc->sc_wdcdev.sc_atac.atac_udma_cap == 6) { /* 8233a */ udmatim_reg |= APO_UDMA_TIME( chp->ch_channel, drive, via_udma133_tim[drvp->UDMA_mode]); } else if (sc->sc_wdcdev.sc_atac.atac_udma_cap == 5) { /* 686b */ udmatim_reg |= APO_UDMA_TIME( chp->ch_channel, drive, via_udma100_tim[drvp->UDMA_mode]); } else if (sc->sc_wdcdev.sc_atac.atac_udma_cap == 4) { /* 596b or 686a */ udmatim_reg |= APO_UDMA_CLK66( chp->ch_channel); udmatim_reg |= APO_UDMA_TIME( chp->ch_channel, drive, via_udma66_tim[drvp->UDMA_mode]); } else { /* 596a or 586b */ udmatim_reg |= APO_UDMA_TIME( chp->ch_channel, drive, via_udma33_tim[drvp->UDMA_mode]); } break; case PCI_VENDOR_AMD: case PCI_VENDOR_NVIDIA: udmatim_reg |= APO_UDMA_TIME(chp->ch_channel, drive, amd7x6_udma_tim[drvp->UDMA_mode]); break; } /* can use PIO timings, MW DMA unused */ mode = drvp->PIO_mode; } else { /* use Multiword DMA, but only if revision is OK */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_UDMA; splx(s); #ifndef PCIIDE_AMD756_ENABLEDMA /* * The workaround doesn't seem to be necessary * with all drives, so it can be disabled by * PCIIDE_AMD756_ENABLEDMA. It causes a hard hang if * triggered. */ if (PCI_VENDOR(sc->sc_pci_id) == PCI_VENDOR_AMD && sc->sc_pp->ide_product == PCI_PRODUCT_AMD_PBC756_IDE && AMD756_CHIPREV_DISABLEDMA(rev)) { aprint_normal( "%s:%d:%d: multi-word DMA disabled due " "to chip revision\n", device_xname( sc->sc_wdcdev.sc_atac.atac_dev), chp->ch_channel, drive); mode = drvp->PIO_mode; s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_DMA; splx(s); goto pio; } #endif /* mode = min(pio, dma+2) */ if (drvp->PIO_mode <= (drvp->DMA_mode + 2)) mode = drvp->PIO_mode; else mode = drvp->DMA_mode + 2; } idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); pio: /* setup PIO mode */ if (mode <= 2) { drvp->DMA_mode = 0; drvp->PIO_mode = 0; mode = 0; } else { drvp->PIO_mode = mode; drvp->DMA_mode = mode - 2; } datatim_reg |= APO_DATATIM_PULSE(chp->ch_channel, drive, apollo_pio_set[mode]) | APO_DATATIM_RECOV(chp->ch_channel, drive, apollo_pio_rec[mode]); } if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } pci_conf_write(sc->sc_pc, sc->sc_tag, APO_DATATIM(sc), datatim_reg); pci_conf_write(sc->sc_pc, sc->sc_tag, APO_UDMA(sc), udmatim_reg); ATADEBUG_PRINT(("via_chip_map: APO_DATATIM=0x%x, APO_UDMA=0x%x\n", pci_conf_read(sc->sc_pc, sc->sc_tag, APO_DATATIM(sc)), pci_conf_read(sc->sc_pc, sc->sc_tag, APO_UDMA(sc))), DEBUG_PROBE); }
static void opti_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); int drive, spd, s; int mode[2]; u_int8_t rv, mr; /* * The `Delay' and `Address Setup Time' fields of the * Miscellaneous Register are always zero initially. */ mr = opti_read_config(chp, OPTI_REG_MISC) & ~OPTI_MISC_INDEX_MASK; mr &= ~(OPTI_MISC_DELAY_MASK | OPTI_MISC_ADDR_SETUP_MASK | OPTI_MISC_INDEX_MASK); /* Prime the control register before setting timing values */ opti_write_config(chp, OPTI_REG_CONTROL, OPTI_CONTROL_DISABLE); /* Determine the clockrate of the PCIbus the chip is attached to */ spd = (int) opti_read_config(chp, OPTI_REG_STRAP); spd &= OPTI_STRAP_PCI_SPEED_MASK; /* setup DMA if needed */ pciide_channel_dma_setup(cp); for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) { mode[drive] = -1; continue; } if ((drvp->drive_flags & ATA_DRIVE_DMA)) { /* * Timings will be used for both PIO and DMA, * so adjust DMA mode if needed */ if (drvp->PIO_mode > (drvp->DMA_mode + 2)) drvp->PIO_mode = drvp->DMA_mode + 2; if (drvp->DMA_mode + 2 > (drvp->PIO_mode)) drvp->DMA_mode = (drvp->PIO_mode > 2) ? drvp->PIO_mode - 2 : 0; if (drvp->DMA_mode == 0) drvp->PIO_mode = 0; mode[drive] = drvp->DMA_mode + 5; } else mode[drive] = drvp->PIO_mode; if (drive && mode[0] >= 0 && (opti_tim_as[spd][mode[0]] != opti_tim_as[spd][mode[1]])) { /* * Can't have two drives using different values * for `Address Setup Time'. * Slow down the faster drive to compensate. */ int d = (opti_tim_as[spd][mode[0]] > opti_tim_as[spd][mode[1]]) ? 0 : 1; mode[d] = mode[1-d]; chp->ch_drive[d].PIO_mode = chp->ch_drive[1-d].PIO_mode; chp->ch_drive[d].DMA_mode = 0; s = splbio(); chp->ch_drive[d].drive_flags &= ~ATA_DRIVE_DMA; splx(s); } } for (drive = 0; drive < 2; drive++) { int m; if ((m = mode[drive]) < 0) continue; /* Set the Address Setup Time and select appropriate index */ rv = opti_tim_as[spd][m] << OPTI_MISC_ADDR_SETUP_SHIFT; rv |= OPTI_MISC_INDEX(drive); opti_write_config(chp, OPTI_REG_MISC, mr | rv); /* Set the pulse width and recovery timing parameters */ rv = opti_tim_cp[spd][m] << OPTI_PULSE_WIDTH_SHIFT; rv |= opti_tim_rt[spd][m] << OPTI_RECOVERY_TIME_SHIFT; opti_write_config(chp, OPTI_REG_READ_CYCLE_TIMING, rv); opti_write_config(chp, OPTI_REG_WRITE_CYCLE_TIMING, rv); /* Set the Enhanced Mode register appropriately */ rv = pciide_pci_read(sc->sc_pc, sc->sc_tag, OPTI_REG_ENH_MODE); rv &= ~OPTI_ENH_MODE_MASK(chp->ch_channel, drive); rv |= OPTI_ENH_MODE(chp->ch_channel, drive, opti_tim_em[m]); pciide_pci_write(sc->sc_pc, sc->sc_tag, OPTI_REG_ENH_MODE, rv); } /* Finally, enable the timings */ opti_write_config(chp, OPTI_REG_CONTROL, OPTI_CONTROL_ENABLE); }
static void cy693_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; int drive; u_int32_t cy_cmd_ctrl; u_int32_t idedma_ctl; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); int dma_mode = -1; ATADEBUG_PRINT(("cy693_chip_map: old timings reg 0x%x\n", pci_conf_read(sc->sc_pc, sc->sc_tag, CY_CMD_CTRL)),DEBUG_PROBE); cy_cmd_ctrl = idedma_ctl = 0; /* setup DMA if needed */ pciide_channel_dma_setup(cp); for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; /* add timing values, setup DMA if needed */ if (drvp->drive_flags & ATA_DRIVE_DMA) { idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); /* use Multiword DMA */ if (dma_mode == -1 || dma_mode > drvp->DMA_mode) dma_mode = drvp->DMA_mode; } cy_cmd_ctrl |= (cy_pio_pulse[drvp->PIO_mode] << CY_CMD_CTRL_IOW_PULSE_OFF(drive)); cy_cmd_ctrl |= (cy_pio_rec[drvp->PIO_mode] << CY_CMD_CTRL_IOW_REC_OFF(drive)); cy_cmd_ctrl |= (cy_pio_pulse[drvp->PIO_mode] << CY_CMD_CTRL_IOR_PULSE_OFF(drive)); cy_cmd_ctrl |= (cy_pio_rec[drvp->PIO_mode] << CY_CMD_CTRL_IOR_REC_OFF(drive)); } pci_conf_write(sc->sc_pc, sc->sc_tag, CY_CMD_CTRL, cy_cmd_ctrl); chp->ch_drive[0].DMA_mode = dma_mode; chp->ch_drive[1].DMA_mode = dma_mode; if (dma_mode == -1) dma_mode = 0; if (sc->sc_cy_handle != NULL) { /* Note: `multiple' is implied. */ cy82c693_write(sc->sc_cy_handle, (sc->sc_cy_compatchan == 0) ? CY_DMA_IDX_PRIMARY : CY_DMA_IDX_SECONDARY, dma_mode); } if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } ATADEBUG_PRINT(("cy693_chip_map: new timings reg 0x%x\n", pci_conf_read(sc->sc_pc, sc->sc_tag, CY_CMD_CTRL)), DEBUG_PROBE); }
static void serverworks_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; struct atac_softc *atac = chp->ch_atac; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); int channel = chp->ch_channel; int drive, unit, s; u_int32_t pio_time, dma_time, pio_mode, udma_mode; u_int32_t idedma_ctl; static const u_int8_t pio_modes[5] = {0x5d, 0x47, 0x34, 0x22, 0x20}; static const u_int8_t dma_modes[3] = {0x77, 0x21, 0x20}; /* setup DMA if needed */ pciide_channel_dma_setup(cp); pio_time = pci_conf_read(sc->sc_pc, sc->sc_tag, 0x40); dma_time = pci_conf_read(sc->sc_pc, sc->sc_tag, 0x44); pio_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, 0x48); udma_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, 0x54); pio_time &= ~(0xffff << (16 * channel)); dma_time &= ~(0xffff << (16 * channel)); pio_mode &= ~(0xff << (8 * channel + 16)); udma_mode &= ~(0xff << (8 * channel + 16)); udma_mode &= ~(3 << (2 * channel)); idedma_ctl = 0; /* Per drive settings */ for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if ((drvp->drive_flags & DRIVE) == 0) continue; unit = drive + 2 * channel; /* add timing values, setup DMA if needed */ pio_time |= pio_modes[drvp->PIO_mode] << (8 * (unit^1)); pio_mode |= drvp->PIO_mode << (4 * unit + 16); if ((atac->atac_cap & ATAC_CAP_UDMA) && (drvp->drive_flags & DRIVE_UDMA)) { /* use Ultra/DMA, check for 80-pin cable */ if (drvp->UDMA_mode > 2 && (PCI_PRODUCT(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_SUBSYS_ID_REG)) & (1 << (14 + channel))) == 0) drvp->UDMA_mode = 2; dma_time |= dma_modes[drvp->DMA_mode] << (8 * (unit^1)); udma_mode |= drvp->UDMA_mode << (4 * unit + 16); udma_mode |= 1 << unit; idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else if ((atac->atac_cap & ATAC_CAP_DMA) && (drvp->drive_flags & DRIVE_DMA)) { /* use Multiword DMA */ s = splbio(); drvp->drive_flags &= ~DRIVE_UDMA; splx(s); dma_time |= dma_modes[drvp->DMA_mode] << (8 * (unit^1)); idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else { /* PIO only */ s = splbio(); drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA); splx(s); } } pci_conf_write(sc->sc_pc, sc->sc_tag, 0x40, pio_time); pci_conf_write(sc->sc_pc, sc->sc_tag, 0x44, dma_time); if (sc->sc_pp->ide_product != PCI_PRODUCT_SERVERWORKS_OSB4_IDE) pci_conf_write(sc->sc_pc, sc->sc_tag, 0x48, pio_mode); pci_conf_write(sc->sc_pc, sc->sc_tag, 0x54, udma_mode); if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } }
static void ite_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; int drive, mode = 0; u_int32_t idedma_ctl; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); int channel = chp->ch_channel; pcireg_t cfg, modectl; pcireg_t tim; cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG); modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE); tim = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_TIM(channel)); ATADEBUG_PRINT(("%s:%d: tim=0x%x\n", device_xname(sc->sc_wdcdev.sc_atac.atac_dev), channel, tim), DEBUG_PROBE); /* Setup DMA if needed */ pciide_channel_dma_setup(cp); /* Clear all bits for this channel */ idedma_ctl = 0; /* Per channel settings */ for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; if ((chp->ch_atac->atac_cap & ATAC_CAP_UDMA) != 0 && (drvp->drive_flags & ATA_DRIVE_UDMA) != 0) { /* Setup UltraDMA mode */ drvp->drive_flags &= ~ATA_DRIVE_DMA; modectl &= ~IT_MODE_DMA(channel, drive); #if 0 /* Check cable, only works in CPU firmware mode */ if (drvp->UDMA_mode > 2 && (cfg & IT_CFG_CABLE(channel, drive)) == 0) { ATADEBUG_PRINT(("(%s:%d:%d): " "80-wire cable not detected\n", device_xname(sc->sc_wdcdev.sc_atac.atac_dev), channel, drive), DEBUG_PROBE); drvp->UDMA_mode = 2; } #endif if (drvp->UDMA_mode >= 5) tim |= IT_TIM_UDMA5(drive); else tim &= ~IT_TIM_UDMA5(drive); mode = drvp->PIO_mode; } else if ((chp->ch_atac->atac_cap & ATAC_CAP_DMA) != 0 && (drvp->drive_flags & ATA_DRIVE_DMA) != 0) { /* Setup multiword DMA mode */ drvp->drive_flags &= ~ATA_DRIVE_UDMA; modectl |= IT_MODE_DMA(channel, drive); /* mode = min(pio, dma + 2) */ if (drvp->PIO_mode <= (drvp->DMA_mode + 2)) mode = drvp->PIO_mode; else mode = drvp->DMA_mode + 2; } else { goto pio; } idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); pio: /* Setup PIO mode */ if (mode <= 2) { drvp->DMA_mode = 0; drvp->PIO_mode = 0; mode = 0; } else { drvp->PIO_mode = mode; drvp->DMA_mode = mode - 2; } /* Enable IORDY if PIO mode >= 3 */ if (drvp->PIO_mode >= 3) cfg |= IT_CFG_IORDY(channel); } ATADEBUG_PRINT(("%s: tim=0x%x\n", device_xname(sc->sc_wdcdev.sc_atac.atac_dev), tim), DEBUG_PROBE); pci_conf_write(sc->sc_pc, sc->sc_tag, IT_CFG, cfg); pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl); pci_conf_write(sc->sc_pc, sc->sc_tag, IT_TIM(channel), tim); if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } }
static void piix_setup_channel(struct ata_channel *chp) { u_int8_t mode[2], drive; u_int32_t oidetim, idetim, idedma_ctl; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); struct ata_drive_datas *drvp = cp->ata_channel.ch_drive; oidetim = pci_conf_read(sc->sc_pc, sc->sc_tag, PIIX_IDETIM); idetim = PIIX_IDETIM_CLEAR(oidetim, 0xffff, chp->ch_channel); idedma_ctl = 0; /* set up new idetim: Enable IDE registers decode */ idetim = PIIX_IDETIM_SET(idetim, PIIX_IDETIM_IDE, chp->ch_channel); /* setup DMA */ pciide_channel_dma_setup(cp); /* * Here we have to mess up with drives mode: PIIX can't have * different timings for master and slave drives. * We need to find the best combination. */ /* If both drives supports DMA, take the lower mode */ if ((drvp[0].drive_flags & ATA_DRIVE_DMA) && (drvp[1].drive_flags & ATA_DRIVE_DMA)) { mode[0] = mode[1] = min(drvp[0].DMA_mode, drvp[1].DMA_mode); drvp[0].DMA_mode = mode[0]; drvp[1].DMA_mode = mode[1]; goto ok; } /* * If only one drive supports DMA, use its mode, and * put the other one in PIO mode 0 if mode not compatible */ if (drvp[0].drive_flags & ATA_DRIVE_DMA) { mode[0] = drvp[0].DMA_mode; mode[1] = drvp[1].PIO_mode; if (piix_isp_pio[mode[1]] != piix_isp_dma[mode[0]] || piix_rtc_pio[mode[1]] != piix_rtc_dma[mode[0]]) mode[1] = drvp[1].PIO_mode = 0; goto ok; } if (drvp[1].drive_flags & ATA_DRIVE_DMA) { mode[1] = drvp[1].DMA_mode; mode[0] = drvp[0].PIO_mode; if (piix_isp_pio[mode[0]] != piix_isp_dma[mode[1]] || piix_rtc_pio[mode[0]] != piix_rtc_dma[mode[1]]) mode[0] = drvp[0].PIO_mode = 0; goto ok; } /* * If both drives are not DMA, takes the lower mode, unless * one of them is PIO mode < 2 */ if (drvp[0].PIO_mode < 2) { mode[0] = drvp[0].PIO_mode = 0; mode[1] = drvp[1].PIO_mode; } else if (drvp[1].PIO_mode < 2) { mode[1] = drvp[1].PIO_mode = 0; mode[0] = drvp[0].PIO_mode; } else { mode[0] = mode[1] = min(drvp[1].PIO_mode, drvp[0].PIO_mode); drvp[0].PIO_mode = mode[0]; drvp[1].PIO_mode = mode[1]; } ok: /* The modes are setup */ for (drive = 0; drive < 2; drive++) { if (drvp[drive].drive_flags & ATA_DRIVE_DMA) { idetim |= piix_setup_idetim_timings( mode[drive], 1, chp->ch_channel); goto end; } } /* If we are there, none of the drives are DMA */ if (mode[0] >= 2) idetim |= piix_setup_idetim_timings( mode[0], 0, chp->ch_channel); else idetim |= piix_setup_idetim_timings( mode[1], 0, chp->ch_channel); end: /* * timing mode is now set up in the controller. Enable * it per-drive */ for (drive = 0; drive < 2; drive++) { /* If no drive, skip */ if (drvp[drive].drive_type == ATA_DRIVET_NONE) continue; idetim |= piix_setup_idetim_drvs(&drvp[drive]); if (drvp[drive].drive_flags & ATA_DRIVE_DMA) idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_IDETIM, idetim); }
static void acer_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; int drive, s; u_int32_t acer_fifo_udma; u_int32_t idedma_ctl; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); idedma_ctl = 0; acer_fifo_udma = pci_conf_read(sc->sc_pc, sc->sc_tag, ACER_FTH_UDMA); ATADEBUG_PRINT(("acer_setup_channel: old fifo/udma reg 0x%x\n", acer_fifo_udma), DEBUG_PROBE); /* setup DMA if needed */ pciide_channel_dma_setup(cp); if ((chp->ch_drive[0].drive_flags | chp->ch_drive[1].drive_flags) & ATA_DRIVE_UDMA) { /* check 80 pins cable */ if (pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_0x4A) & ACER_0x4A_80PIN(chp->ch_channel)) { if (chp->ch_drive[0].UDMA_mode > 2) chp->ch_drive[0].UDMA_mode = 2; if (chp->ch_drive[1].UDMA_mode > 2) chp->ch_drive[1].UDMA_mode = 2; } } for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; ATADEBUG_PRINT(("acer_setup_channel: old timings reg for " "channel %d drive %d 0x%x\n", chp->ch_channel, drive, pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_IDETIM(chp->ch_channel, drive))), DEBUG_PROBE); /* clear FIFO/DMA mode */ acer_fifo_udma &= ~(ACER_FTH_OPL(chp->ch_channel, drive, 0x3) | ACER_UDMA_EN(chp->ch_channel, drive) | ACER_UDMA_TIM(chp->ch_channel, drive, 0x7)); /* add timing values, setup DMA if needed */ if ((drvp->drive_flags & ATA_DRIVE_DMA) == 0 && (drvp->drive_flags & ATA_DRIVE_UDMA) == 0) { acer_fifo_udma |= ACER_FTH_OPL(chp->ch_channel, drive, 0x1); goto pio; } acer_fifo_udma |= ACER_FTH_OPL(chp->ch_channel, drive, 0x2); if (drvp->drive_flags & ATA_DRIVE_UDMA) { /* use Ultra/DMA */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_DMA; splx(s); acer_fifo_udma |= ACER_UDMA_EN(chp->ch_channel, drive); acer_fifo_udma |= ACER_UDMA_TIM(chp->ch_channel, drive, acer_udma[drvp->UDMA_mode]); /* XXX disable if one drive < UDMA3 ? */ if (drvp->UDMA_mode >= 3) { pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_0x4B, pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_0x4B) | ACER_0x4B_UDMA66); } } else { /* * use Multiword DMA * Timings will be used for both PIO and DMA, * so adjust DMA mode if needed */ if (drvp->PIO_mode > (drvp->DMA_mode + 2)) drvp->PIO_mode = drvp->DMA_mode + 2; if (drvp->DMA_mode + 2 > (drvp->PIO_mode)) drvp->DMA_mode = (drvp->PIO_mode > 2) ? drvp->PIO_mode - 2 : 0; if (drvp->DMA_mode == 0) drvp->PIO_mode = 0; } idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); pio: pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_IDETIM(chp->ch_channel, drive), acer_pio[drvp->PIO_mode]); } ATADEBUG_PRINT(("acer_setup_channel: new fifo/udma reg 0x%x\n", acer_fifo_udma), DEBUG_PROBE); pci_conf_write(sc->sc_pc, sc->sc_tag, ACER_FTH_UDMA, acer_fifo_udma); if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } }
static void sis_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; int drive, s; u_int32_t sis_tim; u_int32_t idedma_ctl; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); ATADEBUG_PRINT(("sis_setup_channel: old timings reg for " "channel %d 0x%x\n", chp->ch_channel, pci_conf_read(sc->sc_pc, sc->sc_tag, SIS_TIM(chp->ch_channel))), DEBUG_PROBE); sis_tim = 0; idedma_ctl = 0; /* setup DMA if needed */ pciide_channel_dma_setup(cp); for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; /* add timing values, setup DMA if needed */ if ((drvp->drive_flags & ATA_DRIVE_DMA) == 0 && (drvp->drive_flags & ATA_DRIVE_UDMA) == 0) goto pio; if (drvp->drive_flags & ATA_DRIVE_UDMA) { /* use Ultra/DMA */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_DMA; splx(s); if (pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_CBL) & SIS_REG_CBL_33(chp->ch_channel)) { if (drvp->UDMA_mode > 2) drvp->UDMA_mode = 2; } switch (sc->sis_type) { case SIS_TYPE_66: case SIS_TYPE_100OLD: sis_tim |= sis_udma66_tim[drvp->UDMA_mode] << SIS_TIM66_UDMA_TIME_OFF(drive); break; case SIS_TYPE_100NEW: sis_tim |= sis_udma100new_tim[drvp->UDMA_mode] << SIS_TIM100_UDMA_TIME_OFF(drive); case SIS_TYPE_133OLD: sis_tim |= sis_udma133old_tim[drvp->UDMA_mode] << SIS_TIM100_UDMA_TIME_OFF(drive); break; default: aprint_error("unknown SiS IDE type %d\n", sc->sis_type); } } else { /* * use Multiword DMA * Timings will be used for both PIO and DMA, * so adjust DMA mode if needed */ if (drvp->PIO_mode > (drvp->DMA_mode + 2)) drvp->PIO_mode = drvp->DMA_mode + 2; if (drvp->DMA_mode + 2 > (drvp->PIO_mode)) drvp->DMA_mode = (drvp->PIO_mode > 2) ? drvp->PIO_mode - 2 : 0; if (drvp->DMA_mode == 0) drvp->PIO_mode = 0; } idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); pio: switch (sc->sis_type) { case SIS_TYPE_NOUDMA: case SIS_TYPE_66: case SIS_TYPE_100OLD: sis_tim |= sis_pio_act[drvp->PIO_mode] << SIS_TIM66_ACT_OFF(drive); sis_tim |= sis_pio_rec[drvp->PIO_mode] << SIS_TIM66_REC_OFF(drive); break; case SIS_TYPE_100NEW: case SIS_TYPE_133OLD: sis_tim |= sis_pio_act[drvp->PIO_mode] << SIS_TIM100_ACT_OFF(drive); sis_tim |= sis_pio_rec[drvp->PIO_mode] << SIS_TIM100_REC_OFF(drive); break; default: aprint_error("unknown SiS IDE type %d\n", sc->sis_type); } } ATADEBUG_PRINT(("sis_setup_channel: new timings reg for " "channel %d 0x%x\n", chp->ch_channel, sis_tim), DEBUG_PROBE); pci_conf_write(sc->sc_pc, sc->sc_tag, SIS_TIM(chp->ch_channel), sis_tim); if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } }
static void sis96x_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; int drive, s; u_int32_t sis_tim; u_int32_t idedma_ctl; int regtim; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); sis_tim = 0; idedma_ctl = 0; /* setup DMA if needed */ pciide_channel_dma_setup(cp); for (drive = 0; drive < 2; drive++) { regtim = SIS_TIM133( pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_57), chp->ch_channel, drive); drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; /* add timing values, setup DMA if needed */ if (drvp->drive_flags & ATA_DRIVE_UDMA) { /* use Ultra/DMA */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_DMA; splx(s); if (pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS96x_REG_CBL(chp->ch_channel)) & SIS96x_REG_CBL_33) { if (drvp->UDMA_mode > 2) drvp->UDMA_mode = 2; } sis_tim |= sis_udma133new_tim[drvp->UDMA_mode]; sis_tim |= sis_pio133new_tim[drvp->PIO_mode]; idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else if (drvp->drive_flags & ATA_DRIVE_DMA) { /* * use Multiword DMA * Timings will be used for both PIO and DMA, * so adjust DMA mode if needed */ if (drvp->PIO_mode > (drvp->DMA_mode + 2)) drvp->PIO_mode = drvp->DMA_mode + 2; if (drvp->DMA_mode + 2 > (drvp->PIO_mode)) drvp->DMA_mode = (drvp->PIO_mode > 2) ? drvp->PIO_mode - 2 : 0; sis_tim |= sis_dma133new_tim[drvp->DMA_mode]; idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else { sis_tim |= sis_pio133new_tim[drvp->PIO_mode]; } ATADEBUG_PRINT(("sis96x_setup_channel: new timings reg for " "channel %d drive %d: 0x%x (reg 0x%x)\n", chp->ch_channel, drive, sis_tim, regtim), DEBUG_PROBE); pci_conf_write(sc->sc_pc, sc->sc_tag, regtim, sis_tim); } if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } }
static void piccolo_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); u_int32_t idedma_ctl; int drive, s; pcireg_t pxdx; #ifdef TOSHIDE_DEBUG pcireg_t pxdx_prime; #endif idedma_ctl = 0; /* Set up DMA if needed. */ pciide_channel_dma_setup(cp); for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; if (drvp->drive_flags & ATA_DRIVE_UDMA) { /* use Ultra/DMA */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_DMA; splx(s); /* * Use UDMA - we can go up to mode 2 so no need to * check anything since nearly all drives with UDMA * are mode 2 or faster */ pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, PICCOLO_DMA_TIMING); pxdx &= PICCOLO_UDMA_MASK; pxdx |= piccolo_udma_times[2]; pci_conf_write(sc->sc_pc, sc->sc_tag, PICCOLO_DMA_TIMING, pxdx); #ifdef TOSHIDE_DEBUG /* XXX sanity check */ pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, PICCOLO_DMA_TIMING); aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, "UDMA want %x, set %x, got %x\n", piccolo_udma_times[2], pxdx, pxdx_prime); #endif idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else if (drvp->drive_flags & ATA_DRIVE_DMA) { /* * Use Multiword DMA */ if (drvp->PIO_mode > (drvp->DMA_mode + 2)) drvp->PIO_mode = drvp->DMA_mode + 2; if (drvp->DMA_mode + 2 > (drvp->PIO_mode)) drvp->DMA_mode = (drvp->PIO_mode > 2) ? drvp->PIO_mode - 2 : 0; pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, PICCOLO_DMA_TIMING); pxdx &= PICCOLO_DMA_MASK; pxdx |= piccolo_mw_dma_times[drvp->DMA_mode]; pci_conf_write(sc->sc_pc, sc->sc_tag, PICCOLO_DMA_TIMING, pxdx); #ifdef TOSHIDE_DEBUG /* XXX sanity check */ pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, PICCOLO_DMA_TIMING); aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, "DMA %d want %x, set %x, got %x\n", drvp->DMA_mode, piccolo_mw_dma_times[drvp->DMA_mode], pxdx, pxdx_prime); #endif idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else { pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, PICCOLO_PIO_TIMING); pxdx &= PICCOLO_PIO_MASK; pxdx |= piccolo_pio_times[drvp->PIO_mode]; pci_conf_write(sc->sc_pc, sc->sc_tag, PICCOLO_PIO_TIMING, pxdx); #ifdef TOSHIDE_DEBUG /* XXX sanity check */ pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, PICCOLO_PIO_TIMING); aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, "PIO %d want %x, set %x, got %x\n", drvp->PIO_mode, piccolo_pio_times[drvp->PIO_mode], pxdx, pxdx_prime); #endif } } if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } }
static void artisea_mapregs(struct pci_attach_args *pa, struct pciide_channel *cp, bus_size_t *cmdsizep, bus_size_t *ctlsizep, int (*pci_intr)(void *)) { struct pciide_softc *sc = CHAN_TO_PCIIDE(&cp->ata_channel); struct ata_channel *wdc_cp = &cp->ata_channel; struct wdc_regs *wdr = CHAN_TO_WDC_REGS(wdc_cp); const char *intrstr; pci_intr_handle_t intrhandle; int i; cp->compat = 0; if (sc->sc_pci_ih == NULL) { if (pci_intr_map(pa, &intrhandle) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map native-PCI interrupt\n"); goto bad; } intrstr = pci_intr_string(pa->pa_pc, intrhandle); sc->sc_pci_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, pci_intr, sc); if (sc->sc_pci_ih != NULL) { aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, "using %s for native-PCI interrupt\n", intrstr ? intrstr : "unknown interrupt"); } else { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't establish native-PCI interrupt"); if (intrstr != NULL) aprint_normal(" at %s", intrstr); aprint_normal("\n"); goto bad; } } cp->ih = sc->sc_pci_ih; wdr->cmd_iot = sc->sc_ba5_st; if (bus_space_subregion (sc->sc_ba5_st, sc->sc_ba5_sh, ARTISEA_DPA_PORT_BASE(wdc_cp->ch_channel), 0x200, &wdr->cmd_baseioh) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map %s channel cmd regs\n", cp->name); goto bad; } wdr->ctl_iot = sc->sc_ba5_st; if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, ARTISEA_SUPDDCTLR, 1, &cp->ctl_baseioh) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map %s channel ctl regs\n", cp->name); goto bad; } wdr->ctl_ioh = cp->ctl_baseioh; for (i = 0; i < WDC_NREG + 2; i++) { if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, artisea_dpa_cmd_map[i].offset, artisea_dpa_cmd_map[i].size, &wdr->cmd_iohs[i]) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't subregion %s channel cmd regs\n", cp->name); goto bad; } } wdr->data32iot = wdr->cmd_iot; wdr->data32ioh = wdr->cmd_iohs[0]; wdr->sata_iot = wdr->cmd_iot; wdr->sata_baseioh = wdr->cmd_baseioh; if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh, ARTISEA_SUPERSET_DPA_OFF + ARTISEA_SUPDSSSR, 1, &wdr->sata_status) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map channel %d sata_status regs\n", wdc_cp->ch_channel); goto bad; } if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh, ARTISEA_SUPERSET_DPA_OFF + ARTISEA_SUPDSSER, 1, &wdr->sata_error) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map channel %d sata_error regs\n", wdc_cp->ch_channel); goto bad; } if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh, ARTISEA_SUPERSET_DPA_OFF + ARTISEA_SUPDSSCR, 1, &wdr->sata_control) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map channel %d sata_control regs\n", wdc_cp->ch_channel); goto bad; } wdcattach(wdc_cp); return; bad: wdc_cp->ch_flags |= ATACH_DISABLED; return; }
static void piix3_4_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; u_int32_t oidetim, idetim, sidetim, udmareg, ideconf, idedma_ctl; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); struct wdc_softc *wdc = &sc->sc_wdcdev; int drive, s; int channel = chp->ch_channel; oidetim = pci_conf_read(sc->sc_pc, sc->sc_tag, PIIX_IDETIM); sidetim = pci_conf_read(sc->sc_pc, sc->sc_tag, PIIX_SIDETIM); udmareg = pci_conf_read(sc->sc_pc, sc->sc_tag, PIIX_UDMAREG); ideconf = pci_conf_read(sc->sc_pc, sc->sc_tag, PIIX_CONFIG); idetim = PIIX_IDETIM_CLEAR(oidetim, 0xffff, channel); sidetim &= ~(PIIX_SIDETIM_ISP_MASK(channel) | PIIX_SIDETIM_RTC_MASK(channel)); idedma_ctl = 0; /* set up new idetim: Enable IDE registers decode */ idetim = PIIX_IDETIM_SET(idetim, PIIX_IDETIM_IDE, channel); /* setup DMA if needed */ pciide_channel_dma_setup(cp); for (drive = 0; drive < 2; drive++) { udmareg &= ~(PIIX_UDMACTL_DRV_EN(channel, drive) | PIIX_UDMATIM_SET(0x3, channel, drive)); drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; if (((drvp->drive_flags & ATA_DRIVE_DMA) == 0 && (drvp->drive_flags & ATA_DRIVE_UDMA) == 0)) goto pio; if (sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801AA_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801AB_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801BA_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801BAM_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801CA_IDE_1 || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801CA_IDE_2 || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801DB_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801DBM_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801EB_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801FB_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_6300ESB_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801G_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801HBM_IDE) { ideconf |= PIIX_CONFIG_PINGPONG; } if (sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801BA_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801BAM_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801CA_IDE_1 || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801CA_IDE_2 || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801DB_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801DBM_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801EB_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801FB_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_6300ESB_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801G_IDE || sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801HBM_IDE) { /* setup Ultra/100 */ if (drvp->UDMA_mode > 2 && (ideconf & PIIX_CONFIG_CR(channel, drive)) == 0) drvp->UDMA_mode = 2; if (drvp->UDMA_mode > 4) { ideconf |= PIIX_CONFIG_UDMA100(channel, drive); } else { ideconf &= ~PIIX_CONFIG_UDMA100(channel, drive); if (drvp->UDMA_mode > 2) { ideconf |= PIIX_CONFIG_UDMA66(channel, drive); } else { ideconf &= ~PIIX_CONFIG_UDMA66(channel, drive); } } } if (sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801AA_IDE) { /* setup Ultra/66 */ if (drvp->UDMA_mode > 2 && (ideconf & PIIX_CONFIG_CR(channel, drive)) == 0) drvp->UDMA_mode = 2; if (drvp->UDMA_mode > 2) ideconf |= PIIX_CONFIG_UDMA66(channel, drive); else ideconf &= ~PIIX_CONFIG_UDMA66(channel, drive); } if ((wdc->sc_atac.atac_cap & ATAC_CAP_UDMA) && (drvp->drive_flags & ATA_DRIVE_UDMA)) { /* use Ultra/DMA */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_DMA; splx(s); udmareg |= PIIX_UDMACTL_DRV_EN( channel, drive); udmareg |= PIIX_UDMATIM_SET( piix4_sct_udma[drvp->UDMA_mode], channel, drive); } else { /* use Multiword DMA */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_UDMA; splx(s); if (drive == 0) { idetim |= piix_setup_idetim_timings( drvp->DMA_mode, 1, channel); } else { sidetim |= piix_setup_sidetim_timings( drvp->DMA_mode, 1, channel); idetim =PIIX_IDETIM_SET(idetim, PIIX_IDETIM_SITRE, channel); } } idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); pio: /* use PIO mode */ idetim |= piix_setup_idetim_drvs(drvp); if (drive == 0) { idetim |= piix_setup_idetim_timings( drvp->PIO_mode, 0, channel); } else { sidetim |= piix_setup_sidetim_timings( drvp->PIO_mode, 0, channel); idetim =PIIX_IDETIM_SET(idetim, PIIX_IDETIM_SITRE, channel); } } if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_IDETIM, idetim); pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_SIDETIM, sidetim); pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_UDMAREG, udmareg); pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_CONFIG, ideconf); }
static void geodeide_setup_channel(struct ata_channel *chp) { struct ata_drive_datas *drvp; struct pciide_channel *cp = CHAN_TO_PCHAN(chp); struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); int channel = chp->ch_channel; int drive, s; u_int32_t dma_timing; u_int8_t idedma_ctl; const int32_t *geode_pio; const int32_t *geode_dma; const int32_t *geode_udma; bus_size_t dmaoff, piooff; switch (sc->sc_pp->ide_product) { case PCI_PRODUCT_CYRIX_CX5530_IDE: geode_pio = geode_cs5530_pio; geode_dma = geode_cs5530_dma; geode_udma = geode_cs5530_udma; break; case PCI_PRODUCT_NS_SC1100_IDE: default: /* XXX gcc */ geode_pio = geode_sc1100_pio; geode_dma = geode_sc1100_dma; geode_udma = geode_sc1100_udma; break; } /* setup DMA if needed */ pciide_channel_dma_setup(cp); idedma_ctl = 0; /* Per drive settings */ for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if (drvp->drive_type == ATA_DRIVET_NONE) continue; switch (sc->sc_pp->ide_product) { case PCI_PRODUCT_CYRIX_CX5530_IDE: dmaoff = CS5530_DMA_REG(channel, drive); piooff = CS5530_PIO_REG(channel, drive); dma_timing = CS5530_DMA_REG_PIO_FORMAT; break; case PCI_PRODUCT_NS_SC1100_IDE: default: /* XXX gcc */ dmaoff = SC1100_DMA_REG(channel, drive); piooff = SC1100_PIO_REG(channel, drive); dma_timing = 0; break; } /* add timing values, setup DMA if needed */ if (drvp->drive_flags & ATA_DRIVE_UDMA) { /* Use Ultra-DMA */ dma_timing |= geode_udma[drvp->UDMA_mode]; idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else if (drvp->drive_flags & ATA_DRIVE_DMA) { /* use Multiword DMA */ dma_timing |= geode_dma[drvp->DMA_mode]; idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else { /* PIO only */ s = splbio(); drvp->drive_flags &= ~(ATA_DRIVE_UDMA | ATA_DRIVE_DMA); splx(s); } switch (sc->sc_pp->ide_product) { case PCI_PRODUCT_CYRIX_CX5530_IDE: bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh, dmaoff, dma_timing); bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh, piooff, geode_pio[drvp->PIO_mode]); break; case PCI_PRODUCT_NS_SC1100_IDE: pci_conf_write(sc->sc_pc, sc->sc_tag, dmaoff, dma_timing); pci_conf_write(sc->sc_pc, sc->sc_tag, piooff, geode_pio[drvp->PIO_mode]); break; } } if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); } }