/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev,
"bus-master DMA support present");
pciide_mapreg_dma(sc, pa);
aprint_verbose("\n");
sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
if (sc->sc_dma_ok) {
sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA;
sc->sc_wdcdev.irqack = pciide_irqack;
/* Do all revisions require DMA alignment workaround? */
sc->sc_wdcdev.dma_init = piix_dma_init;
switch(sc->sc_pp->ide_product) {
case PCI_PRODUCT_INTEL_82371AB_IDE:
case PCI_PRODUCT_INTEL_82440MX_IDE:
case PCI_PRODUCT_INTEL_82801AA_IDE:
case PCI_PRODUCT_INTEL_82801AB_IDE:
case PCI_PRODUCT_INTEL_82801BA_IDE:
case PCI_PRODUCT_INTEL_82801BAM_IDE:
case PCI_PRODUCT_INTEL_82801CA_IDE_1:
case PCI_PRODUCT_INTEL_82801CA_IDE_2:
case PCI_PRODUCT_INTEL_82801DB_IDE:
case PCI_PRODUCT_INTEL_82801DBM_IDE:
case PCI_PRODUCT_INTEL_82801EB_IDE:
case PCI_PRODUCT_INTEL_6300ESB_IDE:
case PCI_PRODUCT_INTEL_82801FB_IDE:
case PCI_PRODUCT_INTEL_82801G_IDE:
case PCI_PRODUCT_INTEL_82801HBM_IDE:
sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA;
}
}
sc->sc_wdcdev.sc_atac.atac_pio_cap = 4;
sc->sc_wdcdev.sc_atac.atac_dma_cap = 2;
switch(sc->sc_pp->ide_product) {
case PCI_PRODUCT_INTEL_82801AA_IDE:
sc->sc_wdcdev.sc_atac.atac_udma_cap = 4;
break;
case PCI_PRODUCT_INTEL_82801BA_IDE:
case PCI_PRODUCT_INTEL_82801BAM_IDE:
case PCI_PRODUCT_INTEL_82801CA_IDE_1:
case PCI_PRODUCT_INTEL_82801CA_IDE_2:
case PCI_PRODUCT_INTEL_82801DB_IDE:
case PCI_PRODUCT_INTEL_82801DBM_IDE:
case PCI_PRODUCT_INTEL_82801EB_IDE:
case PCI_PRODUCT_INTEL_6300ESB_IDE:
case PCI_PRODUCT_INTEL_82801FB_IDE:
case PCI_PRODUCT_INTEL_82801G_IDE:
case PCI_PRODUCT_INTEL_82801HBM_IDE:
sc->sc_wdcdev.sc_atac.atac_udma_cap = 5;
break;
default:
sc->sc_wdcdev.sc_atac.atac_udma_cap = 2;
}
if (sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82371FB_IDE)
sc->sc_wdcdev.sc_atac.atac_set_modes = piix_setup_channel;
else
sc->sc_wdcdev.sc_atac.atac_set_modes = piix3_4_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
sc->sc_wdcdev.wdc_maxdrives = 2;
/* 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] =
uimin(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] =
uimin(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);
}
/* setup DTE, PPE, IE and TIME field based on PIO mode */
static u_int32_t
piix_setup_idetim_drvs(struct ata_drive_datas *drvp)
{
u_int32_t ret = 0;
struct ata_channel *chp = drvp->chnl_softc;
u_int8_t channel = chp->ch_channel;
u_int8_t drive = drvp->drive;
/*
* If drive is using UDMA, timings setups are independent
* So just check DMA and PIO here.
*/
if (drvp->drive_flags & ATA_DRIVE_DMA) {
/* if mode = DMA mode 0, use compatible timings */
if ((drvp->drive_flags & ATA_DRIVE_DMA) &&
drvp->DMA_mode == 0) {
drvp->PIO_mode = 0;
return ret;
}
ret = PIIX_IDETIM_SET(ret, PIIX_IDETIM_TIME(drive), channel);
/*
* PIO and DMA timings are the same, use fast timings for PIO
* too, else use compat timings.
*/
if ((piix_isp_pio[drvp->PIO_mode] !=
piix_isp_dma[drvp->DMA_mode]) ||
(piix_rtc_pio[drvp->PIO_mode] !=
piix_rtc_dma[drvp->DMA_mode]))
drvp->PIO_mode = 0;
/* if PIO mode <= 2, use compat timings for PIO */
if (drvp->PIO_mode <= 2) {
ret = PIIX_IDETIM_SET(ret, PIIX_IDETIM_DTE(drive),
channel);
return ret;
}
}
/*
* Now setup PIO modes. If mode < 2, use compat timings.
* Else enable fast timings. Enable IORDY and prefetch/post
* if PIO mode >= 3.
*/
if (drvp->PIO_mode < 2)
return ret;
ret = PIIX_IDETIM_SET(ret, PIIX_IDETIM_TIME(drive), channel);
if (drvp->PIO_mode >= 3) {
ret = PIIX_IDETIM_SET(ret, PIIX_IDETIM_IE(drive), channel);
ret = PIIX_IDETIM_SET(ret, PIIX_IDETIM_PPE(drive), channel);
}
return ret;
}
/* setup values in SIDETIM registers, based on mode */
static u_int32_t
piix_setup_sidetim_timings(u_int8_t mode, u_int8_t dma, u_int8_t channel)
{
if (dma)
return PIIX_SIDETIM_ISP_SET(piix_isp_dma[mode], channel) |
PIIX_SIDETIM_RTC_SET(piix_rtc_dma[mode], channel);
else
return PIIX_SIDETIM_ISP_SET(piix_isp_pio[mode], channel) |
PIIX_SIDETIM_RTC_SET(piix_rtc_pio[mode], channel);
}