1*780493b6Sjakllsch /* $NetBSD: iteide.c,v 1.19 2013/10/07 19:51:55 jakllsch Exp $ */
29204390fSgrant
39204390fSgrant /*
49204390fSgrant * Copyright (c) 2004 The NetBSD Foundation, Inc.
59204390fSgrant *
69204390fSgrant * This code is derived from software contributed to The NetBSD Foundation
79204390fSgrant * by Grant Beattie.
89204390fSgrant *
99204390fSgrant * Redistribution and use in source and binary forms, with or without
109204390fSgrant * modification, are permitted provided that the following conditions
119204390fSgrant * are met:
129204390fSgrant * 1. Redistributions of source code must retain the above copyright
139204390fSgrant * notice, this list of conditions and the following disclaimer.
149204390fSgrant * 2. Redistributions in binary form must reproduce the above copyright
159204390fSgrant * notice, this list of conditions and the following disclaimer in the
169204390fSgrant * documentation and/or other materials provided with the distribution.
179204390fSgrant * 3. The name of the author may not be used to endorse or promote products
189204390fSgrant * derived from this software without specific prior written permission.
199204390fSgrant *
209204390fSgrant * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
219204390fSgrant * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
229204390fSgrant * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
239204390fSgrant * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
249204390fSgrant * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
259204390fSgrant * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
269204390fSgrant * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
279204390fSgrant * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
289204390fSgrant * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
299204390fSgrant * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
309204390fSgrant *
319204390fSgrant */
329204390fSgrant
33ec43f8fcSlukem #include <sys/cdefs.h>
34*780493b6Sjakllsch __KERNEL_RCSID(0, "$NetBSD: iteide.c,v 1.19 2013/10/07 19:51:55 jakllsch Exp $");
35ec43f8fcSlukem
369204390fSgrant #include <sys/param.h>
379204390fSgrant #include <sys/systm.h>
389204390fSgrant
399204390fSgrant #include <dev/pci/pcivar.h>
409204390fSgrant #include <dev/pci/pcidevs.h>
419204390fSgrant #include <dev/pci/pciidereg.h>
429204390fSgrant #include <dev/pci/pciidevar.h>
439204390fSgrant #include <dev/pci/pciide_ite_reg.h>
449204390fSgrant
4538e973e4Sdyoung static void ite_chip_map(struct pciide_softc*, const struct pci_attach_args*);
469204390fSgrant static void ite_setup_channel(struct ata_channel*);
479204390fSgrant
487aa6248cScube static int iteide_match(device_t, cfdata_t, void *);
497aa6248cScube static void iteide_attach(device_t, device_t, void *);
509204390fSgrant
517aa6248cScube CFATTACH_DECL_NEW(iteide, sizeof(struct pciide_softc),
52*780493b6Sjakllsch iteide_match, iteide_attach, pciide_detach, NULL);
539204390fSgrant
549204390fSgrant static const struct pciide_product_desc pciide_ite_products[] = {
55cc39aa8fSxtraeme { PCI_PRODUCT_ITE_IT8211,
56cc39aa8fSxtraeme 0,
57cc39aa8fSxtraeme "Integrated Technology Express IDE controller",
58cc39aa8fSxtraeme ite_chip_map,
59cc39aa8fSxtraeme },
609204390fSgrant { PCI_PRODUCT_ITE_IT8212,
619204390fSgrant 0,
629204390fSgrant "Integrated Technology Express IDE controller",
639204390fSgrant ite_chip_map,
649204390fSgrant },
659204390fSgrant { 0,
669204390fSgrant 0,
679204390fSgrant NULL,
689204390fSgrant NULL
699204390fSgrant }
709204390fSgrant };
719204390fSgrant
729204390fSgrant static int
iteide_match(device_t parent,cfdata_t match,void * aux)737aa6248cScube iteide_match(device_t parent, cfdata_t match, void *aux)
749204390fSgrant {
759204390fSgrant struct pci_attach_args *pa = aux;
769204390fSgrant if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ITE &&
779204390fSgrant PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE) {
789204390fSgrant if (pciide_lookup_product(pa->pa_id, pciide_ite_products))
799204390fSgrant return (2);
809204390fSgrant }
819204390fSgrant return (0);
829204390fSgrant }
839204390fSgrant
849204390fSgrant static void
iteide_attach(device_t parent,device_t self,void * aux)857aa6248cScube iteide_attach(device_t parent, device_t self, void *aux)
869204390fSgrant {
879204390fSgrant struct pci_attach_args *pa = aux;
887aa6248cScube struct pciide_softc *sc = device_private(self);
897aa6248cScube
907aa6248cScube sc->sc_wdcdev.sc_atac.atac_dev = self;
919204390fSgrant
929204390fSgrant pciide_common_attach(sc, pa,
939204390fSgrant pciide_lookup_product(pa->pa_id, pciide_ite_products));
949204390fSgrant }
959204390fSgrant
969204390fSgrant static void
ite_chip_map(struct pciide_softc * sc,const struct pci_attach_args * pa)9738e973e4Sdyoung ite_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
989204390fSgrant {
999204390fSgrant struct pciide_channel *cp;
1009204390fSgrant int channel;
1019204390fSgrant pcireg_t interface;
1029204390fSgrant pcireg_t cfg, modectl;
1039204390fSgrant
1049204390fSgrant /* fake interface since IT8212 claims to be a RAID device */
1059204390fSgrant interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
1069204390fSgrant PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
1079204390fSgrant
1089204390fSgrant cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG);
1099204390fSgrant modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE);
1109204390fSgrant ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n",
1117aa6248cScube device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cfg & IT_CFG_MASK,
1129204390fSgrant modectl & IT_MODE_MASK), DEBUG_PROBE);
1139204390fSgrant
1149204390fSgrant if (pciide_chipen(sc, pa) == 0)
1159204390fSgrant return;
1169204390fSgrant
1177aa6248cScube aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev,
1187aa6248cScube "bus-master DMA support present");
1199204390fSgrant pciide_mapreg_dma(sc, pa);
120b07ec3fcSad aprint_verbose("\n");
1219204390fSgrant
1229204390fSgrant sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
1239204390fSgrant
1249204390fSgrant if (sc->sc_dma_ok) {
1259204390fSgrant sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA;
1269204390fSgrant sc->sc_wdcdev.irqack = pciide_irqack;
1279204390fSgrant }
1289204390fSgrant sc->sc_wdcdev.sc_atac.atac_pio_cap = 4;
1299204390fSgrant sc->sc_wdcdev.sc_atac.atac_dma_cap = 2;
1309204390fSgrant sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
1319204390fSgrant
1329204390fSgrant sc->sc_wdcdev.sc_atac.atac_set_modes = ite_setup_channel;
1339204390fSgrant sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
1349204390fSgrant sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
135aee187e7Sbouyer sc->sc_wdcdev.wdc_maxdrives = 2;
1369204390fSgrant
1379204390fSgrant wdc_allocate_regs(&sc->sc_wdcdev);
1389204390fSgrant
1399204390fSgrant /* Disable RAID */
1409204390fSgrant modectl &= ~IT_MODE_RAID1;
1419204390fSgrant /* Disable CPU firmware mode */
1429204390fSgrant modectl &= ~IT_MODE_CPU;
1439204390fSgrant
1449204390fSgrant pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl);
1459204390fSgrant
1469204390fSgrant for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; channel++) {
1479204390fSgrant cp = &sc->pciide_channels[channel];
1489204390fSgrant
1499204390fSgrant if (pciide_chansetup(sc, channel, interface) == 0)
1509204390fSgrant continue;
1519204390fSgrant
1525947ac4eSjakllsch pciide_mapchan(pa, cp, interface, pciide_pci_intr);
1539204390fSgrant }
1549204390fSgrant /* Re-read configuration registers after channels setup */
1559204390fSgrant cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG);
1569204390fSgrant modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE);
1579204390fSgrant ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n",
1587aa6248cScube device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cfg & IT_CFG_MASK,
1599204390fSgrant modectl & IT_MODE_MASK), DEBUG_PROBE);
1609204390fSgrant }
1619204390fSgrant
1629204390fSgrant static void
ite_setup_channel(struct ata_channel * chp)1639204390fSgrant ite_setup_channel(struct ata_channel *chp)
1649204390fSgrant {
1659204390fSgrant struct ata_drive_datas *drvp;
1669204390fSgrant int drive, mode = 0;
1679204390fSgrant u_int32_t idedma_ctl;
1689204390fSgrant struct pciide_channel *cp = CHAN_TO_PCHAN(chp);
1699204390fSgrant struct pciide_softc *sc = CHAN_TO_PCIIDE(chp);
1709204390fSgrant int channel = chp->ch_channel;
1719204390fSgrant pcireg_t cfg, modectl;
1729204390fSgrant pcireg_t tim;
1739204390fSgrant
1749204390fSgrant cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG);
1759204390fSgrant modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE);
1769204390fSgrant tim = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_TIM(channel));
1779204390fSgrant ATADEBUG_PRINT(("%s:%d: tim=0x%x\n",
1787aa6248cScube device_xname(sc->sc_wdcdev.sc_atac.atac_dev),
1799204390fSgrant channel, tim), DEBUG_PROBE);
1809204390fSgrant
1819204390fSgrant /* Setup DMA if needed */
1829204390fSgrant pciide_channel_dma_setup(cp);
1839204390fSgrant
1849204390fSgrant /* Clear all bits for this channel */
1859204390fSgrant idedma_ctl = 0;
1869204390fSgrant
1879204390fSgrant /* Per channel settings */
1889204390fSgrant for (drive = 0; drive < 2; drive++) {
1899204390fSgrant drvp = &chp->ch_drive[drive];
1909204390fSgrant
1919204390fSgrant /* If no drive, skip */
192aee187e7Sbouyer if (drvp->drive_type == ATA_DRIVET_NONE)
1939204390fSgrant continue;
1949204390fSgrant
1959204390fSgrant if ((chp->ch_atac->atac_cap & ATAC_CAP_UDMA) != 0 &&
196aee187e7Sbouyer (drvp->drive_flags & ATA_DRIVE_UDMA) != 0) {
1979204390fSgrant /* Setup UltraDMA mode */
198aee187e7Sbouyer drvp->drive_flags &= ~ATA_DRIVE_DMA;
1999204390fSgrant modectl &= ~IT_MODE_DMA(channel, drive);
2009204390fSgrant
2019204390fSgrant #if 0
2029204390fSgrant /* Check cable, only works in CPU firmware mode */
2039204390fSgrant if (drvp->UDMA_mode > 2 &&
2049204390fSgrant (cfg & IT_CFG_CABLE(channel, drive)) == 0) {
2059204390fSgrant ATADEBUG_PRINT(("(%s:%d:%d): "
2069204390fSgrant "80-wire cable not detected\n",
2075f819ca3Schs device_xname(sc->sc_wdcdev.sc_atac.atac_dev),
2089204390fSgrant channel, drive), DEBUG_PROBE);
2099204390fSgrant drvp->UDMA_mode = 2;
2109204390fSgrant }
2119204390fSgrant #endif
2129204390fSgrant
2139204390fSgrant if (drvp->UDMA_mode >= 5)
2149204390fSgrant tim |= IT_TIM_UDMA5(drive);
2159204390fSgrant else
2169204390fSgrant tim &= ~IT_TIM_UDMA5(drive);
2179204390fSgrant
2189204390fSgrant mode = drvp->PIO_mode;
2199204390fSgrant } else if ((chp->ch_atac->atac_cap & ATAC_CAP_DMA) != 0 &&
220aee187e7Sbouyer (drvp->drive_flags & ATA_DRIVE_DMA) != 0) {
2219204390fSgrant /* Setup multiword DMA mode */
222aee187e7Sbouyer drvp->drive_flags &= ~ATA_DRIVE_UDMA;
2239204390fSgrant modectl |= IT_MODE_DMA(channel, drive);
2249204390fSgrant
2259204390fSgrant /* mode = min(pio, dma + 2) */
2269204390fSgrant if (drvp->PIO_mode <= (drvp->DMA_mode + 2))
2279204390fSgrant mode = drvp->PIO_mode;
2289204390fSgrant else
2299204390fSgrant mode = drvp->DMA_mode + 2;
2309204390fSgrant } else {
2319204390fSgrant goto pio;
2329204390fSgrant }
2339204390fSgrant idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
2349204390fSgrant
2359204390fSgrant pio:
2369204390fSgrant /* Setup PIO mode */
2379204390fSgrant if (mode <= 2) {
2389204390fSgrant drvp->DMA_mode = 0;
2399204390fSgrant drvp->PIO_mode = 0;
2409204390fSgrant mode = 0;
2419204390fSgrant } else {
2429204390fSgrant drvp->PIO_mode = mode;
2439204390fSgrant drvp->DMA_mode = mode - 2;
2449204390fSgrant }
2459204390fSgrant
2469204390fSgrant /* Enable IORDY if PIO mode >= 3 */
2479204390fSgrant if (drvp->PIO_mode >= 3)
2489204390fSgrant cfg |= IT_CFG_IORDY(channel);
2499204390fSgrant }
2509204390fSgrant
2519204390fSgrant ATADEBUG_PRINT(("%s: tim=0x%x\n",
2527aa6248cScube device_xname(sc->sc_wdcdev.sc_atac.atac_dev), tim), DEBUG_PROBE);
2539204390fSgrant
2549204390fSgrant pci_conf_write(sc->sc_pc, sc->sc_tag, IT_CFG, cfg);
2559204390fSgrant pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl);
2569204390fSgrant pci_conf_write(sc->sc_pc, sc->sc_tag, IT_TIM(channel), tim);
2579204390fSgrant
2589204390fSgrant if (idedma_ctl != 0) {
2599204390fSgrant /* Add software bits in status register */
2609204390fSgrant bus_space_write_1(sc->sc_dma_iot,
2619204390fSgrant cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl);
2629204390fSgrant }
2639204390fSgrant }
264