xref: /netbsd/sys/dev/pci/iteide.c (revision 780493b6)
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