iteide.c revision 1.2 1 /* $NetBSD: iteide.c,v 1.2 2005/02/27 00:27:33 perry Exp $ */
2
3 /*
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Grant Beattie.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35
36 #include <dev/pci/pcivar.h>
37 #include <dev/pci/pcidevs.h>
38 #include <dev/pci/pciidereg.h>
39 #include <dev/pci/pciidevar.h>
40 #include <dev/pci/pciide_ite_reg.h>
41
42 static void ite_chip_map(struct pciide_softc*, struct pci_attach_args*);
43 static void ite_setup_channel(struct ata_channel*);
44
45 static int iteide_match(struct device *, struct cfdata *, void *);
46 static void iteide_attach(struct device *, struct device *, void *);
47
48 CFATTACH_DECL(iteide, sizeof(struct pciide_softc),
49 iteide_match, iteide_attach, NULL, NULL);
50
51 static const struct pciide_product_desc pciide_ite_products[] = {
52 { PCI_PRODUCT_ITE_IT8212,
53 0,
54 "Integrated Technology Express IDE controller",
55 ite_chip_map,
56 },
57 { 0,
58 0,
59 NULL,
60 NULL
61 }
62 };
63
64 static int
65 iteide_match(struct device *parent, struct cfdata *match, void *aux)
66 {
67 struct pci_attach_args *pa = aux;
68 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ITE &&
69 PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE) {
70 if (pciide_lookup_product(pa->pa_id, pciide_ite_products))
71 return (2);
72 }
73 return (0);
74 }
75
76 static void
77 iteide_attach(struct device *parent, struct device *self, void *aux)
78 {
79 struct pci_attach_args *pa = aux;
80 struct pciide_softc *sc = (struct pciide_softc *)self;
81
82 pciide_common_attach(sc, pa,
83 pciide_lookup_product(pa->pa_id, pciide_ite_products));
84 }
85
86 static void
87 ite_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
88 {
89 struct pciide_channel *cp;
90 int channel;
91 pcireg_t interface;
92 bus_size_t cmdsize, ctlsize;
93 pcireg_t cfg, modectl;
94
95 /* fake interface since IT8212 claims to be a RAID device */
96 interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
97 PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
98
99 cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG);
100 modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE);
101 ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n",
102 sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, cfg & IT_CFG_MASK,
103 modectl & IT_MODE_MASK), DEBUG_PROBE);
104
105 if (pciide_chipen(sc, pa) == 0)
106 return;
107
108 aprint_normal("%s: bus-master DMA support present",
109 sc->sc_wdcdev.sc_atac.atac_dev.dv_xname);
110 pciide_mapreg_dma(sc, pa);
111 aprint_normal("\n");
112
113 sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
114
115 if (sc->sc_dma_ok) {
116 sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA;
117 sc->sc_wdcdev.irqack = pciide_irqack;
118 }
119 sc->sc_wdcdev.sc_atac.atac_pio_cap = 4;
120 sc->sc_wdcdev.sc_atac.atac_dma_cap = 2;
121 sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
122
123 sc->sc_wdcdev.sc_atac.atac_set_modes = ite_setup_channel;
124 sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
125 sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
126
127 wdc_allocate_regs(&sc->sc_wdcdev);
128
129 /* Disable RAID */
130 modectl &= ~IT_MODE_RAID1;
131 /* Disable CPU firmware mode */
132 modectl &= ~IT_MODE_CPU;
133
134 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl);
135
136 for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; channel++) {
137 cp = &sc->pciide_channels[channel];
138
139 if (pciide_chansetup(sc, channel, interface) == 0)
140 continue;
141
142 pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
143 pciide_pci_intr);
144 }
145 /* Re-read configuration registers after channels setup */
146 cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG);
147 modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE);
148 ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n",
149 sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, cfg & IT_CFG_MASK,
150 modectl & IT_MODE_MASK), DEBUG_PROBE);
151 }
152
153 static void
154 ite_setup_channel(struct ata_channel *chp)
155 {
156 struct ata_drive_datas *drvp;
157 int drive, mode = 0;
158 u_int32_t idedma_ctl;
159 struct pciide_channel *cp = CHAN_TO_PCHAN(chp);
160 struct pciide_softc *sc = CHAN_TO_PCIIDE(chp);
161 int channel = chp->ch_channel;
162 pcireg_t cfg, modectl;
163 pcireg_t tim;
164
165 cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG);
166 modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE);
167 tim = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_TIM(channel));
168 ATADEBUG_PRINT(("%s:%d: tim=0x%x\n",
169 sc->sc_wdcdev.sc_atac.atac_dev.dv_xname,
170 channel, tim), DEBUG_PROBE);
171
172 /* Setup DMA if needed */
173 pciide_channel_dma_setup(cp);
174
175 /* Clear all bits for this channel */
176 idedma_ctl = 0;
177
178 /* Per channel settings */
179 for (drive = 0; drive < 2; drive++) {
180 drvp = &chp->ch_drive[drive];
181
182 /* If no drive, skip */
183 if ((drvp->drive_flags & DRIVE) == 0)
184 continue;
185
186 if ((chp->ch_atac->atac_cap & ATAC_CAP_UDMA) != 0 &&
187 (drvp->drive_flags & DRIVE_UDMA) != 0) {
188 /* Setup UltraDMA mode */
189 drvp->drive_flags &= ~DRIVE_DMA;
190 modectl &= ~IT_MODE_DMA(channel, drive);
191
192 #if 0
193 /* Check cable, only works in CPU firmware mode */
194 if (drvp->UDMA_mode > 2 &&
195 (cfg & IT_CFG_CABLE(channel, drive)) == 0) {
196 ATADEBUG_PRINT(("(%s:%d:%d): "
197 "80-wire cable not detected\n",
198 sc->sc_wdcdev.sc_atac.atac_dev.dv_xname,
199 channel, drive), DEBUG_PROBE);
200 drvp->UDMA_mode = 2;
201 }
202 #endif
203
204 if (drvp->UDMA_mode >= 5)
205 tim |= IT_TIM_UDMA5(drive);
206 else
207 tim &= ~IT_TIM_UDMA5(drive);
208
209 mode = drvp->PIO_mode;
210 } else if ((chp->ch_atac->atac_cap & ATAC_CAP_DMA) != 0 &&
211 (drvp->drive_flags & DRIVE_DMA) != 0) {
212 /* Setup multiword DMA mode */
213 drvp->drive_flags &= ~DRIVE_UDMA;
214 modectl |= IT_MODE_DMA(channel, drive);
215
216 /* mode = min(pio, dma + 2) */
217 if (drvp->PIO_mode <= (drvp->DMA_mode + 2))
218 mode = drvp->PIO_mode;
219 else
220 mode = drvp->DMA_mode + 2;
221 } else {
222 goto pio;
223 }
224 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
225
226 pio:
227 /* Setup PIO mode */
228 if (mode <= 2) {
229 drvp->DMA_mode = 0;
230 drvp->PIO_mode = 0;
231 mode = 0;
232 } else {
233 drvp->PIO_mode = mode;
234 drvp->DMA_mode = mode - 2;
235 }
236
237 /* Enable IORDY if PIO mode >= 3 */
238 if (drvp->PIO_mode >= 3)
239 cfg |= IT_CFG_IORDY(channel);
240 }
241
242 ATADEBUG_PRINT(("%s: tim=0x%x\n",
243 sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, tim), DEBUG_PROBE);
244
245 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_CFG, cfg);
246 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl);
247 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_TIM(channel), tim);
248
249 if (idedma_ctl != 0) {
250 /* Add software bits in status register */
251 bus_space_write_1(sc->sc_dma_iot,
252 cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl);
253 }
254 }
255