1 | /* $NetBSD: pdcide.c,v 1.35 2013/10/07 19:51:55 jakllsch Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1999, 2000, 2001 Manuel Bouyer. |
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: pdcide.c,v 1.35 2013/10/07 19:51:55 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_pdc202xx_reg.h> |
38 | |
39 | static void pdc202xx_chip_map(struct pciide_softc *, |
40 | const struct pci_attach_args *); |
41 | static void pdc202xx_setup_channel(struct ata_channel *); |
42 | static void pdc20268_setup_channel(struct ata_channel *); |
43 | static int pdc202xx_pci_intr(void *); |
44 | static int pdc20265_pci_intr(void *); |
45 | static void pdc20262_dma_start(void *, int, int); |
46 | static int pdc20262_dma_finish(void *, int, int, int); |
47 | |
48 | static int pdcide_match(device_t, cfdata_t, void *); |
49 | static void pdcide_attach(device_t, device_t, void *); |
50 | |
51 | CFATTACH_DECL_NEW(pdcide, sizeof(struct pciide_softc), |
52 | pdcide_match, pdcide_attach, pciide_detach, NULL); |
53 | |
54 | static const struct pciide_product_desc pciide_promise_products[] = { |
55 | { PCI_PRODUCT_PROMISE_PDC20246, |
56 | 0, |
57 | "Promise Ultra33/ATA Bus Master IDE Accelerator" , |
58 | pdc202xx_chip_map, |
59 | }, |
60 | { PCI_PRODUCT_PROMISE_PDC20262, |
61 | 0, |
62 | "Promise Ultra66/ATA Bus Master IDE Accelerator" , |
63 | pdc202xx_chip_map, |
64 | }, |
65 | { PCI_PRODUCT_PROMISE_PDC20267, |
66 | 0, |
67 | "Promise Ultra100/ATA Bus Master IDE Accelerator" , |
68 | pdc202xx_chip_map, |
69 | }, |
70 | { PCI_PRODUCT_PROMISE_PDC20265, |
71 | 0, |
72 | "Promise Ultra100/ATA Bus Master IDE Accelerator" , |
73 | pdc202xx_chip_map, |
74 | }, |
75 | { PCI_PRODUCT_PROMISE_PDC20268, |
76 | 0, |
77 | "Promise Ultra100TX2/ATA Bus Master IDE Accelerator" , |
78 | pdc202xx_chip_map, |
79 | }, |
80 | { PCI_PRODUCT_PROMISE_PDC20270, |
81 | 0, |
82 | "Promise Ultra100TX2v2/ATA Bus Master IDE Accelerator" , |
83 | pdc202xx_chip_map, |
84 | }, |
85 | { PCI_PRODUCT_PROMISE_PDC20269, |
86 | 0, |
87 | "Promise Ultra133/ATA Bus Master IDE Accelerator" , |
88 | pdc202xx_chip_map, |
89 | }, |
90 | { PCI_PRODUCT_PROMISE_PDC20276, |
91 | 0, |
92 | "Promise Ultra133TX2/ATA Bus Master IDE Accelerator" , |
93 | pdc202xx_chip_map, |
94 | }, |
95 | { PCI_PRODUCT_PROMISE_PDC20275, |
96 | 0, |
97 | "Promise Ultra133/ATA Bus Master IDE Accelerator (MB)" , |
98 | pdc202xx_chip_map, |
99 | }, |
100 | { PCI_PRODUCT_PROMISE_PDC20271, |
101 | 0, |
102 | "Promise Ultra133TX2v2/ATA Bus Master IDE Accelerator" , |
103 | pdc202xx_chip_map, |
104 | }, |
105 | { PCI_PRODUCT_PROMISE_PDC20277, |
106 | 0, |
107 | "Promise Fasttrak133 Lite Bus Master IDE Accelerator" , |
108 | pdc202xx_chip_map, |
109 | }, |
110 | { 0, |
111 | 0, |
112 | NULL, |
113 | NULL |
114 | } |
115 | }; |
116 | |
117 | static int |
118 | pdcide_match(device_t parent, cfdata_t match, void *aux) |
119 | { |
120 | struct pci_attach_args *pa = aux; |
121 | |
122 | if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_PROMISE) { |
123 | if (pciide_lookup_product(pa->pa_id, pciide_promise_products)) |
124 | return (2); |
125 | } |
126 | return (0); |
127 | } |
128 | |
129 | static void |
130 | pdcide_attach(device_t parent, device_t self, void *aux) |
131 | { |
132 | struct pci_attach_args *pa = aux; |
133 | struct pciide_softc *sc = device_private(self); |
134 | |
135 | sc->sc_wdcdev.sc_atac.atac_dev = self; |
136 | |
137 | pciide_common_attach(sc, pa, |
138 | pciide_lookup_product(pa->pa_id, pciide_promise_products)); |
139 | |
140 | } |
141 | |
142 | /* Macros to test product */ |
143 | #define PDC_IS_262(sc) \ |
144 | ((sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20262 || \ |
145 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20267 || \ |
146 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20265 || \ |
147 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20268 || \ |
148 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20270 || \ |
149 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20269 || \ |
150 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20276 || \ |
151 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20275 || \ |
152 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20271 || \ |
153 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20277) |
154 | #define PDC_IS_265(sc) \ |
155 | ((sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20267 || \ |
156 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20265 || \ |
157 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20268 || \ |
158 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20270 || \ |
159 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20269 || \ |
160 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20276 || \ |
161 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20275 || \ |
162 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20271 || \ |
163 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20277) |
164 | #define PDC_IS_268(sc) \ |
165 | ((sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20268 || \ |
166 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20270 || \ |
167 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20269 || \ |
168 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20276 || \ |
169 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20275 || \ |
170 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20271 || \ |
171 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20277) |
172 | #define PDC_IS_276(sc) \ |
173 | ((sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20269 || \ |
174 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20276 || \ |
175 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20275 || \ |
176 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20271 || \ |
177 | (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20277) |
178 | |
179 | static void |
180 | pdc202xx_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) |
181 | { |
182 | struct pciide_channel *cp; |
183 | int channel; |
184 | pcireg_t interface, st, mode; |
185 | |
186 | if (!PDC_IS_268(sc)) { |
187 | st = pci_conf_read(sc->sc_pc, sc->sc_tag, PDC2xx_STATE); |
188 | ATADEBUG_PRINT(("pdc202xx_setup_chip: controller state 0x%x\n" , |
189 | st), DEBUG_PROBE); |
190 | /* turn off RAID mode */ |
191 | if (st & PDC2xx_STATE_IDERAID) { |
192 | ATADEBUG_PRINT(("pdc202xx_setup_chip: turning off RAID mode\n" ), DEBUG_PROBE); |
193 | st &= ~PDC2xx_STATE_IDERAID; |
194 | pci_conf_write(sc->sc_pc, sc->sc_tag, PDC2xx_STATE, st); |
195 | } |
196 | } else |
197 | st = PDC2xx_STATE_NATIVE | PDC262_STATE_EN(0) | PDC262_STATE_EN(1); |
198 | |
199 | if (pciide_chipen(sc, pa) == 0) |
200 | return; |
201 | |
202 | /* |
203 | * can't rely on the PCI_CLASS_REG content if the chip was in raid |
204 | * mode. We have to fake interface |
205 | */ |
206 | interface = PCIIDE_INTERFACE_SETTABLE(0) | PCIIDE_INTERFACE_SETTABLE(1); |
207 | if (st & PDC2xx_STATE_NATIVE) |
208 | interface |= PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1); |
209 | |
210 | aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
211 | "bus-master DMA support present" ); |
212 | pciide_mapreg_dma(sc, pa); |
213 | aprint_verbose("\n" ); |
214 | sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32; |
215 | if (sc->sc_dma_ok) { |
216 | sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; |
217 | sc->sc_wdcdev.irqack = pciide_irqack; |
218 | } |
219 | if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE && |
220 | PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID) |
221 | sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_RAID; |
222 | sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; |
223 | sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; |
224 | if (PDC_IS_276(sc)) |
225 | sc->sc_wdcdev.sc_atac.atac_udma_cap = 6; |
226 | else if (PDC_IS_265(sc)) |
227 | sc->sc_wdcdev.sc_atac.atac_udma_cap = 5; |
228 | else if (PDC_IS_262(sc)) |
229 | sc->sc_wdcdev.sc_atac.atac_udma_cap = 4; |
230 | else |
231 | sc->sc_wdcdev.sc_atac.atac_udma_cap = 2; |
232 | sc->sc_wdcdev.sc_atac.atac_set_modes = PDC_IS_268(sc) ? |
233 | pdc20268_setup_channel : pdc202xx_setup_channel; |
234 | sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; |
235 | sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS; |
236 | sc->sc_wdcdev.wdc_maxdrives = 2; |
237 | |
238 | wdc_allocate_regs(&sc->sc_wdcdev); |
239 | |
240 | if (sc->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20262 || |
241 | sc->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20267 || |
242 | sc->sc_pp->ide_product == PCI_PRODUCT_PROMISE_PDC20265) { |
243 | sc->sc_wdcdev.dma_start = pdc20262_dma_start; |
244 | sc->sc_wdcdev.dma_finish = pdc20262_dma_finish; |
245 | } |
246 | |
247 | if (!PDC_IS_268(sc)) { |
248 | /* setup failsafe defaults */ |
249 | mode = 0; |
250 | mode = PDC2xx_TIM_SET_PA(mode, pdc2xx_pa[0]); |
251 | mode = PDC2xx_TIM_SET_PB(mode, pdc2xx_pb[0]); |
252 | mode = PDC2xx_TIM_SET_MB(mode, pdc2xx_dma_mb[0]); |
253 | mode = PDC2xx_TIM_SET_MC(mode, pdc2xx_dma_mc[0]); |
254 | for (channel = 0; |
255 | channel < sc->sc_wdcdev.sc_atac.atac_nchannels; |
256 | channel++) { |
257 | ATADEBUG_PRINT(("pdc202xx_setup_chip: channel %d " |
258 | "drive 0 initial timings 0x%x, now 0x%x\n" , |
259 | channel, pci_conf_read(sc->sc_pc, sc->sc_tag, |
260 | PDC2xx_TIM(channel, 0)), mode | PDC2xx_TIM_IORDYp), |
261 | DEBUG_PROBE); |
262 | pci_conf_write(sc->sc_pc, sc->sc_tag, |
263 | PDC2xx_TIM(channel, 0), mode | PDC2xx_TIM_IORDYp); |
264 | ATADEBUG_PRINT(("pdc202xx_setup_chip: channel %d " |
265 | "drive 1 initial timings 0x%x, now 0x%x\n" , |
266 | channel, pci_conf_read(sc->sc_pc, sc->sc_tag, |
267 | PDC2xx_TIM(channel, 1)), mode), DEBUG_PROBE); |
268 | pci_conf_write(sc->sc_pc, sc->sc_tag, |
269 | PDC2xx_TIM(channel, 1), mode); |
270 | } |
271 | |
272 | mode = PDC2xx_SCR_DMA; |
273 | if (PDC_IS_265(sc)) { |
274 | mode = PDC2xx_SCR_SET_GEN(mode, PDC265_SCR_GEN_LAT); |
275 | } else if (PDC_IS_262(sc)) { |
276 | mode = PDC2xx_SCR_SET_GEN(mode, PDC262_SCR_GEN_LAT); |
277 | } else { |
278 | /* the BIOS set it up this way */ |
279 | mode = PDC2xx_SCR_SET_GEN(mode, 0x1); |
280 | } |
281 | mode = PDC2xx_SCR_SET_I2C(mode, 0x3); /* ditto */ |
282 | mode = PDC2xx_SCR_SET_POLL(mode, 0x1); /* ditto */ |
283 | ATADEBUG_PRINT(("pdc202xx_setup_chip: initial SCR 0x%x, " |
284 | "now 0x%x\n" , |
285 | bus_space_read_4(sc->sc_dma_iot, sc->sc_dma_ioh, |
286 | PDC2xx_SCR), |
287 | mode), DEBUG_PROBE); |
288 | bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh, |
289 | PDC2xx_SCR, mode); |
290 | |
291 | /* controller initial state register is OK even without BIOS */ |
292 | /* Set DMA mode to IDE DMA compatibility */ |
293 | mode = |
294 | bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_PM); |
295 | ATADEBUG_PRINT(("pdc202xx_setup_chip: primary mode 0x%x" , mode), |
296 | DEBUG_PROBE); |
297 | bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_PM, |
298 | mode | 0x1); |
299 | mode = |
300 | bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SM); |
301 | ATADEBUG_PRINT((", secondary mode 0x%x\n" , mode ), DEBUG_PROBE); |
302 | bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SM, |
303 | mode | 0x1); |
304 | } |
305 | for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; |
306 | channel++) { |
307 | cp = &sc->pciide_channels[channel]; |
308 | if (pciide_chansetup(sc, channel, interface) == 0) |
309 | continue; |
310 | if ((st & (PDC_IS_262(sc) ? |
311 | PDC262_STATE_EN(channel):PDC246_STATE_EN(channel))) == 0) { |
312 | aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
313 | "%s channel ignored (disabled)\n" , cp->name); |
314 | cp->ata_channel.ch_flags |= ATACH_DISABLED; |
315 | continue; |
316 | } |
317 | pciide_mapchan(pa, cp, interface, |
318 | PDC_IS_265(sc) ? pdc20265_pci_intr : pdc202xx_pci_intr); |
319 | /* clear interrupt, in case there is one pending */ |
320 | bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, |
321 | IDEDMA_CTL_INTR); |
322 | } |
323 | return; |
324 | } |
325 | |
326 | static void |
327 | pdc202xx_setup_channel(struct ata_channel *chp) |
328 | { |
329 | struct ata_drive_datas *drvp; |
330 | int drive, s; |
331 | pcireg_t mode, st; |
332 | u_int32_t idedma_ctl, scr, atapi; |
333 | struct pciide_channel *cp = CHAN_TO_PCHAN(chp); |
334 | struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); |
335 | int channel = chp->ch_channel; |
336 | |
337 | /* setup DMA if needed */ |
338 | pciide_channel_dma_setup(cp); |
339 | |
340 | idedma_ctl = 0; |
341 | ATADEBUG_PRINT(("pdc202xx_setup_channel %s: scr 0x%x\n" , |
342 | device_xname(sc->sc_wdcdev.sc_atac.atac_dev), |
343 | bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC262_U66)), |
344 | DEBUG_PROBE); |
345 | |
346 | /* Per channel settings */ |
347 | if (PDC_IS_262(sc)) { |
348 | scr = bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, |
349 | PDC262_U66); |
350 | st = pci_conf_read(sc->sc_pc, sc->sc_tag, PDC2xx_STATE); |
351 | /* Trim UDMA mode */ |
352 | if ((st & PDC262_STATE_80P(channel)) != 0 || |
353 | (chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA && |
354 | chp->ch_drive[0].UDMA_mode <= 2) || |
355 | (chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA && |
356 | chp->ch_drive[1].UDMA_mode <= 2)) { |
357 | if (chp->ch_drive[0].UDMA_mode > 2) |
358 | chp->ch_drive[0].UDMA_mode = 2; |
359 | if (chp->ch_drive[1].UDMA_mode > 2) |
360 | chp->ch_drive[1].UDMA_mode = 2; |
361 | } |
362 | /* Set U66 if needed */ |
363 | if ((chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA && |
364 | chp->ch_drive[0].UDMA_mode > 2) || |
365 | (chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA && |
366 | chp->ch_drive[1].UDMA_mode > 2)) |
367 | scr |= PDC262_U66_EN(channel); |
368 | else |
369 | scr &= ~PDC262_U66_EN(channel); |
370 | bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, |
371 | PDC262_U66, scr); |
372 | ATADEBUG_PRINT(("pdc202xx_setup_channel %s:%d: ATAPI 0x%x\n" , |
373 | device_xname(sc->sc_wdcdev.sc_atac.atac_dev), channel, |
374 | bus_space_read_4(sc->sc_dma_iot, sc->sc_dma_ioh, |
375 | PDC262_ATAPI(channel))), DEBUG_PROBE); |
376 | if (chp->ch_drive[0].drive_type == ATA_DRIVET_ATAPI || |
377 | chp->ch_drive[1].drive_type == ATA_DRIVET_ATAPI) { |
378 | if (((chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA) && |
379 | !(chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA) && |
380 | (chp->ch_drive[1].drive_flags & ATA_DRIVE_DMA)) || |
381 | ((chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA) && |
382 | !(chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA) && |
383 | (chp->ch_drive[0].drive_flags & ATA_DRIVE_DMA))) |
384 | atapi = 0; |
385 | else |
386 | atapi = PDC262_ATAPI_UDMA; |
387 | bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh, |
388 | PDC262_ATAPI(channel), atapi); |
389 | } |
390 | } |
391 | for (drive = 0; drive < 2; drive++) { |
392 | drvp = &chp->ch_drive[drive]; |
393 | /* If no drive, skip */ |
394 | if (drvp->drive_type == ATA_DRIVET_NONE) |
395 | continue; |
396 | mode = 0; |
397 | if (drvp->drive_flags & ATA_DRIVE_UDMA) { |
398 | /* use Ultra/DMA */ |
399 | s = splbio(); |
400 | drvp->drive_flags &= ~ATA_DRIVE_DMA; |
401 | splx(s); |
402 | mode = PDC2xx_TIM_SET_MB(mode, |
403 | pdc2xx_udma_mb[drvp->UDMA_mode]); |
404 | mode = PDC2xx_TIM_SET_MC(mode, |
405 | pdc2xx_udma_mc[drvp->UDMA_mode]); |
406 | idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); |
407 | } else if (drvp->drive_flags & ATA_DRIVE_DMA) { |
408 | mode = PDC2xx_TIM_SET_MB(mode, |
409 | pdc2xx_dma_mb[drvp->DMA_mode]); |
410 | mode = PDC2xx_TIM_SET_MC(mode, |
411 | pdc2xx_dma_mc[drvp->DMA_mode]); |
412 | idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); |
413 | } else { |
414 | mode = PDC2xx_TIM_SET_MB(mode, |
415 | pdc2xx_dma_mb[0]); |
416 | mode = PDC2xx_TIM_SET_MC(mode, |
417 | pdc2xx_dma_mc[0]); |
418 | } |
419 | mode = PDC2xx_TIM_SET_PA(mode, pdc2xx_pa[drvp->PIO_mode]); |
420 | mode = PDC2xx_TIM_SET_PB(mode, pdc2xx_pb[drvp->PIO_mode]); |
421 | if (drvp->drive_type == ATA_DRIVET_ATA) |
422 | mode |= PDC2xx_TIM_PRE; |
423 | mode |= PDC2xx_TIM_SYNC | PDC2xx_TIM_ERRDY; |
424 | if (drvp->PIO_mode >= 3) { |
425 | mode |= PDC2xx_TIM_IORDY; |
426 | if (drive == 0) |
427 | mode |= PDC2xx_TIM_IORDYp; |
428 | } |
429 | ATADEBUG_PRINT(("pdc202xx_setup_channel: %s:%d:%d " |
430 | "timings 0x%x\n" , |
431 | device_xname(sc->sc_wdcdev.sc_atac.atac_dev), |
432 | chp->ch_channel, drive, mode), DEBUG_PROBE); |
433 | pci_conf_write(sc->sc_pc, sc->sc_tag, |
434 | PDC2xx_TIM(chp->ch_channel, drive), mode); |
435 | } |
436 | if (idedma_ctl != 0) { |
437 | /* Add software bits in status register */ |
438 | bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], |
439 | 0, idedma_ctl); |
440 | } |
441 | } |
442 | |
443 | static void |
444 | pdc20268_setup_channel(struct ata_channel *chp) |
445 | { |
446 | struct ata_drive_datas *drvp; |
447 | int drive, s; |
448 | u_int32_t idedma_ctl; |
449 | struct pciide_channel *cp = CHAN_TO_PCHAN(chp); |
450 | struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); |
451 | int u100; |
452 | |
453 | /* setup DMA if needed */ |
454 | pciide_channel_dma_setup(cp); |
455 | |
456 | idedma_ctl = 0; |
457 | |
458 | /* I don't know what this is for, FreeBSD does it ... */ |
459 | bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, |
460 | IDEDMA_CMD + 0x1 + IDEDMA_SCH_OFFSET * chp->ch_channel, 0x0b); |
461 | |
462 | /* |
463 | * cable type detect, from FreeBSD |
464 | */ |
465 | u100 = (bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, |
466 | IDEDMA_CMD + 0x3 + IDEDMA_SCH_OFFSET * chp->ch_channel) & 0x04) ? |
467 | 0 : 1; |
468 | |
469 | for (drive = 0; drive < 2; drive++) { |
470 | drvp = &chp->ch_drive[drive]; |
471 | /* If no drive, skip */ |
472 | if (drvp->drive_type == ATA_DRIVET_NONE) |
473 | continue; |
474 | if (drvp->drive_flags & ATA_DRIVE_UDMA) { |
475 | /* use Ultra/DMA */ |
476 | s = splbio(); |
477 | drvp->drive_flags &= ~ATA_DRIVE_DMA; |
478 | splx(s); |
479 | idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); |
480 | if (drvp->UDMA_mode > 2 && u100 == 0) |
481 | drvp->UDMA_mode = 2; |
482 | } else if (drvp->drive_flags & ATA_DRIVE_DMA) { |
483 | idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); |
484 | } |
485 | } |
486 | /* nothing to do to setup modes, the controller snoop SET_FEATURE cmd */ |
487 | if (idedma_ctl != 0) { |
488 | /* Add software bits in status register */ |
489 | bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], |
490 | 0, idedma_ctl); |
491 | } |
492 | } |
493 | |
494 | static int |
495 | pdc202xx_pci_intr(void *arg) |
496 | { |
497 | struct pciide_softc *sc = arg; |
498 | struct pciide_channel *cp; |
499 | struct ata_channel *wdc_cp; |
500 | int i, rv, crv; |
501 | u_int32_t scr; |
502 | |
503 | rv = 0; |
504 | scr = bus_space_read_4(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SCR); |
505 | for (i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) { |
506 | cp = &sc->pciide_channels[i]; |
507 | wdc_cp = &cp->ata_channel; |
508 | /* If a compat channel skip. */ |
509 | if (cp->compat) |
510 | continue; |
511 | if (scr & PDC2xx_SCR_INT(i)) { |
512 | crv = wdcintr(wdc_cp); |
513 | if (crv == 0) |
514 | aprint_error("%s:%d: bogus intr (reg 0x%x)\n" , |
515 | device_xname( |
516 | sc->sc_wdcdev.sc_atac.atac_dev), i, scr); |
517 | else |
518 | rv = 1; |
519 | } |
520 | } |
521 | return rv; |
522 | } |
523 | |
524 | static int |
525 | pdc20265_pci_intr(void *arg) |
526 | { |
527 | struct pciide_softc *sc = arg; |
528 | struct pciide_channel *cp; |
529 | struct ata_channel *wdc_cp; |
530 | int i, rv, crv; |
531 | u_int32_t dmastat; |
532 | |
533 | rv = 0; |
534 | for (i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) { |
535 | cp = &sc->pciide_channels[i]; |
536 | wdc_cp = &cp->ata_channel; |
537 | /* If a compat channel skip. */ |
538 | if (cp->compat) |
539 | continue; |
540 | #if 0 |
541 | bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, IDEDMA_CMD + 0x1 + IDEDMA_SCH_OFFSET * i, 0x0b); |
542 | if ((bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, IDEDMA_CMD + 0x3 + IDEDMA_SCH_OFFSET * i) & 0x20) == 0) |
543 | continue; |
544 | #endif |
545 | /* |
546 | * The Ultra/100 seems to assert PDC2xx_SCR_INT * spuriously, |
547 | * however it asserts INT in IDEDMA_CTL even for non-DMA ops. |
548 | * So use it instead (requires 2 reg reads instead of 1, |
549 | * but we can't do it another way). |
550 | */ |
551 | dmastat = bus_space_read_1(sc->sc_dma_iot, |
552 | cp->dma_iohs[IDEDMA_CTL], 0); |
553 | if((dmastat & IDEDMA_CTL_INTR) == 0) |
554 | continue; |
555 | crv = wdcintr(wdc_cp); |
556 | if (crv == 0) |
557 | aprint_error("%s:%d: bogus intr\n" , |
558 | device_xname(sc->sc_wdcdev.sc_atac.atac_dev), i); |
559 | else |
560 | rv = 1; |
561 | } |
562 | return rv; |
563 | } |
564 | |
565 | static void |
566 | pdc20262_dma_start(void *v, int channel, int drive) |
567 | { |
568 | struct pciide_softc *sc = v; |
569 | struct pciide_dma_maps *dma_maps = |
570 | &sc->pciide_channels[channel].dma_maps[drive]; |
571 | int atapi; |
572 | |
573 | if (dma_maps->dma_flags & WDC_DMA_LBA48) { |
574 | atapi = (dma_maps->dma_flags & WDC_DMA_READ) ? |
575 | PDC262_ATAPI_LBA48_READ : PDC262_ATAPI_LBA48_WRITE; |
576 | atapi |= dma_maps->dmamap_xfer->dm_mapsize >> 1; |
577 | bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh, |
578 | PDC262_ATAPI(channel), atapi); |
579 | } |
580 | |
581 | pciide_dma_start(v, channel, drive); |
582 | } |
583 | |
584 | static int |
585 | pdc20262_dma_finish(void *v, int channel, int drive, int force) |
586 | { |
587 | struct pciide_softc *sc = v; |
588 | struct pciide_dma_maps *dma_maps = |
589 | &sc->pciide_channels[channel].dma_maps[drive]; |
590 | struct ata_channel *chp; |
591 | int atapi, error; |
592 | |
593 | error = pciide_dma_finish(v, channel, drive, force); |
594 | |
595 | if (dma_maps->dma_flags & WDC_DMA_LBA48) { |
596 | chp = sc->wdc_chanarray[channel]; |
597 | atapi = 0; |
598 | if (chp->ch_drive[0].drive_type == ATA_DRIVET_ATAPI || |
599 | chp->ch_drive[1].drive_type == ATA_DRIVET_ATAPI) { |
600 | if ((!(chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA) || |
601 | (chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA) || |
602 | !(chp->ch_drive[1].drive_flags & ATA_DRIVE_DMA)) && |
603 | (!(chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA) || |
604 | (chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA) || |
605 | !(chp->ch_drive[0].drive_flags & ATA_DRIVE_DMA))) |
606 | atapi = PDC262_ATAPI_UDMA; |
607 | } |
608 | bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh, |
609 | PDC262_ATAPI(channel), atapi); |
610 | } |
611 | |
612 | return error; |
613 | } |
614 | |