1 /* $NetBSD: pcscp.c,v 1.46 2012/01/30 19:41:22 drochner Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center; Izumi Tsutsui. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * pcscp.c: device dependent code for AMD Am53c974 (PCscsi-PCI) 35 * written by Izumi Tsutsui <tsutsui@NetBSD.org> 36 * 37 * Technical manual available at 38 * http://www.amd.com/files/connectivitysolutions/networking/archivednetworking/19113.pdf 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: pcscp.c,v 1.46 2012/01/30 19:41:22 drochner Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/device.h> 47 #include <sys/buf.h> 48 49 #include <sys/bus.h> 50 #include <sys/intr.h> 51 52 #include <dev/scsipi/scsipi_all.h> 53 #include <dev/scsipi/scsi_all.h> 54 #include <dev/scsipi/scsiconf.h> 55 56 #include <dev/pci/pcireg.h> 57 #include <dev/pci/pcivar.h> 58 #include <dev/pci/pcidevs.h> 59 60 #include <dev/ic/ncr53c9xreg.h> 61 #include <dev/ic/ncr53c9xvar.h> 62 63 #include <dev/pci/pcscpreg.h> 64 65 #define IO_MAP_REG 0x10 66 67 struct pcscp_softc { 68 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ 69 70 bus_space_tag_t sc_st; /* bus space tag */ 71 bus_space_handle_t sc_sh; /* bus space handle */ 72 void *sc_ih; /* interrupt cookie */ 73 74 bus_dma_tag_t sc_dmat; /* DMA tag */ 75 76 bus_dmamap_t sc_xfermap; /* DMA map for transfers */ 77 78 uint32_t *sc_mdladdr; /* MDL array */ 79 bus_dmamap_t sc_mdldmap; /* MDL DMA map */ 80 81 int sc_active; /* DMA state */ 82 int sc_datain; /* DMA Data Direction */ 83 size_t sc_dmasize; /* DMA size */ 84 uint8_t **sc_dmaaddr; /* DMA address */ 85 size_t *sc_dmalen; /* DMA length */ 86 }; 87 88 #define READ_DMAREG(sc, reg) \ 89 bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg)) 90 #define WRITE_DMAREG(sc, reg, var) \ 91 bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (var)) 92 93 #define PCSCP_READ_REG(sc, reg) \ 94 bus_space_read_1((sc)->sc_st, (sc)->sc_sh, (reg) << 2) 95 #define PCSCP_WRITE_REG(sc, reg, val) \ 96 bus_space_write_1((sc)->sc_st, (sc)->sc_sh, (reg) << 2, (val)) 97 98 99 static int pcscp_match(device_t, cfdata_t, void *); 100 static void pcscp_attach(device_t, device_t, void *); 101 102 CFATTACH_DECL_NEW(pcscp, sizeof(struct pcscp_softc), 103 pcscp_match, pcscp_attach, NULL, NULL); 104 105 /* 106 * Functions and the switch for the MI code. 107 */ 108 109 static uint8_t pcscp_read_reg(struct ncr53c9x_softc *, int); 110 static void pcscp_write_reg(struct ncr53c9x_softc *, int, uint8_t); 111 static int pcscp_dma_isintr(struct ncr53c9x_softc *); 112 static void pcscp_dma_reset(struct ncr53c9x_softc *); 113 static int pcscp_dma_intr(struct ncr53c9x_softc *); 114 static int pcscp_dma_setup(struct ncr53c9x_softc *, uint8_t **, size_t *, 115 int, size_t *); 116 static void pcscp_dma_go(struct ncr53c9x_softc *); 117 static void pcscp_dma_stop(struct ncr53c9x_softc *); 118 static int pcscp_dma_isactive(struct ncr53c9x_softc *); 119 120 static struct ncr53c9x_glue pcscp_glue = { 121 pcscp_read_reg, 122 pcscp_write_reg, 123 pcscp_dma_isintr, 124 pcscp_dma_reset, 125 pcscp_dma_intr, 126 pcscp_dma_setup, 127 pcscp_dma_go, 128 pcscp_dma_stop, 129 pcscp_dma_isactive, 130 NULL, /* gl_clear_latched_intr */ 131 }; 132 133 static int 134 pcscp_match(device_t parent, cfdata_t cf, void *aux) 135 { 136 struct pci_attach_args *pa = aux; 137 138 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD) 139 return 0; 140 141 switch (PCI_PRODUCT(pa->pa_id)) { 142 case PCI_PRODUCT_AMD_PCSCSI_PCI: 143 return 1; 144 } 145 return 0; 146 } 147 148 /* 149 * Attach this instance, and then all the sub-devices 150 */ 151 static void 152 pcscp_attach(device_t parent, device_t self, void *aux) 153 { 154 struct pcscp_softc *esc = device_private(self); 155 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 156 struct pci_attach_args *pa = aux; 157 bus_space_tag_t iot; 158 bus_space_handle_t ioh; 159 pci_intr_handle_t ih; 160 const char *intrstr; 161 pcireg_t csr; 162 bus_dma_segment_t seg; 163 int error, rseg; 164 165 sc->sc_dev = self; 166 pci_aprint_devinfo(pa, NULL); 167 aprint_normal("%s", device_xname(sc->sc_dev)); 168 169 if (pci_mapreg_map(pa, IO_MAP_REG, PCI_MAPREG_TYPE_IO, 0, 170 &iot, &ioh, NULL, NULL)) { 171 aprint_error(": unable to map registers\n"); 172 return; 173 } 174 175 sc->sc_glue = &pcscp_glue; 176 177 esc->sc_st = iot; 178 esc->sc_sh = ioh; 179 esc->sc_dmat = pa->pa_dmat; 180 181 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 182 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 183 csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE); 184 185 /* 186 * XXX More of this should be in ncr53c9x_attach(), but 187 * XXX should we really poke around the chip that much in 188 * XXX the MI code? Think about this more... 189 */ 190 191 /* 192 * Set up static configuration info. 193 */ 194 195 /* 196 * XXX should read configuration from EEPROM? 197 * 198 * MI ncr53c9x driver does not support configuration 199 * per each target device, though... 200 */ 201 sc->sc_id = 7; 202 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 203 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE; 204 sc->sc_cfg3 = NCRAMDCFG3_IDM | NCRAMDCFG3_FCLK; 205 sc->sc_cfg4 = NCRAMDCFG4_GE12NS | NCRAMDCFG4_RADE; 206 sc->sc_rev = NCR_VARIANT_AM53C974; 207 sc->sc_features = NCR_F_FASTSCSI; 208 sc->sc_cfg3_fscsi = NCRAMDCFG3_FSCSI; 209 sc->sc_freq = 40; /* MHz */ 210 211 /* 212 * XXX minsync and maxxfer _should_ be set up in MI code, 213 * XXX but it appears to have some dependency on what sort 214 * XXX of DMA we're hooked up to, etc. 215 */ 216 217 /* 218 * This is the value used to start sync negotiations 219 * Note that the NCR register "SYNCTP" is programmed 220 * in "clocks per byte", and has a minimum value of 4. 221 * The SCSI period used in negotiation is one-fourth 222 * of the time (in nanoseconds) needed to transfer one byte. 223 * Since the chip's clock is given in MHz, we have the following 224 * formula: 4 * period = (1000 / freq) * 4 225 */ 226 227 sc->sc_minsync = 1000 / sc->sc_freq; 228 229 /* Really no limit, but since we want to fit into the TCR... */ 230 sc->sc_maxxfer = 16 * 1024 * 1024; 231 232 /* 233 * Create the DMA maps for the data transfers. 234 */ 235 236 #define MDL_SEG_SIZE 0x1000 /* 4kbyte per segment */ 237 #define MDL_SEG_OFFSET 0x0FFF 238 #define MDL_SIZE (MAXPHYS / MDL_SEG_SIZE + 1) /* no hardware limit? */ 239 240 if (bus_dmamap_create(esc->sc_dmat, MAXPHYS, MDL_SIZE, MDL_SEG_SIZE, 241 MDL_SEG_SIZE, BUS_DMA_NOWAIT, &esc->sc_xfermap)) { 242 aprint_error(": can't create DMA maps\n"); 243 return; 244 } 245 246 /* 247 * Allocate and map memory for the MDL. 248 */ 249 250 if ((error = bus_dmamem_alloc(esc->sc_dmat, 251 sizeof(uint32_t) * MDL_SIZE, PAGE_SIZE, 0, &seg, 1, &rseg, 252 BUS_DMA_NOWAIT)) != 0) { 253 aprint_error(": unable to allocate memory for the MDL," 254 " error = %d\n", error); 255 goto fail_0; 256 } 257 if ((error = bus_dmamem_map(esc->sc_dmat, &seg, rseg, 258 sizeof(uint32_t) * MDL_SIZE , (void **)&esc->sc_mdladdr, 259 BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { 260 aprint_error(": unable to map the MDL memory, error = %d\n", 261 error); 262 goto fail_1; 263 } 264 if ((error = bus_dmamap_create(esc->sc_dmat, 265 sizeof(uint32_t) * MDL_SIZE, 1, sizeof(uint32_t) * MDL_SIZE, 266 0, BUS_DMA_NOWAIT, &esc->sc_mdldmap)) != 0) { 267 aprint_error(": unable to map_create for the MDL, error = %d\n", 268 error); 269 goto fail_2; 270 } 271 if ((error = bus_dmamap_load(esc->sc_dmat, esc->sc_mdldmap, 272 esc->sc_mdladdr, sizeof(uint32_t) * MDL_SIZE, 273 NULL, BUS_DMA_NOWAIT)) != 0) { 274 aprint_error(": unable to load for the MDL, error = %d\n", 275 error); 276 goto fail_3; 277 } 278 279 /* map and establish interrupt */ 280 if (pci_intr_map(pa, &ih)) { 281 aprint_error(": couldn't map interrupt\n"); 282 goto fail_4; 283 } 284 285 intrstr = pci_intr_string(pa->pa_pc, ih); 286 esc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, 287 ncr53c9x_intr, esc); 288 if (esc->sc_ih == NULL) { 289 aprint_error(": couldn't establish interrupt"); 290 if (intrstr != NULL) 291 aprint_error(" at %s", intrstr); 292 aprint_error("\n"); 293 goto fail_4; 294 } 295 if (intrstr != NULL) { 296 aprint_normal(": interrupting at %s\n", intrstr); 297 aprint_normal("%s", device_xname(sc->sc_dev)); 298 } 299 300 /* Do the common parts of attachment. */ 301 sc->sc_adapter.adapt_minphys = minphys; 302 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 303 ncr53c9x_attach(sc); 304 305 /* Turn on target selection using the `DMA' method */ 306 sc->sc_features |= NCR_F_DMASELECT; 307 308 return; 309 310 fail_4: 311 bus_dmamap_unload(esc->sc_dmat, esc->sc_mdldmap); 312 fail_3: 313 bus_dmamap_destroy(esc->sc_dmat, esc->sc_mdldmap); 314 fail_2: 315 bus_dmamem_unmap(esc->sc_dmat, (void *)esc->sc_mdldmap, 316 sizeof(uint32_t) * MDL_SIZE); 317 fail_1: 318 bus_dmamem_free(esc->sc_dmat, &seg, rseg); 319 fail_0: 320 bus_dmamap_destroy(esc->sc_dmat, esc->sc_xfermap); 321 } 322 323 /* 324 * Glue functions. 325 */ 326 327 static uint8_t 328 pcscp_read_reg(struct ncr53c9x_softc *sc, int reg) 329 { 330 struct pcscp_softc *esc = (struct pcscp_softc *)sc; 331 332 return PCSCP_READ_REG(esc, reg); 333 } 334 335 static void 336 pcscp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v) 337 { 338 struct pcscp_softc *esc = (struct pcscp_softc *)sc; 339 340 PCSCP_WRITE_REG(esc, reg, v); 341 } 342 343 static int 344 pcscp_dma_isintr(struct ncr53c9x_softc *sc) 345 { 346 struct pcscp_softc *esc = (struct pcscp_softc *)sc; 347 348 return (PCSCP_READ_REG(esc, NCR_STAT) & NCRSTAT_INT) != 0; 349 } 350 351 static void 352 pcscp_dma_reset(struct ncr53c9x_softc *sc) 353 { 354 struct pcscp_softc *esc = (struct pcscp_softc *)sc; 355 356 WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE); 357 358 esc->sc_active = 0; 359 } 360 361 static int 362 pcscp_dma_intr(struct ncr53c9x_softc *sc) 363 { 364 struct pcscp_softc *esc = (struct pcscp_softc *)sc; 365 int trans, resid, i; 366 bus_dmamap_t dmap = esc->sc_xfermap; 367 int datain = esc->sc_datain; 368 uint32_t dmastat; 369 uint8_t *p = NULL; 370 371 dmastat = READ_DMAREG(esc, DMA_STAT); 372 373 if (dmastat & DMASTAT_ERR) { 374 /* XXX not tested... */ 375 WRITE_DMAREG(esc, DMA_CMD, 376 DMACMD_ABORT | (datain ? DMACMD_DIR : 0)); 377 378 printf("%s: error: DMA error detected; Aborting.\n", 379 device_xname(sc->sc_dev)); 380 bus_dmamap_unload(esc->sc_dmat, dmap); 381 return -1; 382 } 383 384 if (dmastat & DMASTAT_ABT) { 385 /* XXX What should be done? */ 386 printf("%s: %s: DMA aborted.\n", 387 device_xname(sc->sc_dev), __func__); 388 WRITE_DMAREG(esc, DMA_CMD, 389 DMACMD_IDLE | (datain ? DMACMD_DIR : 0)); 390 esc->sc_active = 0; 391 return 0; 392 } 393 394 #ifdef DIAGNOSTIC 395 /* This is an "assertion" :) */ 396 if (esc->sc_active == 0) 397 panic("%s: %s: DMA wasn't active", 398 device_xname(sc->sc_dev), __func__); 399 #endif 400 401 /* DMA has stopped */ 402 403 esc->sc_active = 0; 404 405 if (esc->sc_dmasize == 0) { 406 /* A "Transfer Pad" operation completed */ 407 NCR_DMA(("%s: discarded %d bytes (tcl=%d, tcm=%d)\n", 408 __func__, 409 PCSCP_READ_REG(esc, NCR_TCL) | 410 (PCSCP_READ_REG(esc, NCR_TCM) << 8), 411 PCSCP_READ_REG(esc, NCR_TCL), 412 PCSCP_READ_REG(esc, NCR_TCM))); 413 return 0; 414 } 415 416 resid = 0; 417 /* 418 * If a transfer onto the SCSI bus gets interrupted by the device 419 * (e.g. for a SAVEPOINTER message), the data in the FIFO counts 420 * as residual since the ESP counter registers get decremented as 421 * bytes are clocked into the FIFO. 422 */ 423 if (!datain && 424 (resid = (PCSCP_READ_REG(esc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { 425 NCR_DMA(("%s: empty esp FIFO of %d ", __func__, resid)); 426 } 427 428 if ((sc->sc_espstat & NCRSTAT_TC) == 0) { 429 /* 430 * `Terminal count' is off, so read the residue 431 * out of the ESP counter registers. 432 */ 433 if (datain) { 434 resid = PCSCP_READ_REG(esc, NCR_FFLAG) & NCRFIFO_FF; 435 while (resid > 1) 436 resid = 437 PCSCP_READ_REG(esc, NCR_FFLAG) & NCRFIFO_FF; 438 WRITE_DMAREG(esc, DMA_CMD, DMACMD_BLAST | DMACMD_MDL | 439 (datain ? DMACMD_DIR : 0)); 440 441 for (i = 0; i < 1000; i++) { /* XXX */ 442 if (READ_DMAREG(esc, DMA_STAT) & DMASTAT_BCMP) 443 break; 444 DELAY(1); 445 } 446 447 /* See the below comments... */ 448 if (resid) 449 p = *esc->sc_dmaaddr; 450 } 451 452 resid += PCSCP_READ_REG(esc, NCR_TCL) | 453 (PCSCP_READ_REG(esc, NCR_TCM) << 8) | 454 (PCSCP_READ_REG(esc, NCR_TCH) << 16); 455 } else { 456 while ((dmastat & DMASTAT_DONE) == 0) 457 dmastat = READ_DMAREG(esc, DMA_STAT); 458 } 459 460 WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | (datain ? DMACMD_DIR : 0)); 461 462 /* sync MDL */ 463 bus_dmamap_sync(esc->sc_dmat, esc->sc_mdldmap, 464 0, sizeof(uint32_t) * dmap->dm_nsegs, BUS_DMASYNC_POSTWRITE); 465 /* sync transfer buffer */ 466 bus_dmamap_sync(esc->sc_dmat, dmap, 0, dmap->dm_mapsize, 467 datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 468 bus_dmamap_unload(esc->sc_dmat, dmap); 469 470 trans = esc->sc_dmasize - resid; 471 472 /* 473 * From the technical manual notes: 474 * 475 * `In some odd byte conditions, one residual byte will be left 476 * in the SCSI FIFO, and the FIFO flags will never count to 0. 477 * When this happens, the residual byte should be retrieved 478 * via PIO following completion of the BLAST operation.' 479 */ 480 481 if (p) { 482 p += trans; 483 *p = PCSCP_READ_REG(esc, NCR_FIFO); 484 trans++; 485 } 486 487 if (trans < 0) { /* transferred < 0 ? */ 488 #if 0 489 /* 490 * This situation can happen in perfectly normal operation 491 * if the ESP is reselected while using DMA to select 492 * another target. As such, don't print the warning. 493 */ 494 printf("%s: xfer (%d) > req (%d)\n", 495 device_xname(sc->sc_dev), trans, esc->sc_dmasize); 496 #endif 497 trans = esc->sc_dmasize; 498 } 499 500 NCR_DMA(("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", 501 __func__, 502 PCSCP_READ_REG(esc, NCR_TCL), 503 PCSCP_READ_REG(esc, NCR_TCM), 504 PCSCP_READ_REG(esc, NCR_TCH), 505 trans, resid)); 506 507 *esc->sc_dmalen -= trans; 508 *esc->sc_dmaaddr += trans; 509 510 return 0; 511 } 512 513 static int 514 pcscp_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len, 515 int datain, size_t *dmasize) 516 { 517 struct pcscp_softc *esc = (struct pcscp_softc *)sc; 518 bus_dmamap_t dmap = esc->sc_xfermap; 519 uint32_t *mdl; 520 int error, nseg, seg; 521 bus_addr_t s_offset, s_addr; 522 523 WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | (datain ? DMACMD_DIR : 0)); 524 525 esc->sc_dmaaddr = addr; 526 esc->sc_dmalen = len; 527 esc->sc_dmasize = *dmasize; 528 esc->sc_datain = datain; 529 530 #ifdef DIAGNOSTIC 531 if ((*dmasize / MDL_SEG_SIZE) > MDL_SIZE) 532 panic("%s: transfer size too large", device_xname(sc->sc_dev)); 533 #endif 534 535 /* 536 * No need to set up DMA in `Transfer Pad' operation. 537 * (case of *dmasize == 0) 538 */ 539 if (*dmasize == 0) 540 return 0; 541 542 error = bus_dmamap_load(esc->sc_dmat, dmap, *esc->sc_dmaaddr, 543 *esc->sc_dmalen, NULL, 544 ((sc->sc_nexus->xs->xs_control & XS_CTL_NOSLEEP) ? 545 BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | BUS_DMA_STREAMING | 546 ((sc->sc_nexus->xs->xs_control & XS_CTL_DATA_IN) ? 547 BUS_DMA_READ : BUS_DMA_WRITE)); 548 if (error) { 549 printf("%s: unable to load dmamap, error = %d\n", 550 device_xname(sc->sc_dev), error); 551 return error; 552 } 553 554 /* set transfer length */ 555 WRITE_DMAREG(esc, DMA_STC, *dmasize); 556 557 /* set up MDL */ 558 mdl = esc->sc_mdladdr; 559 nseg = dmap->dm_nsegs; 560 561 /* the first segment is possibly not aligned with 4k MDL boundary */ 562 s_addr = dmap->dm_segs[0].ds_addr; 563 s_offset = s_addr & MDL_SEG_OFFSET; 564 s_addr -= s_offset; 565 566 /* set the first MDL and offset */ 567 WRITE_DMAREG(esc, DMA_SPA, s_offset); 568 *mdl++ = htole32(s_addr); 569 570 /* the rest dmamap segments are aligned with 4k boundary */ 571 for (seg = 1; seg < nseg; seg++) 572 *mdl++ = htole32(dmap->dm_segs[seg].ds_addr); 573 574 return 0; 575 } 576 577 static void 578 pcscp_dma_go(struct ncr53c9x_softc *sc) 579 { 580 struct pcscp_softc *esc = (struct pcscp_softc *)sc; 581 bus_dmamap_t dmap = esc->sc_xfermap, mdldmap = esc->sc_mdldmap; 582 int datain = esc->sc_datain; 583 584 /* No DMA transfer in Transfer Pad operation */ 585 if (esc->sc_dmasize == 0) 586 return; 587 588 /* sync transfer buffer */ 589 bus_dmamap_sync(esc->sc_dmat, dmap, 0, dmap->dm_mapsize, 590 datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 591 592 /* sync MDL */ 593 bus_dmamap_sync(esc->sc_dmat, mdldmap, 594 0, sizeof(uint32_t) * dmap->dm_nsegs, BUS_DMASYNC_PREWRITE); 595 596 /* set Starting MDL Address */ 597 WRITE_DMAREG(esc, DMA_SMDLA, mdldmap->dm_segs[0].ds_addr); 598 599 /* set DMA command register bits */ 600 /* XXX DMA Transfer Interrupt Enable bit is broken? */ 601 WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | DMACMD_MDL | 602 /* DMACMD_INTE | */ 603 (datain ? DMACMD_DIR : 0)); 604 605 /* issue DMA start command */ 606 WRITE_DMAREG(esc, DMA_CMD, DMACMD_START | DMACMD_MDL | 607 /* DMACMD_INTE | */ 608 (datain ? DMACMD_DIR : 0)); 609 610 esc->sc_active = 1; 611 } 612 613 static void 614 pcscp_dma_stop(struct ncr53c9x_softc *sc) 615 { 616 struct pcscp_softc *esc = (struct pcscp_softc *)sc; 617 618 /* DMA stop */ 619 /* XXX What should we do here ? */ 620 WRITE_DMAREG(esc, DMA_CMD, 621 DMACMD_ABORT | (esc->sc_datain ? DMACMD_DIR : 0)); 622 bus_dmamap_unload(esc->sc_dmat, esc->sc_xfermap); 623 624 esc->sc_active = 0; 625 } 626 627 static int 628 pcscp_dma_isactive(struct ncr53c9x_softc *sc) 629 { 630 struct pcscp_softc *esc = (struct pcscp_softc *)sc; 631 632 /* XXX should check esc->sc_active? */ 633 if ((READ_DMAREG(esc, DMA_CMD) & DMACMD_CMD) != DMACMD_IDLE) 634 return 1; 635 return 0; 636 } 637