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 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 sii3112_setup_channel(struct wdc_channel *chp) { struct ata_drive_datas *drvp; int drive; u_int32_t idedma_ctl, dtm; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = (struct pciide_softc*)cp->wdc_channel.ch_wdc; /* setup DMA if needed */ pciide_channel_dma_setup(cp); idedma_ctl = 0; dtm = 0; for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if ((drvp->drive_flags & DRIVE) == 0) continue; if (drvp->drive_flags & DRIVE_UDMA) { /* use Ultra/DMA */ drvp->drive_flags &= ~DRIVE_DMA; idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); dtm |= DTM_IDEx_DMA; } else if (drvp->drive_flags & DRIVE_DMA) { idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); dtm |= DTM_IDEx_DMA; } else { dtm |= DTM_IDEx_PIO; } } /* * Nothing to do to setup modes; it is meaningless in S-ATA * (but many S-ATA drives still want to get the SET_FEATURE * command). */ 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); } BA5_WRITE_4(sc, chp->ch_channel, ba5_IDE_DTM, dtm); }
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 piix3_4_setup_channel(struct wdc_channel *chp) { struct ata_drive_datas *drvp; u_int32_t oidetim, idetim, sidetim, udmareg, ideconf, idedma_ctl; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc; struct wdc_softc *wdc = &sc->sc_wdcdev; int drive; 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_flags & DRIVE) == 0) continue; if (((drvp->drive_flags & DRIVE_DMA) == 0 && (drvp->drive_flags & 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_6300ESB_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_6300ESB_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->cap & WDC_CAPABILITY_UDMA) && (drvp->drive_flags & DRIVE_UDMA)) { /* use Ultra/DMA */ drvp->drive_flags &= ~DRIVE_DMA; udmareg |= PIIX_UDMACTL_DRV_EN( channel, drive); udmareg |= PIIX_UDMATIM_SET( piix4_sct_udma[drvp->UDMA_mode], channel, drive); } else { /* use Multiword DMA */ drvp->drive_flags &= ~DRIVE_UDMA; 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 piix_setup_channel(struct wdc_channel *chp) { u_int8_t mode[2], drive; u_int32_t oidetim, idetim, idedma_ctl; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc; struct ata_drive_datas *drvp = cp->wdc_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 & DRIVE_DMA) && (drvp[1].drive_flags & 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 & 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 & 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 & 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_flags & DRIVE) == 0) continue; idetim |= piix_setup_idetim_drvs(&drvp[drive]); if (drvp[drive].drive_flags & 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 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 cmd0643_9_setup_channel(struct wdc_channel *chp) { struct ata_drive_datas *drvp; u_int8_t tim; u_int32_t idedma_ctl, udma_reg; int drive; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc; 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_flags & DRIVE) == 0) continue; /* add timing values, setup DMA if needed */ tim = cmd0643_9_data_tim_pio[drvp->PIO_mode]; if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) { if (drvp->drive_flags & DRIVE_UDMA) { /* UltraDMA on a 646U2, 0648 or 0649 */ drvp->drive_flags &= ~DRIVE_DMA; udma_reg = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_UDMATIM(chp->ch_channel)); if (drvp->UDMA_mode > 2 && (pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_BICSR) & CMD_BICSR_80(chp->ch_channel)) == 0) drvp->UDMA_mode = 2; if (drvp->UDMA_mode > 2) udma_reg &= ~CMD_UDMATIM_UDMA33(drive); else if (sc->sc_wdcdev.UDMA_cap > 2) udma_reg |= CMD_UDMATIM_UDMA33(drive); udma_reg |= CMD_UDMATIM_UDMA(drive); udma_reg &= ~(CMD_UDMATIM_TIM_MASK << CMD_UDMATIM_TIM_OFF(drive)); udma_reg |= (cmd0646_9_tim_udma[drvp->UDMA_mode] << CMD_UDMATIM_TIM_OFF(drive)); pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_UDMATIM(chp->ch_channel), udma_reg); } else { /* * use Multiword DMA. * Timings will be used for both PIO and DMA, * so adjust DMA mode if needed * if we have a 0646U2/8/9, turn off UDMA */ if (sc->sc_wdcdev.cap & WDC_CAPABILITY_UDMA) { udma_reg = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_UDMATIM(chp->ch_channel)); udma_reg &= ~CMD_UDMATIM_UDMA(drive); pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_UDMATIM(chp->ch_channel), udma_reg); } if (drvp->PIO_mode >= 3 && (drvp->DMA_mode + 2) > drvp->PIO_mode) { drvp->DMA_mode = drvp->PIO_mode - 2; } tim = cmd0643_9_data_tim_dma[drvp->DMA_mode]; } idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_DATA_TIM(chp->ch_channel, drive), 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 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); } }
void pciide_pnpbios_attach(device_t parent, device_t self, void *aux) { struct pciide_softc *sc = device_private(self); struct pnpbiosdev_attach_args *aa = aux; struct pciide_channel *cp; struct ata_channel *wdc_cp; struct wdc_regs *wdr; bus_space_tag_t compat_iot; bus_space_handle_t cmd_baseioh, ctl_ioh; int i, drive, size; uint8_t idedma_ctl; sc->sc_wdcdev.sc_atac.atac_dev = self; aprint_naive(": disk controller\n"); aprint_normal("\n"); pnpbios_print_devres(self, aa); aprint_normal_dev(self, "Toshiba Extended IDE Controller\n"); if (pnpbios_io_map(aa->pbt, aa->resc, 2, &sc->sc_dma_iot, &sc->sc_dma_ioh) != 0) { aprint_error_dev(self, "unable to map DMA registers\n"); return; } if (pnpbios_io_map(aa->pbt, aa->resc, 0, &compat_iot, &cmd_baseioh) != 0) { aprint_error_dev(self, "unable to map command registers\n"); return; } if (pnpbios_io_map(aa->pbt, aa->resc, 1, &compat_iot, &ctl_ioh) != 0) { aprint_error_dev(self, "unable to map control register\n"); return; } sc->sc_dmat = &pci_bus_dma_tag; cp = &sc->pciide_channels[0]; sc->wdc_chanarray[0] = &cp->ata_channel; cp->ata_channel.ch_channel = 0; cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; cp->ata_channel.ch_queue = malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); cp->ata_channel.ch_ndrive = 2; if (cp->ata_channel.ch_queue == NULL) { aprint_error_dev(self, "unable to allocate memory for command " "queue\n"); return; } sc->sc_dma_ok = 1; for (i = 0; i < IDEDMA_NREGS; i++) { size = 4; if (size > (IDEDMA_SCH_OFFSET - i)) size = IDEDMA_SCH_OFFSET - i; if (bus_space_subregion(sc->sc_dma_iot, sc->sc_dma_ioh, i, size, &cp->dma_iohs[i]) != 0) { aprint_error_dev(self, "can't subregion offset %d " "size %lu", i, (u_long)size); return; } } sc->sc_dma_maxsegsz = IDEDMA_BYTE_COUNT_MAX; sc->sc_dma_boundary = IDEDMA_BYTE_COUNT_ALIGN; sc->sc_wdcdev.dma_arg = sc; sc->sc_wdcdev.dma_init = pciide_dma_init; sc->sc_wdcdev.dma_start = pciide_dma_start; sc->sc_wdcdev.dma_finish = pciide_dma_finish; sc->sc_wdcdev.irqack = pciide_irqack; sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA; sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; sc->sc_wdcdev.sc_atac.atac_nchannels = 1; sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32; sc->sc_wdcdev.sc_atac.atac_pio_cap = 0; sc->sc_wdcdev.sc_atac.atac_dma_cap = 0; /* XXX */ sc->sc_wdcdev.sc_atac.atac_udma_cap = 0; /* XXX */ wdc_allocate_regs(&sc->sc_wdcdev); wdc_cp = &cp->ata_channel; wdr = CHAN_TO_WDC_REGS(wdc_cp); wdr->cmd_iot = compat_iot; wdr->cmd_baseioh = cmd_baseioh; for (i = 0; i < WDC_NREG; i++) { if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, i, i == 0 ? 4 : 1, &wdr->cmd_iohs[i]) != 0) { aprint_error_dev(self, "unable to subregion " "control register\n"); return; } } wdc_init_shadow_regs(wdc_cp); wdr->ctl_iot = wdr->data32iot = compat_iot; wdr->ctl_ioh = wdr->data32ioh = ctl_ioh; cp->compat = 1; cp->ih = pnpbios_intr_establish(aa->pbt, aa->resc, 0, IPL_BIO, pciide_compat_intr, cp); wdcattach(wdc_cp); idedma_ctl = 0; for (drive = 0; drive < cp->ata_channel.ch_ndrive; drive++) { /* * we have not probed the drives yet, * allocate ressources for all of them. */ if (pciide_dma_table_setup(sc, 0, drive) != 0) { /* Abort DMA setup */ aprint_error( "%s:%d:%d: can't allocate DMA maps, " "using PIO transfers\n", device_xname(self), 0, drive); sc->sc_dma_ok = 0; sc->sc_wdcdev.sc_atac.atac_cap &= ~ATAC_CAP_DMA; sc->sc_wdcdev.irqack = NULL; idedma_ctl = 0; break; } 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); } }
static void cmd680_setup_channel(struct wdc_channel *chp) { struct ata_drive_datas *drvp; u_int8_t mode, off, scsc; u_int16_t val; u_int32_t idedma_ctl; int drive; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc; pci_chipset_tag_t pc = sc->sc_pc; pcitag_t pa = sc->sc_tag; static const u_int8_t udma2_tbl[] = { 0x0f, 0x0b, 0x07, 0x06, 0x03, 0x02, 0x01 }; static const u_int8_t udma_tbl[] = { 0x0c, 0x07, 0x05, 0x04, 0x02, 0x01, 0x00 }; static const u_int16_t dma_tbl[] = { 0x2208, 0x10c2, 0x10c1 }; static const u_int16_t pio_tbl[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; idedma_ctl = 0; pciide_channel_dma_setup(cp); mode = pciide_pci_read(pc, pa, 0x80 + chp->ch_channel * 4); for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if ((drvp->drive_flags & DRIVE) == 0) continue; mode &= ~(0x03 << (drive * 4)); if (drvp->drive_flags & DRIVE_UDMA) { drvp->drive_flags &= ~DRIVE_DMA; off = 0xa0 + chp->ch_channel * 16; if (drvp->UDMA_mode > 2 && (pciide_pci_read(pc, pa, off) & 0x01) == 0) drvp->UDMA_mode = 2; scsc = pciide_pci_read(pc, pa, 0x8a); if (drvp->UDMA_mode == 6 && (scsc & 0x30) == 0) { pciide_pci_write(pc, pa, 0x8a, scsc | 0x01); scsc = pciide_pci_read(pc, pa, 0x8a); if ((scsc & 0x30) == 0) drvp->UDMA_mode = 5; } mode |= 0x03 << (drive * 4); off = 0xac + chp->ch_channel * 16 + drive * 2; val = pciide_pci_read(pc, pa, off) & ~0x3f; if (scsc & 0x30) val |= udma2_tbl[drvp->UDMA_mode]; else val |= udma_tbl[drvp->UDMA_mode]; pciide_pci_write(pc, pa, off, val); idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else if (drvp->drive_flags & DRIVE_DMA) { mode |= 0x02 << (drive * 4); off = 0xa8 + chp->ch_channel * 16 + drive * 2; val = dma_tbl[drvp->DMA_mode]; pciide_pci_write(pc, pa, off, val & 0xff); pciide_pci_write(pc, pa, off, val >> 8); idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } else {
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); } }