1/*	$NetBSD: acardide.c,v 1.24 2010/11/05 18:07:24 jakllsch Exp $	*/
2
3/*-
4 * Copyright (c) 2001 Izumi Tsutsui.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD: acardide.c,v 1.24 2010/11/05 18:07:24 jakllsch Exp $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32
33#include <dev/pci/pcivar.h>
34#include <dev/pci/pcidevs.h>
35#include <dev/pci/pciidereg.h>
36#include <dev/pci/pciidevar.h>
37#include <dev/pci/pciide_acard_reg.h>
38
39static void acard_chip_map(struct pciide_softc*, const struct pci_attach_args*);
40static void acard_setup_channel(struct ata_channel*);
41#if 0 /* XXX !! */
42static int  acard_pci_intr(void *);
43#endif
44
45static int  acardide_match(device_t, cfdata_t, void *);
46static void acardide_attach(device_t, device_t, void *);
47
48CFATTACH_DECL_NEW(acardide, sizeof(struct pciide_softc),
49    acardide_match, acardide_attach, NULL, NULL);
50
51static const struct pciide_product_desc pciide_acard_products[] =  {
52	{ PCI_PRODUCT_ACARD_ATP850U,
53	  0,
54	  "Acard ATP850U Ultra33 IDE Controller",
55	  acard_chip_map,
56	},
57	{ PCI_PRODUCT_ACARD_ATP860,
58	  0,
59	  "Acard ATP860 Ultra66 IDE Controller",
60	  acard_chip_map,
61	},
62	{ PCI_PRODUCT_ACARD_ATP860A,
63	  0,
64	  "Acard ATP860-A Ultra66 IDE Controller",
65	  acard_chip_map,
66	},
67	{ PCI_PRODUCT_ACARD_ATP865,
68	  0,
69	  "Acard ATP865 Ultra133 IDE Controller",
70	  acard_chip_map,
71	},
72	{ PCI_PRODUCT_ACARD_ATP865A,
73	  0,
74	  "Acard ATP865-A Ultra133 IDE Controller",
75	  acard_chip_map,
76	},
77	{ 0,
78	  0,
79	  NULL,
80	  NULL
81	}
82};
83
84static int
85acardide_match(device_t parent, cfdata_t match, void *aux)
86{
87	struct pci_attach_args *pa = aux;
88
89	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ACARD) {
90		if (pciide_lookup_product(pa->pa_id, pciide_acard_products))
91			return (2);
92	}
93	return (0);
94}
95
96static void
97acardide_attach(device_t parent, device_t self, void *aux)
98{
99	struct pci_attach_args *pa = aux;
100	struct pciide_softc *sc = device_private(self);
101
102	sc->sc_wdcdev.sc_atac.atac_dev = self;
103
104	pciide_common_attach(sc, pa,
105	    pciide_lookup_product(pa->pa_id, pciide_acard_products));
106
107}
108
109#define	ACARD_IS_850(sc)						\
110	((sc)->sc_pp->ide_product == PCI_PRODUCT_ACARD_ATP850U)
111
112static void
113acard_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
114{
115	struct pciide_channel *cp;
116	int i;
117	pcireg_t interface;
118
119	if (pciide_chipen(sc, pa) == 0)
120		return;
121
122	/*
123	 * when the chip is in native mode it identifies itself as a
124	 * 'misc mass storage'. Fake interface in this case.
125	 */
126	if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) {
127		interface = PCI_INTERFACE(pa->pa_class);
128	} else {
129		interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
130		    PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
131	}
132
133	aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev,
134	    "bus-master DMA support present");
135	pciide_mapreg_dma(sc, pa);
136	aprint_verbose("\n");
137	sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
138
139	if (sc->sc_dma_ok) {
140		sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA;
141		sc->sc_wdcdev.irqack = pciide_irqack;
142	}
143	sc->sc_wdcdev.sc_atac.atac_pio_cap = 4;
144	sc->sc_wdcdev.sc_atac.atac_dma_cap = 2;
145	switch (sc->sc_pp->ide_product) {
146	case PCI_PRODUCT_ACARD_ATP860:
147	case PCI_PRODUCT_ACARD_ATP860A:
148		sc->sc_wdcdev.sc_atac.atac_udma_cap = 4;
149		break;
150	case PCI_PRODUCT_ACARD_ATP865:
151	case PCI_PRODUCT_ACARD_ATP865A:
152		sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
153		break;
154	default:
155		sc->sc_wdcdev.sc_atac.atac_udma_cap = 2;
156		break;
157	}
158
159	sc->sc_wdcdev.sc_atac.atac_set_modes = acard_setup_channel;
160	sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
161	sc->sc_wdcdev.sc_atac.atac_nchannels = 2;
162
163	wdc_allocate_regs(&sc->sc_wdcdev);
164
165	for (i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) {
166		cp = &sc->pciide_channels[i];
167		if (pciide_chansetup(sc, i, interface) == 0)
168			continue;
169		pciide_mapchan(pa, cp, interface, pciide_pci_intr);
170	}
171	if (!ACARD_IS_850(sc)) {
172		u_int32_t reg;
173		reg = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL);
174		reg &= ~ATP860_CTRL_INT;
175		pci_conf_write(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL, reg);
176	}
177}
178
179static void
180acard_setup_channel(struct ata_channel *chp)
181{
182	struct ata_drive_datas *drvp;
183	struct atac_softc *atac = chp->ch_atac;
184	struct pciide_channel *cp = CHAN_TO_PCHAN(chp);
185	struct pciide_softc *sc = CHAN_TO_PCIIDE(chp);
186	int channel = chp->ch_channel;
187	int drive, s;
188	u_int32_t idetime, udma_mode;
189	u_int32_t idedma_ctl;
190
191	/* setup DMA if needed */
192	pciide_channel_dma_setup(cp);
193
194	if (ACARD_IS_850(sc)) {
195		idetime = 0;
196		udma_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP850_UDMA);
197		udma_mode &= ~ATP850_UDMA_MASK(channel);
198	} else {
199		idetime = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP860_IDETIME);
200		idetime &= ~ATP860_SETTIME_MASK(channel);
201		udma_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP860_UDMA);
202		udma_mode &= ~ATP860_UDMA_MASK(channel);
203
204		/* check 80 pins cable */
205		if ((chp->ch_drive[0].drive_flags & DRIVE_UDMA) ||
206		    (chp->ch_drive[1].drive_flags & DRIVE_UDMA)) {
207			if (pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL)
208			    & ATP860_CTRL_80P(chp->ch_channel)) {
209				if (chp->ch_drive[0].UDMA_mode > 2)
210					chp->ch_drive[0].UDMA_mode = 2;
211				if (chp->ch_drive[1].UDMA_mode > 2)
212					chp->ch_drive[1].UDMA_mode = 2;
213			}
214		}
215	}
216
217	idedma_ctl = 0;
218
219	/* Per drive settings */
220	for (drive = 0; drive < 2; drive++) {
221		drvp = &chp->ch_drive[drive];
222		/* If no drive, skip */
223		if ((drvp->drive_flags & DRIVE) == 0)
224			continue;
225		/* add timing values, setup DMA if needed */
226		if ((atac->atac_cap & ATAC_CAP_UDMA) &&
227		    (drvp->drive_flags & DRIVE_UDMA)) {
228			/* use Ultra/DMA */
229			if (ACARD_IS_850(sc)) {
230				idetime |= ATP850_SETTIME(drive,
231				    acard_act_udma[drvp->UDMA_mode],
232				    acard_rec_udma[drvp->UDMA_mode]);
233				udma_mode |= ATP850_UDMA_MODE(channel, drive,
234				    acard_udma_conf[drvp->UDMA_mode]);
235			} else {
236				idetime |= ATP860_SETTIME(channel, drive,
237				    acard_act_udma[drvp->UDMA_mode],
238				    acard_rec_udma[drvp->UDMA_mode]);
239				udma_mode |= ATP860_UDMA_MODE(channel, drive,
240				    acard_udma_conf[drvp->UDMA_mode]);
241			}
242			idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
243		} else if ((atac->atac_cap & ATAC_CAP_DMA) &&
244		    (drvp->drive_flags & DRIVE_DMA)) {
245			/* use Multiword DMA */
246			s = splbio();
247			drvp->drive_flags &= ~DRIVE_UDMA;
248			splx(s);
249			if (ACARD_IS_850(sc)) {
250				idetime |= ATP850_SETTIME(drive,
251				    acard_act_dma[drvp->DMA_mode],
252				    acard_rec_dma[drvp->DMA_mode]);
253			} else {
254				idetime |= ATP860_SETTIME(channel, drive,
255				    acard_act_dma[drvp->DMA_mode],
256				    acard_rec_dma[drvp->DMA_mode]);
257			}
258			idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
259		} else {
260			/* PIO only */
261			s = splbio();
262			drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
263			splx(s);
264			if (ACARD_IS_850(sc)) {
265				idetime |= ATP850_SETTIME(drive,
266				    acard_act_pio[drvp->PIO_mode],
267				    acard_rec_pio[drvp->PIO_mode]);
268			} else {
269				idetime |= ATP860_SETTIME(channel, drive,
270				    acard_act_pio[drvp->PIO_mode],
271				    acard_rec_pio[drvp->PIO_mode]);
272			}
273		pci_conf_write(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL,
274		    pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL)
275		    | ATP8x0_CTRL_EN(channel));
276		}
277	}
278
279	if (idedma_ctl != 0) {
280		/* Add software bits in status register */
281		bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0,
282		    idedma_ctl);
283	}
284
285	if (ACARD_IS_850(sc)) {
286		pci_conf_write(sc->sc_pc, sc->sc_tag,
287		    ATP850_IDETIME(channel), idetime);
288		pci_conf_write(sc->sc_pc, sc->sc_tag, ATP850_UDMA, udma_mode);
289	} else {
290		pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_IDETIME, idetime);
291		pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_UDMA, udma_mode);
292	}
293}
294
295#if 0 /* XXX !! */
296static int
297acard_pci_intr(void *arg)
298{
299	struct pciide_softc *sc = arg;
300	struct pciide_channel *cp;
301	struct ata_channel *wdc_cp;
302	int rv = 0;
303	int dmastat, i, crv;
304
305	for (i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) {
306		cp = &sc->pciide_channels[i];
307		dmastat = bus_space_read_1(sc->sc_dma_iot,
308		    cp->dma_iohs[IDEDMA_CTL], 0);
309		if ((dmastat & IDEDMA_CTL_INTR) == 0)
310			continue;
311		wdc_cp = &cp->ata_channel;
312		if ((wdc_cp->ch_flags & ATACH_IRQ_WAIT) == 0) {
313			(void)wdcintr(wdc_cp);
314			bus_space_write_1(sc->sc_dma_iot,
315			    cp->dma_iohs[IDEDMA_CTL], 0, dmastat);
316			continue;
317		}
318		crv = wdcintr(wdc_cp);
319		if (crv == 0) {
320			printf("%s:%d: bogus intr\n",
321			    device_xname(sc->sc_wdcdev.sc_atac.atac_dev), i);
322			bus_space_write_1(sc->sc_dma_iot,
323			    cp->dma_iohs[IDEDMA_CTL], 0, dmastat);
324		} else if (crv == 1)
325			rv = 1;
326		else if (rv == 0)
327			rv = crv;
328	}
329	return rv;
330}
331#endif
332