| 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 | |