/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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");
/*
* XXXSCW:
* There seem to be a couple of buggy revisions/implementations
* of the OPTi pciide chipset. This kludge seems to fix one of
* the reported problems (PR/11644) but still fails for the
* other (PR/13151), although the latter may be due to other
* issues too...
*/
if (PCI_REVISION(pa->pa_class) <= 0x12) {
aprint_verbose(" but disabled due to chip rev. <= 0x12");
sc->sc_dma_ok = 0;
} else
pciide_mapreg_dma(sc, pa);
/*
* 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;
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;
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);