xref: /netbsd/sys/dev/pci/iteide.c (revision ec43f8fc)
1*ec43f8fcSlukem /*	$NetBSD: iteide.c,v 1.3 2005/05/24 05:25:15 lukem 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 
33*ec43f8fcSlukem #include <sys/cdefs.h>
34*ec43f8fcSlukem __KERNEL_RCSID(0, "$NetBSD: iteide.c,v 1.3 2005/05/24 05:25:15 lukem Exp $");
35*ec43f8fcSlukem 
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 
459204390fSgrant static void ite_chip_map(struct pciide_softc*, struct pci_attach_args*);
469204390fSgrant static void ite_setup_channel(struct ata_channel*);
479204390fSgrant 
489204390fSgrant static int  iteide_match(struct device *, struct cfdata *, void *);
499204390fSgrant static void iteide_attach(struct device *, struct device *, void *);
509204390fSgrant 
519204390fSgrant CFATTACH_DECL(iteide, sizeof(struct pciide_softc),
529204390fSgrant     iteide_match, iteide_attach, NULL, NULL);
539204390fSgrant 
549204390fSgrant static const struct pciide_product_desc pciide_ite_products[] =  {
559204390fSgrant 	{ PCI_PRODUCT_ITE_IT8212,
569204390fSgrant 	  0,
579204390fSgrant 	  "Integrated Technology Express IDE controller",
589204390fSgrant 	  ite_chip_map,
599204390fSgrant 	},
609204390fSgrant 	{ 0,
619204390fSgrant 	  0,
629204390fSgrant 	  NULL,
639204390fSgrant 	  NULL
649204390fSgrant 	}
659204390fSgrant };
669204390fSgrant 
679204390fSgrant static int
689204390fSgrant iteide_match(struct device *parent, struct cfdata *match, void *aux)
699204390fSgrant {
709204390fSgrant 	struct pci_attach_args *pa = aux;
719204390fSgrant 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ITE &&
729204390fSgrant 	    PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE) {
739204390fSgrant 		if (pciide_lookup_product(pa->pa_id, pciide_ite_products))
749204390fSgrant 			return (2);
759204390fSgrant 	}
769204390fSgrant 	return (0);
779204390fSgrant }
789204390fSgrant 
799204390fSgrant static void
809204390fSgrant iteide_attach(struct device *parent, struct device *self, void *aux)
819204390fSgrant {
829204390fSgrant 	struct pci_attach_args *pa = aux;
839204390fSgrant 	struct pciide_softc *sc = (struct pciide_softc *)self;
849204390fSgrant 
859204390fSgrant 	pciide_common_attach(sc, pa,
869204390fSgrant 	    pciide_lookup_product(pa->pa_id, pciide_ite_products));
879204390fSgrant }
889204390fSgrant 
899204390fSgrant static void
909204390fSgrant ite_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
919204390fSgrant {
929204390fSgrant 	struct pciide_channel *cp;
939204390fSgrant 	int channel;
949204390fSgrant 	pcireg_t interface;
959204390fSgrant 	bus_size_t cmdsize, ctlsize;
969204390fSgrant 	pcireg_t cfg, modectl;
979204390fSgrant 
989204390fSgrant 	/* fake interface since IT8212 claims to be a RAID device */
999204390fSgrant 	interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
1009204390fSgrant 	    PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
1019204390fSgrant 
1029204390fSgrant 	cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG);
1039204390fSgrant 	modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE);
1049204390fSgrant 	ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n",
1059204390fSgrant 	    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, cfg & IT_CFG_MASK,
1069204390fSgrant 	    modectl & IT_MODE_MASK), DEBUG_PROBE);
1079204390fSgrant 
1089204390fSgrant 	if (pciide_chipen(sc, pa) == 0)
1099204390fSgrant 		return;
1109204390fSgrant 
1119204390fSgrant 	aprint_normal("%s: bus-master DMA support present",
1129204390fSgrant 	    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname);
1139204390fSgrant 	pciide_mapreg_dma(sc, pa);
1149204390fSgrant 	aprint_normal("\n");
1159204390fSgrant 
1169204390fSgrant 	sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
1179204390fSgrant 
1189204390fSgrant 	if (sc->sc_dma_ok) {
1199204390fSgrant 		sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA;
1209204390fSgrant 		sc->sc_wdcdev.irqack = pciide_irqack;
1219204390fSgrant 	}
1229204390fSgrant 	sc->sc_wdcdev.sc_atac.atac_pio_cap = 4;
1239204390fSgrant 	sc->sc_wdcdev.sc_atac.atac_dma_cap = 2;
1249204390fSgrant 	sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
1259204390fSgrant 
1269204390fSgrant 	sc->sc_wdcdev.sc_atac.atac_set_modes = ite_setup_channel;
1279204390fSgrant 	sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
1289204390fSgrant 	sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
1299204390fSgrant 
1309204390fSgrant 	wdc_allocate_regs(&sc->sc_wdcdev);
1319204390fSgrant 
1329204390fSgrant 	/* Disable RAID */
1339204390fSgrant 	modectl &= ~IT_MODE_RAID1;
1349204390fSgrant 	/* Disable CPU firmware mode */
1359204390fSgrant 	modectl &= ~IT_MODE_CPU;
1369204390fSgrant 
1379204390fSgrant 	pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl);
1389204390fSgrant 
1399204390fSgrant 	for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; channel++) {
1409204390fSgrant 		cp = &sc->pciide_channels[channel];
1419204390fSgrant 
1429204390fSgrant 		if (pciide_chansetup(sc, channel, interface) == 0)
1439204390fSgrant 			continue;
1449204390fSgrant 
1459204390fSgrant 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
1469204390fSgrant 		    pciide_pci_intr);
1479204390fSgrant 	}
1489204390fSgrant 	/* Re-read configuration registers after channels setup */
1499204390fSgrant 	cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG);
1509204390fSgrant 	modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE);
1519204390fSgrant 	ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n",
1529204390fSgrant 	    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, cfg & IT_CFG_MASK,
1539204390fSgrant 	    modectl & IT_MODE_MASK), DEBUG_PROBE);
1549204390fSgrant }
1559204390fSgrant 
1569204390fSgrant static void
1579204390fSgrant ite_setup_channel(struct ata_channel *chp)
1589204390fSgrant {
1599204390fSgrant 	struct ata_drive_datas *drvp;
1609204390fSgrant 	int drive, mode = 0;
1619204390fSgrant 	u_int32_t idedma_ctl;
1629204390fSgrant 	struct pciide_channel *cp = CHAN_TO_PCHAN(chp);
1639204390fSgrant 	struct pciide_softc *sc = CHAN_TO_PCIIDE(chp);
1649204390fSgrant 	int channel = chp->ch_channel;
1659204390fSgrant 	pcireg_t cfg, modectl;
1669204390fSgrant 	pcireg_t tim;
1679204390fSgrant 
1689204390fSgrant 	cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG);
1699204390fSgrant 	modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE);
1709204390fSgrant 	tim = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_TIM(channel));
1719204390fSgrant 	ATADEBUG_PRINT(("%s:%d: tim=0x%x\n",
1729204390fSgrant 	    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname,
1739204390fSgrant 	    channel, tim), DEBUG_PROBE);
1749204390fSgrant 
1759204390fSgrant 	/* Setup DMA if needed */
1769204390fSgrant 	pciide_channel_dma_setup(cp);
1779204390fSgrant 
1789204390fSgrant 	/* Clear all bits for this channel */
1799204390fSgrant 	idedma_ctl = 0;
1809204390fSgrant 
1819204390fSgrant 	/* Per channel settings */
1829204390fSgrant 	for (drive = 0; drive < 2; drive++) {
1839204390fSgrant 		drvp = &chp->ch_drive[drive];
1849204390fSgrant 
1859204390fSgrant 		/* If no drive, skip */
1869204390fSgrant 		if ((drvp->drive_flags & DRIVE) == 0)
1879204390fSgrant 			continue;
1889204390fSgrant 
1899204390fSgrant 		if ((chp->ch_atac->atac_cap & ATAC_CAP_UDMA) != 0 &&
1909204390fSgrant 		    (drvp->drive_flags & DRIVE_UDMA) != 0) {
1919204390fSgrant 			/* Setup UltraDMA mode */
1929204390fSgrant 			drvp->drive_flags &= ~DRIVE_DMA;
1939204390fSgrant 			modectl &= ~IT_MODE_DMA(channel, drive);
1949204390fSgrant 
1959204390fSgrant #if 0
1969204390fSgrant 			/* Check cable, only works in CPU firmware mode */
1979204390fSgrant 			if (drvp->UDMA_mode > 2 &&
1989204390fSgrant 			    (cfg & IT_CFG_CABLE(channel, drive)) == 0) {
1999204390fSgrant 				ATADEBUG_PRINT(("(%s:%d:%d): "
2009204390fSgrant 				    "80-wire cable not detected\n",
2019204390fSgrant 				    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname,
2029204390fSgrant 				    channel, drive), DEBUG_PROBE);
2039204390fSgrant 				drvp->UDMA_mode = 2;
2049204390fSgrant 			}
2059204390fSgrant #endif
2069204390fSgrant 
2079204390fSgrant 			if (drvp->UDMA_mode >= 5)
2089204390fSgrant 				tim |= IT_TIM_UDMA5(drive);
2099204390fSgrant 			else
2109204390fSgrant 				tim &= ~IT_TIM_UDMA5(drive);
2119204390fSgrant 
2129204390fSgrant 			mode = drvp->PIO_mode;
2139204390fSgrant 		} else if ((chp->ch_atac->atac_cap & ATAC_CAP_DMA) != 0 &&
2149204390fSgrant 		    (drvp->drive_flags & DRIVE_DMA) != 0) {
2159204390fSgrant 			/* Setup multiword DMA mode */
2169204390fSgrant 			drvp->drive_flags &= ~DRIVE_UDMA;
2179204390fSgrant 			modectl |= IT_MODE_DMA(channel, drive);
2189204390fSgrant 
2199204390fSgrant 			/* mode = min(pio, dma + 2) */
2209204390fSgrant 			if (drvp->PIO_mode <= (drvp->DMA_mode + 2))
2219204390fSgrant 				mode = drvp->PIO_mode;
2229204390fSgrant 			else
2239204390fSgrant 				mode = drvp->DMA_mode + 2;
2249204390fSgrant 		} else {
2259204390fSgrant 			goto pio;
2269204390fSgrant 		}
2279204390fSgrant 		idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
2289204390fSgrant 
2299204390fSgrant pio:
2309204390fSgrant 		/* Setup PIO mode */
2319204390fSgrant 		if (mode <= 2) {
2329204390fSgrant 			drvp->DMA_mode = 0;
2339204390fSgrant 			drvp->PIO_mode = 0;
2349204390fSgrant 			mode = 0;
2359204390fSgrant 		} else {
2369204390fSgrant 			drvp->PIO_mode = mode;
2379204390fSgrant 			drvp->DMA_mode = mode - 2;
2389204390fSgrant 		}
2399204390fSgrant 
2409204390fSgrant 		/* Enable IORDY if PIO mode >= 3 */
2419204390fSgrant 		if (drvp->PIO_mode >= 3)
2429204390fSgrant 			cfg |= IT_CFG_IORDY(channel);
2439204390fSgrant 	}
2449204390fSgrant 
2459204390fSgrant 	ATADEBUG_PRINT(("%s: tim=0x%x\n",
2469204390fSgrant 	    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, tim), DEBUG_PROBE);
2479204390fSgrant 
2489204390fSgrant 	pci_conf_write(sc->sc_pc, sc->sc_tag, IT_CFG, cfg);
2499204390fSgrant 	pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl);
2509204390fSgrant 	pci_conf_write(sc->sc_pc, sc->sc_tag, IT_TIM(channel), tim);
2519204390fSgrant 
2529204390fSgrant 	if (idedma_ctl != 0) {
2539204390fSgrant 		/* Add software bits in status register */
2549204390fSgrant 		bus_space_write_1(sc->sc_dma_iot,
2559204390fSgrant 		    cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl);
2569204390fSgrant 	}
2579204390fSgrant }
258