1 | /* $NetBSD: ninjaata32.c,v 1.18 2012/07/31 15:50:34 bouyer Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2006 ITOH Yasufumi. |
5 | * All rights reserved. |
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 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' |
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
18 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
26 | * THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: ninjaata32.c,v 1.18 2012/07/31 15:50:34 bouyer Exp $" ); |
31 | |
32 | #include <sys/param.h> |
33 | #include <sys/kernel.h> |
34 | #include <sys/device.h> |
35 | #include <sys/proc.h> |
36 | |
37 | #include <sys/bus.h> |
38 | #include <sys/intr.h> |
39 | |
40 | #include <dev/ata/atavar.h> |
41 | #include <dev/ic/wdcreg.h> |
42 | #include <dev/ic/wdcvar.h> |
43 | |
44 | #include <dev/ic/ninjaata32reg.h> |
45 | #include <dev/ic/ninjaata32var.h> |
46 | |
47 | #ifdef NJATA32_DEBUG |
48 | #define DPRINTF(x) printf x |
49 | #else |
50 | #define DPRINTF(x) |
51 | #endif |
52 | |
53 | static void njata32_init(struct njata32_softc *, int nosleep); |
54 | static void njata32_irqack(struct ata_channel *); |
55 | static void njata32_clearirq(struct ata_channel *, int); |
56 | static void njata32_setup_channel(struct ata_channel *); |
57 | static int njata32_dma_init(void *, int channel, int drive, |
58 | void *databuf, size_t datalen, int flags); |
59 | static void njata32_piobm_start(void *, int channel, int drive, int skip, |
60 | int xferlen, int flags); |
61 | static int njata32_dma_finish(void *, int channel, int drive, int force); |
62 | static void njata32_piobm_done(void *, int channel, int drive); |
63 | |
64 | #if 0 /* ATA DMA is currently unused */ |
65 | static const uint8_t njata32_timing_dma[NJATA32_MODE_MAX_DMA + 1] = { |
66 | NJATA32_TIMING_DMA0, NJATA32_TIMING_DMA1, NJATA32_TIMING_DMA2 |
67 | }; |
68 | #endif |
69 | static const uint8_t njata32_timing_pio[NJATA32_MODE_MAX_PIO + 1] = { |
70 | NJATA32_TIMING_PIO0, NJATA32_TIMING_PIO1, NJATA32_TIMING_PIO2, |
71 | NJATA32_TIMING_PIO3, NJATA32_TIMING_PIO4 |
72 | }; |
73 | |
74 | static void |
75 | njata32_init(struct njata32_softc *sc, int nosleep) |
76 | { |
77 | |
78 | /* disable interrupts */ |
79 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
80 | NJATA32_REG_IRQ_SELECT, 0); |
81 | |
82 | /* bus reset */ |
83 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), NJATA32_REG_AS, |
84 | NJATA32_AS_WAIT0 | NJATA32_AS_BUS_RESET); |
85 | if (nosleep) |
86 | delay(50000); |
87 | else |
88 | tsleep(sc, PRIBIO, "njaini" , mstohz(50)); |
89 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), NJATA32_REG_AS, |
90 | NJATA32_AS_WAIT0); |
91 | |
92 | /* initial transfer speed */ |
93 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
94 | NJATA32_REG_TIMING, NJATA32_TIMING_PIO0 + sc->sc_atawait); |
95 | |
96 | /* setup busmaster mode */ |
97 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), NJATA32_REG_IOBM, |
98 | NJATA32_IOBM_DEFAULT); |
99 | |
100 | /* enable interrupts */ |
101 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
102 | NJATA32_REG_IRQ_SELECT, NJATA32_IRQ_XFER | NJATA32_IRQ_DEV); |
103 | } |
104 | |
105 | void |
106 | njata32_attach(struct njata32_softc *sc) |
107 | { |
108 | bus_addr_t dmaaddr; |
109 | int i, devno, error; |
110 | struct wdc_regs *wdr; |
111 | |
112 | /* |
113 | * allocate DMA resource |
114 | */ |
115 | if ((error = bus_dmamem_alloc(sc->sc_dmat, |
116 | sizeof(struct njata32_dma_page), PAGE_SIZE, 0, |
117 | &sc->sc_sgt_seg, 1, &sc->sc_sgt_nsegs, BUS_DMA_NOWAIT)) != 0) { |
118 | aprint_error("%s: unable to allocate sgt page, error = %d\n" , |
119 | NJATA32NAME(sc), error); |
120 | return; |
121 | } |
122 | if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_sgt_seg, |
123 | sc->sc_sgt_nsegs, sizeof(struct njata32_dma_page), |
124 | (void **)&sc->sc_sgtpg, |
125 | BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { |
126 | aprint_error("%s: unable to map sgt page, error = %d\n" , |
127 | NJATA32NAME(sc), error); |
128 | goto fail1; |
129 | } |
130 | if ((error = bus_dmamap_create(sc->sc_dmat, |
131 | sizeof(struct njata32_dma_page), 1, |
132 | sizeof(struct njata32_dma_page), 0, BUS_DMA_NOWAIT, |
133 | &sc->sc_dmamap_sgt)) != 0) { |
134 | aprint_error("%s: unable to create sgt DMA map, error = %d\n" , |
135 | NJATA32NAME(sc), error); |
136 | goto fail2; |
137 | } |
138 | if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_sgt, |
139 | sc->sc_sgtpg, sizeof(struct njata32_dma_page), |
140 | NULL, BUS_DMA_NOWAIT)) != 0) { |
141 | aprint_error("%s: unable to load sgt DMA map, error = %d\n" , |
142 | NJATA32NAME(sc), error); |
143 | goto fail3; |
144 | } |
145 | |
146 | dmaaddr = sc->sc_dmamap_sgt->dm_segs[0].ds_addr; |
147 | |
148 | for (devno = 0; devno < NJATA32_NUM_DEV; devno++) { |
149 | sc->sc_dev[devno].d_sgt = sc->sc_sgtpg->dp_sg[devno]; |
150 | sc->sc_dev[devno].d_sgt_dma = dmaaddr + |
151 | offsetof(struct njata32_dma_page, dp_sg[devno]); |
152 | |
153 | error = bus_dmamap_create(sc->sc_dmat, |
154 | NJATA32_MAX_XFER, /* max total map size */ |
155 | NJATA32_NUM_SG, /* max number of segments */ |
156 | NJATA32_SGT_MAXSEGLEN, /* max size of a segment */ |
157 | 0, /* boundary */ |
158 | BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, |
159 | &sc->sc_dev[devno].d_dmamap_xfer); |
160 | if (error) { |
161 | aprint_error("%s: failed to create DMA map " |
162 | "(error = %d)\n" , NJATA32NAME(sc), error); |
163 | goto fail4; |
164 | } |
165 | } |
166 | |
167 | /* device properties */ |
168 | sc->sc_wdcdev.sc_atac.atac_cap = |
169 | ATAC_CAP_DATA16 | ATAC_CAP_DATA32 | ATAC_CAP_PIOBM; |
170 | sc->sc_wdcdev.irqack = njata32_irqack; |
171 | sc->sc_wdcdev.sc_atac.atac_channels = sc->sc_wdc_chanarray; |
172 | sc->sc_wdcdev.sc_atac.atac_nchannels = NJATA32_NCHAN; /* 1 */ |
173 | sc->sc_wdcdev.sc_atac.atac_pio_cap = NJATA32_MODE_MAX_PIO; |
174 | #if 0 /* ATA DMA is currently unused */ |
175 | sc->sc_wdcdev.sc_atac.atac_dma_cap = NJATA32_MODE_MAX_DMA; |
176 | #endif |
177 | sc->sc_wdcdev.sc_atac.atac_set_modes = njata32_setup_channel; |
178 | |
179 | /* DMA control functions */ |
180 | sc->sc_wdcdev.dma_arg = sc; |
181 | sc->sc_wdcdev.dma_init = njata32_dma_init; |
182 | sc->sc_wdcdev.piobm_start = njata32_piobm_start; |
183 | sc->sc_wdcdev.dma_finish = njata32_dma_finish; |
184 | sc->sc_wdcdev.piobm_done = njata32_piobm_done; |
185 | |
186 | sc->sc_wdcdev.cap |= WDC_CAPABILITY_NO_EXTRA_RESETS; |
187 | |
188 | sc->sc_wdcdev.regs = wdr = &sc->sc_wdc_regs; |
189 | |
190 | /* only one channel */ |
191 | sc->sc_wdc_chanarray[0] = &sc->sc_ch[0].ch_ata_channel; |
192 | sc->sc_ch[0].ch_ata_channel.ch_channel = 0; |
193 | sc->sc_ch[0].ch_ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; |
194 | sc->sc_ch[0].ch_ata_channel.ch_queue = &sc->sc_wdc_chqueue; |
195 | sc->sc_wdcdev.wdc_maxdrives = 2; /* max number of drives per channel */ |
196 | |
197 | /* map ATA registers */ |
198 | for (i = 0; i < WDC_NREG; i++) { |
199 | if (bus_space_subregion(NJATA32_REGT(sc), NJATA32_REGH(sc), |
200 | NJATA32_OFFSET_WDCREGS + i, |
201 | i == wd_data ? 4 : 1, &wdr->cmd_iohs[i]) != 0) { |
202 | aprint_error("%s: couldn't subregion cmd regs\n" , |
203 | NJATA32NAME(sc)); |
204 | goto fail4; |
205 | } |
206 | } |
207 | wdc_init_shadow_regs(&sc->sc_ch[0].ch_ata_channel); |
208 | wdr->data32iot = NJATA32_REGT(sc); |
209 | wdr->data32ioh = wdr->cmd_iohs[wd_data]; |
210 | |
211 | /* map ATA ctl reg */ |
212 | wdr->ctl_iot = NJATA32_REGT(sc); |
213 | if (bus_space_subregion(NJATA32_REGT(sc), NJATA32_REGH(sc), |
214 | NJATA32_REG_WD_ALTSTATUS, 1, &wdr->ctl_ioh) != 0) { |
215 | aprint_error("%s: couldn't subregion ctl regs\n" , |
216 | NJATA32NAME(sc)); |
217 | goto fail4; |
218 | } |
219 | |
220 | sc->sc_flags |= NJATA32_CMDPG_MAPPED; |
221 | |
222 | /* use flags value as busmaster wait */ |
223 | if ((sc->sc_atawait = |
224 | (uint8_t)device_cfdata(sc->sc_wdcdev.sc_atac.atac_dev)->cf_flags)) |
225 | aprint_normal("%s: ATA wait = %#x\n" , |
226 | NJATA32NAME(sc), sc->sc_atawait); |
227 | |
228 | njata32_init(sc, cold); |
229 | |
230 | wdcattach(&sc->sc_ch[0].ch_ata_channel); |
231 | |
232 | return; |
233 | |
234 | /* |
235 | * cleanup |
236 | */ |
237 | fail4: while (--devno >= 0) { |
238 | bus_dmamap_destroy(sc->sc_dmat, |
239 | sc->sc_dev[devno].d_dmamap_xfer); |
240 | } |
241 | bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap_sgt); |
242 | fail3: bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap_sgt); |
243 | fail2: bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_sgtpg, |
244 | sizeof(struct njata32_dma_page)); |
245 | fail1: bus_dmamem_free(sc->sc_dmat, &sc->sc_sgt_seg, sc->sc_sgt_nsegs); |
246 | } |
247 | |
248 | int |
249 | njata32_detach(struct njata32_softc *sc, int flags) |
250 | { |
251 | int rv, devno; |
252 | |
253 | if (sc->sc_flags & NJATA32_CMDPG_MAPPED) { |
254 | if ((rv = wdcdetach(sc->sc_wdcdev.sc_atac.atac_dev, flags))) |
255 | return rv; |
256 | |
257 | /* free DMA resource */ |
258 | for (devno = 0; devno < NJATA32_NUM_DEV; devno++) { |
259 | bus_dmamap_destroy(sc->sc_dmat, |
260 | sc->sc_dev[devno].d_dmamap_xfer); |
261 | } |
262 | bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap_sgt); |
263 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap_sgt); |
264 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_sgtpg, |
265 | sizeof(struct njata32_dma_page)); |
266 | bus_dmamem_free(sc->sc_dmat, &sc->sc_sgt_seg, sc->sc_sgt_nsegs); |
267 | } |
268 | |
269 | return 0; |
270 | } |
271 | |
272 | static void |
273 | njata32_irqack(struct ata_channel *chp) |
274 | { |
275 | struct njata32_softc *sc = (void *)chp->ch_atac; |
276 | |
277 | /* disable busmaster */ |
278 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
279 | NJATA32_REG_BM, NJATA32_BM_WAIT0); |
280 | } |
281 | |
282 | static void |
283 | njata32_clearirq(struct ata_channel *chp, int irq) |
284 | { |
285 | struct njata32_softc *sc = (void *)chp->ch_atac; |
286 | |
287 | aprint_error("%s: unhandled intr: irq %#x, bm %#x, " , |
288 | NJATA32NAME(sc), irq, |
289 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
290 | NJATA32_REG_BM)); |
291 | |
292 | /* disable busmaster */ |
293 | njata32_irqack(chp); |
294 | |
295 | /* clear device interrupt */ |
296 | aprint_normal("err %#x, seccnt %#x, cyl %#x, sdh %#x, " , |
297 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
298 | NJATA32_REG_WD_ERROR), |
299 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
300 | NJATA32_REG_WD_SECCNT), |
301 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
302 | NJATA32_REG_WD_CYL_LO) | |
303 | (bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
304 | NJATA32_REG_WD_CYL_HI) << 8), |
305 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
306 | NJATA32_REG_WD_SDH)); |
307 | aprint_normal("status %#x\n" , |
308 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
309 | NJATA32_REG_WD_STATUS)); |
310 | } |
311 | |
312 | static void |
313 | njata32_setup_channel(struct ata_channel *chp) |
314 | { |
315 | struct njata32_softc *sc = (void *)chp->ch_atac; |
316 | struct ata_drive_datas *drvp; |
317 | int drive; |
318 | uint8_t mode; |
319 | |
320 | KASSERT(chp->ch_ndrives != 0); |
321 | |
322 | sc->sc_timing_pio = 0; |
323 | #if 0 /* ATA DMA is currently unused */ |
324 | sc->sc_timing_dma = 0; |
325 | #endif |
326 | |
327 | for (drive = 0; drive < chp->ch_ndrives; drive++) { |
328 | drvp = &chp->ch_drive[drive]; |
329 | if (drvp->drive_type == ATA_DRIVET_NONE) |
330 | continue; /* no drive */ |
331 | |
332 | #if 0 /* ATA DMA is currently unused */ |
333 | if ((drvp->drive_flags & ATA_DRIVE_DMA) != 0) { |
334 | /* |
335 | * Multiword DMA |
336 | */ |
337 | if ((mode = drvp->DMA_mode) > NJATA32_MODE_MAX_DMA) |
338 | mode = NJATA32_MODE_MAX_DMA; |
339 | if (sc->sc_timing_dma < njata32_timing_dma[mode]) |
340 | sc->sc_timing_dma = njata32_timing_dma[mode]; |
341 | } |
342 | #endif |
343 | /* |
344 | * PIO |
345 | */ |
346 | if ((mode = drvp->PIO_mode) > NJATA32_MODE_MAX_PIO) |
347 | mode = NJATA32_MODE_MAX_PIO; |
348 | if (sc->sc_timing_pio < njata32_timing_pio[mode]) |
349 | sc->sc_timing_pio = njata32_timing_pio[mode]; |
350 | } |
351 | |
352 | sc->sc_timing_pio += sc->sc_atawait; |
353 | |
354 | /* set timing for PIO */ |
355 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
356 | NJATA32_REG_TIMING, sc->sc_timing_pio); |
357 | } |
358 | |
359 | /* |
360 | * map DMA buffer |
361 | */ |
362 | int |
363 | njata32_dma_init(void *v, int channel, int drive, void *databuf, |
364 | size_t datalen, int flags) |
365 | { |
366 | struct njata32_softc *sc = v; |
367 | int error; |
368 | struct njata32_device *dev = &sc->sc_dev[drive]; |
369 | |
370 | KASSERT(channel == 0); |
371 | KASSERT((dev->d_flags & NJATA32_DEV_DMA_MAPPED) == 0); |
372 | KASSERT((dev->d_flags & NJATA32_DEV_DMA_STARTED) == 0); |
373 | |
374 | KASSERT(flags & (WDC_DMA_PIOBM_ATA | WDC_DMA_PIOBM_ATAPI)); |
375 | |
376 | /* use PIO for short transfer */ |
377 | if (datalen < 64 /* needs tune */) { |
378 | DPRINTF(("%s: njata32_dma_init: short transfer (%u)\n" , |
379 | NJATA32NAME(sc), (unsigned)datalen)); |
380 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
381 | NJATA32_REG_TIMING, sc->sc_timing_pio); |
382 | return EINVAL; |
383 | } |
384 | |
385 | /* use PIO for unaligned transfer (word alignment seems OK) */ |
386 | if (((uintptr_t)databuf & 1) || (datalen & 1)) { |
387 | DPRINTF(("%s: njata32_dma_init: unaligned: buf %p, len %u\n" , |
388 | NJATA32NAME(sc), databuf, (unsigned)datalen)); |
389 | return EINVAL; |
390 | } |
391 | |
392 | DPRINTF(("%s: njata32_dma_init: %s: databuf %p, datalen %u\n" , |
393 | NJATA32NAME(sc), (flags & WDC_DMA_READ) ? "read" : "write" , |
394 | databuf, (unsigned)datalen)); |
395 | |
396 | error = bus_dmamap_load(sc->sc_dmat, dev->d_dmamap_xfer, |
397 | databuf, datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING | |
398 | ((flags & WDC_DMA_READ) ? BUS_DMA_READ : BUS_DMA_WRITE)); |
399 | if (error) { |
400 | printf("%s: load xfer failed, error %d\n" , |
401 | NJATA32NAME(sc), error); |
402 | return error; |
403 | } |
404 | |
405 | bus_dmamap_sync(sc->sc_dmat, dev->d_dmamap_xfer, 0, |
406 | dev->d_dmamap_xfer->dm_mapsize, |
407 | (flags & WDC_DMA_READ) ? |
408 | BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); |
409 | |
410 | dev->d_flags = |
411 | ((flags & WDC_DMA_READ) ? NJATA32_DEV_DMA_READ : 0) | |
412 | ((flags & WDC_DMA_PIOBM_ATAPI) ? NJATA32_DEV_DMA_ATAPI : 0) | |
413 | NJATA32_DEV_DMA_MAPPED; |
414 | |
415 | return 0; |
416 | } |
417 | |
418 | /* |
419 | * start DMA |
420 | * |
421 | * top: databuf + skip |
422 | * size: xferlen |
423 | */ |
424 | void |
425 | njata32_piobm_start(void *v, int channel, int drive, |
426 | int skip, int xferlen, int flags) |
427 | { |
428 | struct njata32_softc *sc = v; |
429 | struct njata32_device *dev = &sc->sc_dev[drive]; |
430 | int i, nsegs, seglen; |
431 | uint8_t bmreg; |
432 | |
433 | DPRINTF(("%s: njata32_piobm_start: ch%d, dv%d, skip %d, xferlen %d\n" , |
434 | NJATA32NAME(sc), channel, drive, skip, xferlen)); |
435 | |
436 | KASSERT(channel == 0); |
437 | KASSERT(dev->d_flags & NJATA32_DEV_DMA_MAPPED); |
438 | KASSERT((dev->d_flags & NJATA32_DEV_DMA_STARTED) == 0); |
439 | |
440 | /* |
441 | * create scatter/gather table |
442 | * XXX this code may be slow |
443 | */ |
444 | for (i = nsegs = 0; |
445 | i < dev->d_dmamap_xfer->dm_nsegs && xferlen > 0; i++) { |
446 | if (dev->d_dmamap_xfer->dm_segs[i].ds_len <= skip) { |
447 | skip -= dev->d_dmamap_xfer->dm_segs[i].ds_len; |
448 | continue; |
449 | } |
450 | |
451 | seglen = dev->d_dmamap_xfer->dm_segs[i].ds_len - skip; |
452 | if (seglen > xferlen) |
453 | seglen = xferlen; |
454 | |
455 | dev->d_sgt[nsegs].sg_addr = |
456 | htole32(dev->d_dmamap_xfer->dm_segs[i].ds_addr + skip); |
457 | dev->d_sgt[nsegs].sg_len = htole32(seglen); |
458 | |
459 | xferlen -= seglen; |
460 | nsegs++; |
461 | skip = 0; |
462 | } |
463 | sc->sc_piobm_nsegs = nsegs; |
464 | /* end mark */ |
465 | dev->d_sgt[nsegs - 1].sg_len |= htole32(NJATA32_SGT_ENDMARK); |
466 | |
467 | #ifdef DIAGNOSTIC |
468 | if (xferlen) |
469 | panic("%s: njata32_piobm_start: xferlen residue %d\n" , |
470 | NJATA32NAME(sc), xferlen); |
471 | #endif |
472 | |
473 | bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_sgt, |
474 | (char *)dev->d_sgt - (char *)sc->sc_sgtpg, |
475 | sizeof(struct njata32_sgtable) * nsegs, |
476 | BUS_DMASYNC_PREWRITE); |
477 | |
478 | /* set timing for PIO */ |
479 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
480 | NJATA32_REG_TIMING, sc->sc_timing_pio); |
481 | |
482 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), NJATA32_REG_IOBM, |
483 | NJATA32_IOBM_DEFAULT); |
484 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), NJATA32_REG_AS, |
485 | NJATA32_AS_WAIT0); |
486 | |
487 | /* |
488 | * interrupt configuration |
489 | */ |
490 | if ((dev->d_flags & (NJATA32_DEV_DMA_READ | NJATA32_DEV_DMA_ATAPI)) == |
491 | NJATA32_DEV_DMA_READ) { |
492 | /* |
493 | * ATA piobm read is executed while device interrupt is active, |
494 | * so disable device interrupt here |
495 | */ |
496 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
497 | NJATA32_REG_IRQ_SELECT, NJATA32_IRQ_XFER); |
498 | } |
499 | |
500 | /* enable scatter/gather busmaster transfer */ |
501 | bmreg = NJATA32_BM_EN | NJATA32_BM_SG | NJATA32_BM_WAIT0 | |
502 | ((dev->d_flags & NJATA32_DEV_DMA_READ) ? NJATA32_BM_RD : 0); |
503 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), NJATA32_REG_BM, |
504 | bmreg); |
505 | |
506 | /* load scatter/gather table */ |
507 | bus_space_write_4(NJATA32_REGT(sc), NJATA32_REGH(sc), |
508 | NJATA32_REG_DMAADDR, dev->d_sgt_dma); |
509 | bus_space_write_4(NJATA32_REGT(sc), NJATA32_REGH(sc), |
510 | NJATA32_REG_DMALENGTH, sizeof(struct njata32_sgtable) * nsegs); |
511 | |
512 | /* start transfer */ |
513 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), NJATA32_REG_BM, |
514 | (bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
515 | NJATA32_REG_BM) |
516 | & ~(NJATA32_BM_RD|NJATA32_BM_SG|NJATA32_BM_WAIT_MASK)) | |
517 | bmreg | NJATA32_BM_GO); |
518 | |
519 | sc->sc_devflags = dev->d_flags; |
520 | if (flags & WDC_PIOBM_XFER_IRQ) |
521 | sc->sc_devflags |= NJATA32_DEV_XFER_INTR; |
522 | #ifdef DIAGNOSTIC |
523 | dev->d_flags |= NJATA32_DEV_DMA_STARTED; |
524 | #endif |
525 | } |
526 | |
527 | /* |
528 | * end of DMA |
529 | */ |
530 | int |
531 | njata32_dma_finish(void *v, int channel, int drive, |
532 | int force) |
533 | { |
534 | struct njata32_softc *sc = v; |
535 | struct njata32_device *dev = &sc->sc_dev[drive]; |
536 | int bm; |
537 | int error = 0; |
538 | |
539 | DPRINTF(("%s: njata32_dma_finish: bm = %#x\n" , NJATA32NAME(sc), |
540 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
541 | NJATA32_REG_BM))); |
542 | |
543 | KASSERT(channel == 0); |
544 | KASSERT(dev->d_flags & NJATA32_DEV_DMA_MAPPED); |
545 | KASSERT(dev->d_flags & NJATA32_DEV_DMA_STARTED); |
546 | |
547 | bm = bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
548 | NJATA32_REG_BM); |
549 | |
550 | #ifdef NJATA32_DEBUG |
551 | printf("%s: irq %#x, bm %#x, 18 %#x, 1c %#x\n" , NJATA32NAME(sc), |
552 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
553 | NJATA32_REG_IRQ_STAT), |
554 | bm, |
555 | bus_space_read_4(NJATA32_REGT(sc), NJATA32_REGH(sc), 0x18), |
556 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), 0x1c)); |
557 | #endif |
558 | |
559 | bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_sgt, |
560 | (char *)dev->d_sgt - (char *)sc->sc_sgtpg, |
561 | sizeof(struct njata32_sgtable) * sc->sc_piobm_nsegs, |
562 | BUS_DMASYNC_POSTWRITE); |
563 | |
564 | /* check if DMA is active */ |
565 | if (bm & NJATA32_BM_GO) { |
566 | error = WDC_DMAST_NOIRQ; |
567 | |
568 | switch (force) { |
569 | case WDC_DMAEND_END: |
570 | return error; |
571 | |
572 | case WDC_DMAEND_ABRT: |
573 | printf("%s: aborting DMA\n" , NJATA32NAME(sc)); |
574 | break; |
575 | } |
576 | } |
577 | |
578 | /* |
579 | * ??? |
580 | * For unknown reason, PIOBM transfer sometimes fails in the middle, |
581 | * in which case the bit #7 of BM register becomes 0. |
582 | * Increasing the wait value seems to improve the situation. |
583 | * |
584 | * XXX |
585 | * PIO transfer may also fail, but it seems it can't be detected. |
586 | */ |
587 | if ((bm & NJATA32_BM_DONE) == 0) { |
588 | error |= WDC_DMAST_ERR; |
589 | printf("%s: busmaster error" , NJATA32NAME(sc)); |
590 | if (sc->sc_atawait < 0x11) { |
591 | if ((sc->sc_atawait & 0xf) == 0) |
592 | sc->sc_atawait++; |
593 | else |
594 | sc->sc_atawait += 0x10; |
595 | printf(", new ATA wait = %#x" , sc->sc_atawait); |
596 | njata32_setup_channel(&sc->sc_ch[0].ch_ata_channel); |
597 | } |
598 | printf("\n" ); |
599 | } |
600 | |
601 | /* stop command */ |
602 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), NJATA32_REG_AS, |
603 | NJATA32_AS_WAIT0); |
604 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), NJATA32_REG_BM, |
605 | NJATA32_BM_WAIT0); |
606 | |
607 | /* set timing for PIO */ |
608 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
609 | NJATA32_REG_TIMING, sc->sc_timing_pio); |
610 | |
611 | /* |
612 | * reenable device interrupt in case it was disabled for |
613 | * this transfer |
614 | */ |
615 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
616 | NJATA32_REG_IRQ_SELECT, NJATA32_IRQ_XFER | NJATA32_IRQ_DEV); |
617 | |
618 | #if 1 /* should be? */ |
619 | if ((sc->sc_devflags & NJATA32_DEV_GOT_XFER_INTR) == 0) |
620 | error |= WDC_DMAST_ERR; |
621 | #endif |
622 | sc->sc_devflags = 0; |
623 | |
624 | #ifdef DIAGNOSTIC |
625 | dev->d_flags &= ~NJATA32_DEV_DMA_STARTED; |
626 | #endif |
627 | |
628 | return error; |
629 | } |
630 | |
631 | /* |
632 | * unmap DMA buffer |
633 | */ |
634 | void |
635 | njata32_piobm_done(void *v, int channel, int drive) |
636 | { |
637 | struct njata32_softc *sc = v; |
638 | struct njata32_device *dev = &sc->sc_dev[drive]; |
639 | |
640 | DPRINTF(("%s: njata32_piobm_done: ch%d dv%d\n" , |
641 | NJATA32NAME(sc), channel, drive)); |
642 | |
643 | KASSERT(channel == 0); |
644 | KASSERT(dev->d_flags & NJATA32_DEV_DMA_MAPPED); |
645 | KASSERT((dev->d_flags & NJATA32_DEV_DMA_STARTED) == 0); |
646 | |
647 | /* unload dma map */ |
648 | bus_dmamap_sync(sc->sc_dmat, dev->d_dmamap_xfer, |
649 | 0, dev->d_dmamap_xfer->dm_mapsize, |
650 | (dev->d_flags & NJATA32_DEV_DMA_READ) ? |
651 | BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); |
652 | |
653 | bus_dmamap_unload(sc->sc_dmat, dev->d_dmamap_xfer); |
654 | dev->d_flags &= ~NJATA32_DEV_DMA_MAPPED; |
655 | } |
656 | |
657 | int |
658 | njata32_intr(void *arg) |
659 | { |
660 | struct njata32_softc *sc = arg; |
661 | struct ata_channel *chp; |
662 | int irq; |
663 | |
664 | irq = bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
665 | NJATA32_REG_IRQ_STAT); |
666 | if ((irq & (NJATA32_IRQ_XFER | NJATA32_IRQ_DEV)) == 0) |
667 | return 0; /* not mine */ |
668 | |
669 | DPRINTF(("%s: njata32_intr: irq = %#x, altstatus = %#x\n" , |
670 | NJATA32NAME(sc), irq, |
671 | bus_space_read_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
672 | NJATA32_REG_WD_ALTSTATUS))); |
673 | |
674 | chp = &sc->sc_ch[0].ch_ata_channel; |
675 | |
676 | if (irq & NJATA32_IRQ_XFER) |
677 | sc->sc_devflags |= NJATA32_DEV_GOT_XFER_INTR; |
678 | |
679 | if ((irq & (NJATA32_IRQ_XFER | NJATA32_IRQ_DEV)) == NJATA32_IRQ_XFER && |
680 | (sc->sc_devflags & NJATA32_DEV_XFER_INTR) == 0) { |
681 | /* |
682 | * transfer done, wait for device interrupt |
683 | */ |
684 | bus_space_write_1(NJATA32_REGT(sc), NJATA32_REGH(sc), |
685 | NJATA32_REG_BM, NJATA32_BM_WAIT0); |
686 | return 1; |
687 | } |
688 | |
689 | /* |
690 | * If both transfer done interrupt and device interrupt are |
691 | * active for ATAPI transfer, call wdcintr() twice. |
692 | */ |
693 | if ((sc->sc_devflags & NJATA32_DEV_DMA_ATAPI) && |
694 | (irq & (NJATA32_IRQ_XFER | NJATA32_IRQ_DEV)) == |
695 | (NJATA32_IRQ_XFER | NJATA32_IRQ_DEV) && |
696 | (sc->sc_devflags & NJATA32_DEV_XFER_INTR)) { |
697 | if (wdcintr(chp) == 0) { |
698 | njata32_clearirq(&sc->sc_ch[0].ch_ata_channel, irq); |
699 | } |
700 | } |
701 | |
702 | if (wdcintr(chp) == 0) { |
703 | njata32_clearirq(&sc->sc_ch[0].ch_ata_channel, irq); |
704 | } |
705 | |
706 | return 1; |
707 | } |
708 | |