static int cmd_pci_intr(void *arg) { struct pciide_softc *sc = arg; struct pciide_channel *cp; struct wdc_channel *wdc_cp; int i, rv, crv; u_int32_t priirq, secirq; rv = 0; priirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CONF); secirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_ARTTIM23); for (i = 0; i < sc->sc_wdcdev.nchannels; i++) { cp = &sc->pciide_channels[i]; wdc_cp = &cp->wdc_channel; /* If a compat channel skip. */ if (cp->compat) continue; if ((i == 0 && (priirq & CMD_CONF_DRV0_INTR)) || (i == 1 && (secirq & CMD_ARTTIM23_IRQ))) { crv = wdcintr(wdc_cp); if (crv == 0) printf("%s:%d: bogus intr\n", sc->sc_wdcdev.sc_dev.dv_xname, i); else rv = 1; } } return rv; }
static void cmd680_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa) { int channel; if (pciide_chipen(sc, pa) == 0) return; aprint_normal("%s: bus-master DMA support present", sc->sc_wdcdev.sc_dev.dv_xname); pciide_mapreg_dma(sc, pa); aprint_normal("\n"); sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 | WDC_CAPABILITY_MODE; if (sc->sc_dma_ok) { sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_IRQACK; sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA; sc->sc_wdcdev.UDMA_cap = 6; sc->sc_wdcdev.irqack = pciide_irqack; } sc->sc_wdcdev.channels = sc->wdc_chanarray; sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS; sc->sc_wdcdev.PIO_cap = 4; sc->sc_wdcdev.DMA_cap = 2; sc->sc_wdcdev.set_modes = cmd680_setup_channel; pciide_pci_write(sc->sc_pc, sc->sc_tag, 0x80, 0x00); pciide_pci_write(sc->sc_pc, sc->sc_tag, 0x84, 0x00); pciide_pci_write(sc->sc_pc, sc->sc_tag, 0x8a, pciide_pci_read(sc->sc_pc, sc->sc_tag, 0x8a) | 0x01); for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) cmd680_channel_map(pa, sc, channel); }
static void cmd646_9_irqack(struct wdc_channel *chp) { u_int32_t priirq, secirq; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc; if (chp->ch_channel == 0) { priirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CONF); pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_CONF, priirq); } else { secirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_ARTTIM23); pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_ARTTIM23, secirq); } pciide_irqack(chp); }
static int acer_pci_intr(void *arg) { struct pciide_softc *sc = arg; struct pciide_channel *cp; struct ata_channel *wdc_cp; int i, rv, crv; u_int32_t chids; rv = 0; chids = pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_CHIDS); for (i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) { cp = &sc->pciide_channels[i]; wdc_cp = &cp->ata_channel; /* If a compat channel skip. */ if (cp->compat) continue; if (chids & ACER_CHIDS_INT(i)) { crv = wdcintr(wdc_cp); if (crv == 0) { aprint_error("%s:%d: bogus intr\n", device_xname( sc->sc_wdcdev.sc_atac.atac_dev), i); pciide_irqack(wdc_cp); } else rv = 1; } } return rv; }
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 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 opti_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) { struct pciide_channel *cp; pcireg_t interface; u_int8_t init_ctrl; int channel; if (pciide_chipen(sc, pa) == 0) return; 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); aprint_verbose("\n"); sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA32 | ATAC_CAP_DATA16; sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; if (sc->sc_dma_ok) { sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA; sc->sc_wdcdev.irqack = pciide_irqack; sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; } sc->sc_wdcdev.sc_atac.atac_set_modes = opti_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; init_ctrl = pciide_pci_read(sc->sc_pc, sc->sc_tag, OPTI_REG_INIT_CONTROL); interface = PCI_INTERFACE(pa->pa_class); wdc_allocate_regs(&sc->sc_wdcdev); for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; channel++) { cp = &sc->pciide_channels[channel]; if (pciide_chansetup(sc, channel, interface) == 0) continue; if (channel == 1 && (init_ctrl & OPTI_INIT_CONTROL_CH2_DISABLE) != 0) { aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, "%s channel ignored (disabled)\n", cp->name); cp->ata_channel.ch_flags |= ATACH_DISABLED; continue; } pciide_mapchan(pa, cp, interface, pciide_pci_intr); } }
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 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 cmd_channel_map(struct pci_attach_args *pa, struct pciide_softc *sc, int channel) { struct pciide_channel *cp = &sc->pciide_channels[channel]; bus_size_t cmdsize, ctlsize; u_int8_t ctrl = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CTRL); int interface, one_channel; /* * The 0648/0649 can be told to identify as a RAID controller. * In this case, we have to fake interface */ if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MASS_STORAGE_IDE) { interface = PCIIDE_INTERFACE_SETTABLE(0) | PCIIDE_INTERFACE_SETTABLE(1); if (pciide_pci_read(pa->pa_pc, pa->pa_tag, CMD_CONF) & CMD_CONF_DSA1) interface |= PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1); } else { interface = PCI_INTERFACE(pa->pa_class); } sc->wdc_chanarray[channel] = &cp->wdc_channel; cp->name = PCIIDE_CHANNEL_NAME(channel); cp->wdc_channel.ch_channel = channel; cp->wdc_channel.ch_wdc = &sc->sc_wdcdev; /* * Older CMD64X doesn't have independant channels */ switch (sc->sc_pp->ide_product) { case PCI_PRODUCT_CMDTECH_649: one_channel = 0; break; default: one_channel = 1; break; } if (channel > 0 && one_channel) { cp->wdc_channel.ch_queue = sc->pciide_channels[0].wdc_channel.ch_queue; } else { cp->wdc_channel.ch_queue = malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); } if (cp->wdc_channel.ch_queue == NULL) { aprint_error("%s %s channel: " "can't allocate memory for command queue", sc->sc_wdcdev.sc_dev.dv_xname, cp->name); return; } aprint_normal("%s: %s channel %s to %s mode\n", sc->sc_wdcdev.sc_dev.dv_xname, cp->name, (interface & PCIIDE_INTERFACE_SETTABLE(channel)) ? "configured" : "wired", (interface & PCIIDE_INTERFACE_PCI(channel)) ? "native-PCI" : "compatibility"); /* * with a CMD PCI64x, if we get here, the first channel is enabled: * there's no way to disable the first channel without disabling * the whole device */ if (channel != 0 && (ctrl & CMD_CTRL_2PORT) == 0) { aprint_normal("%s: %s channel ignored (disabled)\n", sc->sc_wdcdev.sc_dev.dv_xname, cp->name); cp->wdc_channel.ch_flags |= WDCF_DISABLED; return; } pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, cmd_pci_intr); }
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 acer_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) { struct pciide_channel *cp; int channel; pcireg_t cr, interface; pcireg_t rev = PCI_REVISION(pa->pa_class); struct aceride_softc *acer_sc = (struct aceride_softc *)sc; if (pciide_chipen(sc, pa) == 0) return; 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; if (rev >= 0x20) { sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA; if (rev >= 0xC7) sc->sc_wdcdev.sc_atac.atac_udma_cap = 6; else if (rev >= 0xC4) sc->sc_wdcdev.sc_atac.atac_udma_cap = 5; else if (rev >= 0xC2) sc->sc_wdcdev.sc_atac.atac_udma_cap = 4; else sc->sc_wdcdev.sc_atac.atac_udma_cap = 2; } sc->sc_wdcdev.irqack = pciide_irqack; if (rev <= 0xc4) { sc->sc_wdcdev.dma_init = acer_dma_init; aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, "using PIO transfers above 137GB as workaround for " "48bit DMA access bug, expect reduced performance\n"); } } sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; sc->sc_wdcdev.sc_atac.atac_set_modes = acer_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; pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_CDRC, (pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_CDRC) | ACER_CDRC_DMA_EN) & ~ACER_CDRC_FIFO_DISABLE); /* Enable "microsoft register bits" R/W. */ pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_CCAR3, pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_CCAR3) | ACER_CCAR3_PI); pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_CCAR1, pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_CCAR1) & ~(ACER_CHANSTATUS_RO|PCIIDE_CHAN_RO(0)|PCIIDE_CHAN_RO(1))); pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_CCAR2, pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_CCAR2) & ~ACER_CHANSTATUSREGS_RO); cr = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG); cr |= (PCIIDE_CHANSTATUS_EN << PCI_INTERFACE_SHIFT); { /* * some BIOSes (port-cats ABLE) enable native mode, but don't * setup everything correctly, so allow the forcing of * compat mode */ bool force_compat_mode; bool property_is_set; property_is_set = prop_dictionary_get_bool( device_properties(sc->sc_wdcdev.sc_atac.atac_dev), "ali1543-ide-force-compat-mode", &force_compat_mode); if (property_is_set && force_compat_mode) { cr &= ~((PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1)) << PCI_INTERFACE_SHIFT); } } pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG, cr); /* Don't use cr, re-read the real register content instead */ interface = PCI_INTERFACE(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG)); /* From linux: enable "Cable Detection" */ if (rev >= 0xC2) { pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_0x4B, pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_0x4B) | ACER_0x4B_CDETECT); } wdc_allocate_regs(&sc->sc_wdcdev); if (rev == 0xC3) { /* install reset bug workaround */ if (pci_find_device(&acer_sc->pcib_pa, acer_pcib_match) == 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "WARNING: can't find pci-isa bridge\n"); } else sc->sc_wdcdev.reset = acer_do_reset; } for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; channel++) { cp = &sc->pciide_channels[channel]; if (pciide_chansetup(sc, channel, interface) == 0) continue; if ((interface & PCIIDE_CHAN_EN(channel)) == 0) { aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, "%s channel ignored (disabled)\n", cp->name); cp->ata_channel.ch_flags |= ATACH_DISABLED; continue; } /* newer controllers seems to lack the ACER_CHIDS. Sigh */ pciide_mapchan(pa, cp, interface, (rev >= 0xC2) ? pciide_pci_intr : acer_pci_intr); } }
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 sis_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) { struct pciide_channel *cp; int channel; u_int8_t sis_ctr0 = pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_CTRL0); pcireg_t interface = PCI_INTERFACE(pa->pa_class); pcireg_t rev = PCI_REVISION(pa->pa_class); if (pciide_chipen(sc, pa) == 0) return; aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, "Silicon Integrated Systems "); pci_find_device(NULL, sis_hostbr_match); if (sis_hostbr_type_match) { if (sis_hostbr_type_match->type == SIS_TYPE_SOUTH) { pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_REG_57, pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_57) & 0x7f); if (PCI_PRODUCT(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_ID_REG)) == SIS_PRODUCT_5518) { aprint_normal("96X UDMA%d", sis_hostbr_type_match->udma_mode); sc->sis_type = SIS_TYPE_133NEW; sc->sc_wdcdev.sc_atac.atac_udma_cap = sis_hostbr_type_match->udma_mode; } else { if (pci_find_device(NULL, sis_south_match)) { sc->sis_type = SIS_TYPE_133OLD; sc->sc_wdcdev.sc_atac.atac_udma_cap = sis_hostbr_type_match->udma_mode; } else { sc->sis_type = SIS_TYPE_100NEW; sc->sc_wdcdev.sc_atac.atac_udma_cap = sis_hostbr_type_match->udma_mode; } } } else { sc->sis_type = sis_hostbr_type_match->type; sc->sc_wdcdev.sc_atac.atac_udma_cap = sis_hostbr_type_match->udma_mode; } aprint_normal("%s", sis_hostbr_type_match->name); } else { aprint_normal("5597/5598"); if (rev >= 0xd0) { sc->sc_wdcdev.sc_atac.atac_udma_cap = 2; sc->sis_type = SIS_TYPE_66; } else { sc->sc_wdcdev.sc_atac.atac_udma_cap = 0; sc->sis_type = SIS_TYPE_NOUDMA; } } aprint_normal(" IDE controller (rev. 0x%02x)\n", PCI_REVISION(pa->pa_class)); 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; if (sc->sis_type >= SIS_TYPE_66) 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; 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; switch(sc->sis_type) { case SIS_TYPE_NOUDMA: case SIS_TYPE_66: case SIS_TYPE_100OLD: sc->sc_wdcdev.sc_atac.atac_set_modes = sis_setup_channel; pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_MISC, pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_MISC) | SIS_MISC_TIM_SEL | SIS_MISC_FIFO_SIZE | SIS_MISC_GTC); break; case SIS_TYPE_100NEW: case SIS_TYPE_133OLD: sc->sc_wdcdev.sc_atac.atac_set_modes = sis_setup_channel; pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_REG_49, pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_49) | 0x01); break; case SIS_TYPE_133NEW: sc->sc_wdcdev.sc_atac.atac_set_modes = sis96x_setup_channel; pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_REG_50, pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_50) & 0xf7); pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_REG_52, pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_52) & 0xf7); break; } wdc_allocate_regs(&sc->sc_wdcdev); for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; channel++) { cp = &sc->pciide_channels[channel]; if (pciide_chansetup(sc, channel, interface) == 0) continue; if ((channel == 0 && (sis_ctr0 & SIS_CTRL0_CHAN0_EN) == 0) || (channel == 1 && (sis_ctr0 & SIS_CTRL0_CHAN1_EN) == 0)) { aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, "%s channel ignored (disabled)\n", cp->name); cp->ata_channel.ch_flags |= ATACH_DISABLED; continue; } pciide_mapchan(pa, cp, interface, pciide_pci_intr); } }