viaide.c revision 1.1 1 /* $NetBSD: viaide.c,v 1.1 2003/10/08 11:51:59 bouyer Exp $ */
2
3
4 /*
5 * Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Manuel Bouyer.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37
38 #include <dev/pci/pcivar.h>
39 #include <dev/pci/pcidevs.h>
40 #include <dev/pci/pciidereg.h>
41 #include <dev/pci/pciidevar.h>
42 #include <dev/pci/pciide_apollo_reg.h>
43
44 void via_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
45 void via_sata_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
46 void via_setup_channel __P((struct channel_softc*));
47
48 int viaide_match __P((struct device *, struct cfdata *, void *));
49 void viaide_attach __P((struct device *, struct device *, void *));
50
51 CFATTACH_DECL(viaide, sizeof(struct pciide_softc),
52 viaide_match, viaide_attach, NULL, NULL);
53
54 const struct pciide_product_desc pciide_amd_products[] = {
55 { PCI_PRODUCT_AMD_PBC756_IDE,
56 0,
57 "Advanced Micro Devices AMD756 IDE Controller",
58 via_chip_map
59 },
60 { PCI_PRODUCT_AMD_PBC766_IDE,
61 0,
62 "Advanced Micro Devices AMD766 IDE Controller",
63 via_chip_map
64 },
65 { PCI_PRODUCT_AMD_PBC768_IDE,
66 0,
67 "Advanced Micro Devices AMD768 IDE Controller",
68 via_chip_map
69 },
70 { PCI_PRODUCT_AMD_PBC8111_IDE,
71 0,
72 "Advanced Micro Devices AMD8111 IDE Controller",
73 via_chip_map
74 },
75 { 0,
76 0,
77 NULL,
78 NULL
79 }
80 };
81
82 const struct pciide_product_desc pciide_nvidia_products[] = {
83 { PCI_PRODUCT_NVIDIA_NFORCE_ATA100,
84 0,
85 "NVIDIA nForce IDE Controller",
86 via_chip_map
87 },
88 { PCI_PRODUCT_NVIDIA_NFORCE2_ATA133,
89 0,
90 "NVIDIA nForce2 IDE Controller",
91 via_chip_map
92 },
93 { 0,
94 0,
95 NULL,
96 NULL
97 }
98 };
99
100 const struct pciide_product_desc pciide_via_products[] = {
101 { PCI_PRODUCT_VIATECH_VT82C586_IDE,
102 0,
103 NULL,
104 via_chip_map,
105 },
106 { PCI_PRODUCT_VIATECH_VT82C586A_IDE,
107 0,
108 NULL,
109 via_chip_map,
110 },
111 { PCI_PRODUCT_VIATECH_VT8237_SATA,
112 IDE_PCI_CLASS_OVERRIDE,
113 "VIA Technologies VT8237 SATA Controller",
114 via_sata_chip_map,
115 },
116 { 0,
117 0,
118 NULL,
119 NULL
120 }
121 };
122
123 int
124 viaide_match(parent, match, aux)
125 struct device *parent;
126 struct cfdata *match;
127 void *aux;
128 {
129 struct pci_attach_args *pa = aux;
130
131 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VIATECH) {
132 if (pciide_lookup_product(pa->pa_id, pciide_via_products))
133 return (2);
134 }
135 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD) {
136 if (pciide_lookup_product(pa->pa_id, pciide_amd_products))
137 return (2);
138 }
139 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NVIDIA) {
140 if (pciide_lookup_product(pa->pa_id, pciide_nvidia_products))
141 return (2);
142 }
143 return (0);
144 }
145
146 void
147 viaide_attach(parent, self, aux)
148 struct device *parent, *self;
149 void *aux;
150 {
151 struct pci_attach_args *pa = aux;
152 struct pciide_softc *sc = (struct pciide_softc *)self;
153 const struct pciide_product_desc *pp = NULL;
154
155 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VIATECH)
156 pp = pciide_lookup_product(pa->pa_id, pciide_via_products);
157 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD)
158 pp = pciide_lookup_product(pa->pa_id, pciide_amd_products);
159 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NVIDIA)
160 pp = pciide_lookup_product(pa->pa_id, pciide_nvidia_products);
161 if (pp == NULL)
162 panic("viaide_attach");
163 pciide_common_attach(sc, pa, pp);
164 }
165
166 void
167 via_chip_map(sc, pa)
168 struct pciide_softc *sc;
169 struct pci_attach_args *pa;
170 {
171 struct pciide_channel *cp;
172 pcireg_t interface = PCI_INTERFACE(pa->pa_class);
173 pcireg_t vendor = PCI_VENDOR(pa->pa_id);
174 int channel;
175 u_int32_t ideconf;
176 bus_size_t cmdsize, ctlsize;
177 pcitag_t pcib_tag;
178 pcireg_t pcib_id, pcib_class;
179
180 if (pciide_chipen(sc, pa) == 0)
181 return;
182
183 switch(vendor) {
184 case PCI_VENDOR_VIATECH:
185 /*
186 * get a PCI tag for the ISA bridge (function 0 of the
187 * same device)
188 */
189 pcib_tag =
190 pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device, 0);
191 /* and read ID and rev of the ISA bridge */
192 pcib_id = pci_conf_read(sc->sc_pc, pcib_tag, PCI_ID_REG);
193 pcib_class = pci_conf_read(sc->sc_pc, pcib_tag, PCI_CLASS_REG);
194 aprint_normal("%s: VIA Technologies ",
195 sc->sc_wdcdev.sc_dev.dv_xname);
196 switch (PCI_PRODUCT(pcib_id)) {
197 case PCI_PRODUCT_VIATECH_VT82C586_ISA:
198 aprint_normal("VT82C586 (Apollo VP) ");
199 if(PCI_REVISION(pcib_class) >= 0x02) {
200 aprint_normal("ATA33 controller\n");
201 sc->sc_wdcdev.UDMA_cap = 2;
202 } else {
203 aprint_normal("controller\n");
204 sc->sc_wdcdev.UDMA_cap = 0;
205 }
206 break;
207 case PCI_PRODUCT_VIATECH_VT82C596A:
208 aprint_normal("VT82C596A (Apollo Pro) ");
209 if (PCI_REVISION(pcib_class) >= 0x12) {
210 aprint_normal("ATA66 controller\n");
211 sc->sc_wdcdev.UDMA_cap = 4;
212 } else {
213 aprint_normal("ATA33 controller\n");
214 sc->sc_wdcdev.UDMA_cap = 2;
215 }
216 break;
217 case PCI_PRODUCT_VIATECH_VT82C686A_ISA:
218 aprint_normal("VT82C686A (Apollo KX133) ");
219 if (PCI_REVISION(pcib_class) >= 0x40) {
220 aprint_normal("ATA100 controller\n");
221 sc->sc_wdcdev.UDMA_cap = 5;
222 } else {
223 aprint_normal("ATA66 controller\n");
224 sc->sc_wdcdev.UDMA_cap = 4;
225 }
226 break;
227 case PCI_PRODUCT_VIATECH_VT8231:
228 aprint_normal("VT8231 ATA100 controller\n");
229 sc->sc_wdcdev.UDMA_cap = 5;
230 break;
231 case PCI_PRODUCT_VIATECH_VT8233:
232 aprint_normal("VT8233 ATA100 controller\n");
233 sc->sc_wdcdev.UDMA_cap = 5;
234 break;
235 case PCI_PRODUCT_VIATECH_VT8233A:
236 aprint_normal("VT8233A ATA133 controller\n");
237 sc->sc_wdcdev.UDMA_cap = 6;
238 break;
239 case PCI_PRODUCT_VIATECH_VT8235:
240 aprint_normal("VT8235 ATA133 controller\n");
241 sc->sc_wdcdev.UDMA_cap = 6;
242 break;
243 case PCI_PRODUCT_VIATECH_VT8237_SATA:
244 aprint_normal("VT8237 ATA133 controller\n");
245 sc->sc_wdcdev.UDMA_cap = 6;
246 break;
247 default:
248 aprint_normal("unknown VIA ATA controller\n");
249 sc->sc_wdcdev.UDMA_cap = 0;
250 }
251 sc->sc_apo_regbase = APO_VIA_REGBASE;
252 break;
253 case PCI_VENDOR_AMD:
254 switch (sc->sc_pp->ide_product) {
255 case PCI_PRODUCT_AMD_PBC766_IDE:
256 case PCI_PRODUCT_AMD_PBC768_IDE:
257 case PCI_PRODUCT_AMD_PBC8111_IDE:
258 sc->sc_wdcdev.UDMA_cap = 5;
259 break;
260 default:
261 sc->sc_wdcdev.UDMA_cap = 4;
262 }
263 sc->sc_apo_regbase = APO_AMD_REGBASE;
264 break;
265 case PCI_VENDOR_NVIDIA:
266 switch (sc->sc_pp->ide_product) {
267 case PCI_PRODUCT_NVIDIA_NFORCE_ATA100:
268 sc->sc_wdcdev.UDMA_cap = 5;
269 break;
270 case PCI_PRODUCT_NVIDIA_NFORCE2_ATA133:
271 sc->sc_wdcdev.UDMA_cap = 6;
272 break;
273 }
274 sc->sc_apo_regbase = APO_NVIDIA_REGBASE;
275 break;
276 default:
277 panic("via_chip_map: unknown vendor");
278 }
279
280 aprint_normal("%s: bus-master DMA support present",
281 sc->sc_wdcdev.sc_dev.dv_xname);
282 pciide_mapreg_dma(sc, pa);
283 aprint_normal("\n");
284 sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
285 WDC_CAPABILITY_MODE;
286 if (sc->sc_dma_ok) {
287 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_IRQACK;
288 sc->sc_wdcdev.irqack = pciide_irqack;
289 if (sc->sc_wdcdev.UDMA_cap > 0)
290 sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA;
291 }
292 sc->sc_wdcdev.PIO_cap = 4;
293 sc->sc_wdcdev.DMA_cap = 2;
294 sc->sc_wdcdev.set_modes = via_setup_channel;
295 sc->sc_wdcdev.channels = sc->wdc_chanarray;
296 sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
297
298 WDCDEBUG_PRINT(("via_chip_map: old APO_IDECONF=0x%x, "
299 "APO_CTLMISC=0x%x, APO_DATATIM=0x%x, APO_UDMA=0x%x\n",
300 pci_conf_read(sc->sc_pc, sc->sc_tag, APO_IDECONF(sc)),
301 pci_conf_read(sc->sc_pc, sc->sc_tag, APO_CTLMISC(sc)),
302 pci_conf_read(sc->sc_pc, sc->sc_tag, APO_DATATIM(sc)),
303 pci_conf_read(sc->sc_pc, sc->sc_tag, APO_UDMA(sc))),
304 DEBUG_PROBE);
305
306 ideconf = pci_conf_read(sc->sc_pc, sc->sc_tag, APO_IDECONF(sc));
307 for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
308 cp = &sc->pciide_channels[channel];
309 if (pciide_chansetup(sc, channel, interface) == 0)
310 continue;
311
312 if ((ideconf & APO_IDECONF_EN(channel)) == 0) {
313 aprint_normal("%s: %s channel ignored (disabled)\n",
314 sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
315 cp->wdc_channel.ch_flags |= WDCF_DISABLED;
316 continue;
317 }
318 pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
319 pciide_pci_intr);
320 }
321 }
322
323 void
324 via_setup_channel(chp)
325 struct channel_softc *chp;
326 {
327 u_int32_t udmatim_reg, datatim_reg;
328 u_int8_t idedma_ctl;
329 int mode, drive;
330 struct ata_drive_datas *drvp;
331 struct pciide_channel *cp = (struct pciide_channel*)chp;
332 struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
333 #ifndef PCIIDE_AMD756_ENABLEDMA
334 int rev = PCI_REVISION(
335 pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG));
336 #endif
337
338
339 idedma_ctl = 0;
340 datatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, APO_DATATIM(sc));
341 udmatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, APO_UDMA(sc));
342 datatim_reg &= ~APO_DATATIM_MASK(chp->channel);
343 udmatim_reg &= ~APO_UDMA_MASK(chp->channel);
344
345 /* setup DMA if needed */
346 pciide_channel_dma_setup(cp);
347
348 for (drive = 0; drive < 2; drive++) {
349 drvp = &chp->ch_drive[drive];
350 /* If no drive, skip */
351 if ((drvp->drive_flags & DRIVE) == 0)
352 continue;
353 /* add timing values, setup DMA if needed */
354 if (((drvp->drive_flags & DRIVE_DMA) == 0 &&
355 (drvp->drive_flags & DRIVE_UDMA) == 0)) {
356 mode = drvp->PIO_mode;
357 goto pio;
358 }
359 if ((chp->wdc->cap & WDC_CAPABILITY_UDMA) &&
360 (drvp->drive_flags & DRIVE_UDMA)) {
361 /* use Ultra/DMA */
362 drvp->drive_flags &= ~DRIVE_DMA;
363 udmatim_reg |= APO_UDMA_EN(chp->channel, drive) |
364 APO_UDMA_EN_MTH(chp->channel, drive);
365 switch(PCI_VENDOR(sc->sc_pci_id)) {
366 case PCI_VENDOR_VIATECH:
367 if (sc->sc_wdcdev.UDMA_cap == 6) {
368 /* 8233a */
369 udmatim_reg |= APO_UDMA_TIME(
370 chp->channel,
371 drive,
372 via_udma133_tim[drvp->UDMA_mode]);
373 } else if (sc->sc_wdcdev.UDMA_cap == 5) {
374 /* 686b */
375 udmatim_reg |= APO_UDMA_TIME(
376 chp->channel,
377 drive,
378 via_udma100_tim[drvp->UDMA_mode]);
379 } else if (sc->sc_wdcdev.UDMA_cap == 4) {
380 /* 596b or 686a */
381 udmatim_reg |= APO_UDMA_CLK66(
382 chp->channel);
383 udmatim_reg |= APO_UDMA_TIME(
384 chp->channel,
385 drive,
386 via_udma66_tim[drvp->UDMA_mode]);
387 } else {
388 /* 596a or 586b */
389 udmatim_reg |= APO_UDMA_TIME(
390 chp->channel,
391 drive,
392 via_udma33_tim[drvp->UDMA_mode]);
393 }
394 break;
395 case PCI_VENDOR_AMD:
396 case PCI_VENDOR_NVIDIA:
397 udmatim_reg |= APO_UDMA_TIME(chp->channel,
398 drive, amd7x6_udma_tim[drvp->UDMA_mode]);
399 break;
400 }
401 /* can use PIO timings, MW DMA unused */
402 mode = drvp->PIO_mode;
403 } else {
404 /* use Multiword DMA, but only if revision is OK */
405 drvp->drive_flags &= ~DRIVE_UDMA;
406 #ifndef PCIIDE_AMD756_ENABLEDMA
407 /*
408 * The workaround doesn't seem to be necessary
409 * with all drives, so it can be disabled by
410 * PCIIDE_AMD756_ENABLEDMA. It causes a hard hang if
411 * triggered.
412 */
413 if (PCI_VENDOR(sc->sc_pci_id) == PCI_VENDOR_AMD &&
414 sc->sc_pp->ide_product ==
415 PCI_PRODUCT_AMD_PBC756_IDE &&
416 AMD756_CHIPREV_DISABLEDMA(rev)) {
417 aprint_normal(
418 "%s:%d:%d: multi-word DMA disabled due "
419 "to chip revision\n",
420 sc->sc_wdcdev.sc_dev.dv_xname,
421 chp->channel, drive);
422 mode = drvp->PIO_mode;
423 drvp->drive_flags &= ~DRIVE_DMA;
424 goto pio;
425 }
426 #endif
427 /* mode = min(pio, dma+2) */
428 if (drvp->PIO_mode <= (drvp->DMA_mode +2))
429 mode = drvp->PIO_mode;
430 else
431 mode = drvp->DMA_mode + 2;
432 }
433 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
434
435 pio: /* setup PIO mode */
436 if (mode <= 2) {
437 drvp->DMA_mode = 0;
438 drvp->PIO_mode = 0;
439 mode = 0;
440 } else {
441 drvp->PIO_mode = mode;
442 drvp->DMA_mode = mode - 2;
443 }
444 datatim_reg |=
445 APO_DATATIM_PULSE(chp->channel, drive,
446 apollo_pio_set[mode]) |
447 APO_DATATIM_RECOV(chp->channel, drive,
448 apollo_pio_rec[mode]);
449 }
450 if (idedma_ctl != 0) {
451 /* Add software bits in status register */
452 bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,
453 IDEDMA_CTL + (IDEDMA_SCH_OFFSET * chp->channel),
454 idedma_ctl);
455 }
456 pci_conf_write(sc->sc_pc, sc->sc_tag, APO_DATATIM(sc), datatim_reg);
457 pci_conf_write(sc->sc_pc, sc->sc_tag, APO_UDMA(sc), udmatim_reg);
458 WDCDEBUG_PRINT(("via_chip_map: APO_DATATIM=0x%x, APO_UDMA=0x%x\n",
459 pci_conf_read(sc->sc_pc, sc->sc_tag, APO_DATATIM(sc)),
460 pci_conf_read(sc->sc_pc, sc->sc_tag, APO_UDMA(sc))), DEBUG_PROBE);
461 }
462
463 void
464 via_sata_chip_map(sc, pa)
465 struct pciide_softc *sc;
466 struct pci_attach_args *pa;
467 {
468 struct pciide_channel *cp;
469 pcireg_t interface = PCI_INTERFACE(pa->pa_class);
470 int channel;
471 bus_size_t cmdsize, ctlsize;
472
473 if (pciide_chipen(sc, pa) == 0)
474 return;
475
476 if ( interface == 0 ) {
477 WDCDEBUG_PRINT(("via_sata_chip_map interface == 0\n"),
478 DEBUG_PROBE);
479 interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
480 PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
481 }
482
483 aprint_normal("%s: bus-master DMA support present",
484 sc->sc_wdcdev.sc_dev.dv_xname);
485 pciide_mapreg_dma(sc, pa);
486 aprint_normal("\n");
487
488 if (sc->sc_dma_ok) {
489 sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA | WDC_CAPABILITY_DMA | WDC_CAPABILITY_IRQACK;
490 sc->sc_wdcdev.irqack = pciide_irqack;
491 }
492 sc->sc_wdcdev.PIO_cap = 4;
493 sc->sc_wdcdev.DMA_cap = 2;
494 sc->sc_wdcdev.UDMA_cap = 6;
495
496 sc->sc_wdcdev.channels = sc->wdc_chanarray;
497 sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
498 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
499 WDC_CAPABILITY_MODE;
500 sc->sc_wdcdev.set_modes = sata_setup_channel;
501
502 for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
503 cp = &sc->pciide_channels[channel];
504 if (pciide_chansetup(sc, channel, interface) == 0)
505 continue;
506 pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
507 pciide_pci_intr);
508 }
509 }
510