1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-2-Clause-NetBSD 3 * 4 * Copyright (c) 2011 Marius Strobl <[email protected]> 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* $NetBSD: pcscp.c,v 1.45 2010/11/13 13:52:08 uebayasi Exp $ */ 30 31 /*- 32 * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. 33 * All rights reserved. 34 * 35 * This code is derived from software contributed to The NetBSD Foundation 36 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 37 * NASA Ames Research Center; Izumi Tsutsui. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 49 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 50 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 51 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 52 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 56 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 58 * POSSIBILITY OF SUCH DAMAGE. 59 */ 60 61 /* 62 * esp_pci.c: device dependent code for AMD Am53c974 (PCscsi-PCI) 63 * written by Izumi Tsutsui <[email protected]> 64 * 65 * Technical manual available at 66 * http://www.amd.com/files/connectivitysolutions/networking/archivednetworking/19113.pdf 67 */ 68 69 #include <sys/cdefs.h> 70 __FBSDID("$FreeBSD$"); 71 72 #include <sys/param.h> 73 #include <sys/systm.h> 74 #include <sys/bus.h> 75 #include <sys/endian.h> 76 #include <sys/kernel.h> 77 #include <sys/lock.h> 78 #include <sys/module.h> 79 #include <sys/mutex.h> 80 #include <sys/resource.h> 81 #include <sys/rman.h> 82 83 #include <machine/bus.h> 84 #include <machine/resource.h> 85 86 #include <cam/cam.h> 87 #include <cam/cam_ccb.h> 88 #include <cam/scsi/scsi_all.h> 89 90 #include <dev/pci/pcireg.h> 91 #include <dev/pci/pcivar.h> 92 93 #include <dev/esp/ncr53c9xreg.h> 94 #include <dev/esp/ncr53c9xvar.h> 95 96 #include <dev/esp/am53c974reg.h> 97 98 #define PCI_DEVICE_ID_AMD53C974 0x20201022 99 100 struct esp_pci_softc { 101 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ 102 device_t sc_dev; 103 104 struct resource *sc_res[2]; 105 #define ESP_PCI_RES_INTR 0 106 #define ESP_PCI_RES_IO 1 107 108 bus_dma_tag_t sc_pdmat; 109 110 bus_dma_tag_t sc_xferdmat; /* DMA tag for transfers */ 111 bus_dmamap_t sc_xferdmam; /* DMA map for transfers */ 112 113 void *sc_ih; /* interrupt handler */ 114 115 size_t sc_dmasize; /* DMA size */ 116 void **sc_dmaaddr; /* DMA address */ 117 size_t *sc_dmalen; /* DMA length */ 118 int sc_active; /* DMA state */ 119 int sc_datain; /* DMA Data Direction */ 120 }; 121 122 static struct resource_spec esp_pci_res_spec[] = { 123 { SYS_RES_IRQ, 0, RF_SHAREABLE | RF_ACTIVE }, /* ESP_PCI_RES_INTR */ 124 { SYS_RES_IOPORT, PCIR_BAR(0), RF_ACTIVE }, /* ESP_PCI_RES_IO */ 125 { -1, 0 } 126 }; 127 128 #define READ_DMAREG(sc, reg) \ 129 bus_read_4((sc)->sc_res[ESP_PCI_RES_IO], (reg)) 130 #define WRITE_DMAREG(sc, reg, var) \ 131 bus_write_4((sc)->sc_res[ESP_PCI_RES_IO], (reg), (var)) 132 133 #define READ_ESPREG(sc, reg) \ 134 bus_read_1((sc)->sc_res[ESP_PCI_RES_IO], (reg) << 2) 135 #define WRITE_ESPREG(sc, reg, val) \ 136 bus_write_1((sc)->sc_res[ESP_PCI_RES_IO], (reg) << 2, (val)) 137 138 static int esp_pci_probe(device_t); 139 static int esp_pci_attach(device_t); 140 static int esp_pci_detach(device_t); 141 static int esp_pci_suspend(device_t); 142 static int esp_pci_resume(device_t); 143 144 static device_method_t esp_pci_methods[] = { 145 DEVMETHOD(device_probe, esp_pci_probe), 146 DEVMETHOD(device_attach, esp_pci_attach), 147 DEVMETHOD(device_detach, esp_pci_detach), 148 DEVMETHOD(device_suspend, esp_pci_suspend), 149 DEVMETHOD(device_resume, esp_pci_resume), 150 151 DEVMETHOD_END 152 }; 153 154 static driver_t esp_pci_driver = { 155 "esp", 156 esp_pci_methods, 157 sizeof(struct esp_pci_softc) 158 }; 159 160 DRIVER_MODULE(esp, pci, esp_pci_driver, esp_devclass, 0, 0); 161 MODULE_DEPEND(esp, pci, 1, 1, 1); 162 163 /* 164 * Functions and the switch for the MI code 165 */ 166 static void esp_pci_dma_go(struct ncr53c9x_softc *); 167 static int esp_pci_dma_intr(struct ncr53c9x_softc *); 168 static int esp_pci_dma_isactive(struct ncr53c9x_softc *); 169 170 static int esp_pci_dma_isintr(struct ncr53c9x_softc *); 171 static void esp_pci_dma_reset(struct ncr53c9x_softc *); 172 static int esp_pci_dma_setup(struct ncr53c9x_softc *, void **, size_t *, 173 int, size_t *); 174 static void esp_pci_dma_stop(struct ncr53c9x_softc *); 175 static void esp_pci_write_reg(struct ncr53c9x_softc *, int, uint8_t); 176 static uint8_t esp_pci_read_reg(struct ncr53c9x_softc *, int); 177 static void esp_pci_xfermap(void *arg, bus_dma_segment_t *segs, int nseg, 178 int error); 179 180 static struct ncr53c9x_glue esp_pci_glue = { 181 esp_pci_read_reg, 182 esp_pci_write_reg, 183 esp_pci_dma_isintr, 184 esp_pci_dma_reset, 185 esp_pci_dma_intr, 186 esp_pci_dma_setup, 187 esp_pci_dma_go, 188 esp_pci_dma_stop, 189 esp_pci_dma_isactive, 190 }; 191 192 static int 193 esp_pci_probe(device_t dev) 194 { 195 196 if (pci_get_devid(dev) == PCI_DEVICE_ID_AMD53C974) { 197 device_set_desc(dev, "AMD Am53C974 Fast-SCSI"); 198 return (BUS_PROBE_DEFAULT); 199 } 200 201 return (ENXIO); 202 } 203 204 /* 205 * Attach this instance, and then all the sub-devices 206 */ 207 static int 208 esp_pci_attach(device_t dev) 209 { 210 struct esp_pci_softc *esc; 211 struct ncr53c9x_softc *sc; 212 int error; 213 214 esc = device_get_softc(dev); 215 sc = &esc->sc_ncr53c9x; 216 217 NCR_LOCK_INIT(sc); 218 219 esc->sc_dev = dev; 220 sc->sc_glue = &esp_pci_glue; 221 222 pci_enable_busmaster(dev); 223 224 error = bus_alloc_resources(dev, esp_pci_res_spec, esc->sc_res); 225 if (error != 0) { 226 device_printf(dev, "failed to allocate resources\n"); 227 bus_release_resources(dev, esp_pci_res_spec, esc->sc_res); 228 return (error); 229 } 230 231 error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, 232 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 233 BUS_SPACE_MAXSIZE_32BIT, BUS_SPACE_UNRESTRICTED, 234 BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, &esc->sc_pdmat); 235 if (error != 0) { 236 device_printf(dev, "cannot create parent DMA tag\n"); 237 goto fail_res; 238 } 239 240 /* 241 * XXX More of this should be in ncr53c9x_attach(), but 242 * XXX should we really poke around the chip that much in 243 * XXX the MI code? Think about this more... 244 */ 245 246 /* 247 * Set up static configuration info. 248 * 249 * XXX we should read the configuration from the EEPROM. 250 */ 251 sc->sc_id = 7; 252 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 253 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE; 254 sc->sc_cfg3 = NCRAMDCFG3_IDM | NCRAMDCFG3_FCLK; 255 sc->sc_cfg4 = NCRAMDCFG4_GE12NS | NCRAMDCFG4_RADE; 256 sc->sc_rev = NCR_VARIANT_AM53C974; 257 sc->sc_features = NCR_F_FASTSCSI | NCR_F_DMASELECT; 258 sc->sc_cfg3_fscsi = NCRAMDCFG3_FSCSI; 259 sc->sc_freq = 40; /* MHz */ 260 261 /* 262 * This is the value used to start sync negotiations 263 * Note that the NCR register "SYNCTP" is programmed 264 * in "clocks per byte", and has a minimum value of 4. 265 * The SCSI period used in negotiation is one-fourth 266 * of the time (in nanoseconds) needed to transfer one byte. 267 * Since the chip's clock is given in MHz, we have the following 268 * formula: 4 * period = (1000 / freq) * 4 269 */ 270 sc->sc_minsync = 1000 / sc->sc_freq; 271 272 sc->sc_maxxfer = DFLTPHYS; /* see below */ 273 sc->sc_maxoffset = 15; 274 sc->sc_extended_geom = 1; 275 276 #define MDL_SEG_SIZE 0x1000 /* 4kbyte per segment */ 277 278 /* 279 * Create the DMA tag and map for the data transfers. 280 * 281 * Note: given that bus_dma(9) only adheres to the requested alignment 282 * for the first segment (and that also only for bus_dmamem_alloc()ed 283 * DMA maps) we can't use the Memory Descriptor List. However, also 284 * when not using the MDL, the maximum transfer size apparently is 285 * limited to 4k so we have to split transfers up, which plain sucks. 286 */ 287 error = bus_dma_tag_create(esc->sc_pdmat, PAGE_SIZE, 0, 288 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 289 MDL_SEG_SIZE, 1, MDL_SEG_SIZE, BUS_DMA_ALLOCNOW, 290 busdma_lock_mutex, &sc->sc_lock, &esc->sc_xferdmat); 291 if (error != 0) { 292 device_printf(dev, "cannot create transfer DMA tag\n"); 293 goto fail_pdmat; 294 } 295 error = bus_dmamap_create(esc->sc_xferdmat, 0, &esc->sc_xferdmam); 296 if (error != 0) { 297 device_printf(dev, "cannot create transfer DMA map\n"); 298 goto fail_xferdmat; 299 } 300 301 error = bus_setup_intr(dev, esc->sc_res[ESP_PCI_RES_INTR], 302 INTR_MPSAFE | INTR_TYPE_CAM, NULL, ncr53c9x_intr, sc, 303 &esc->sc_ih); 304 if (error != 0) { 305 device_printf(dev, "cannot set up interrupt\n"); 306 goto fail_xferdmam; 307 } 308 309 /* Do the common parts of attachment. */ 310 sc->sc_dev = esc->sc_dev; 311 error = ncr53c9x_attach(sc); 312 if (error != 0) { 313 device_printf(esc->sc_dev, "ncr53c9x_attach failed\n"); 314 goto fail_intr; 315 } 316 317 return (0); 318 319 fail_intr: 320 bus_teardown_intr(esc->sc_dev, esc->sc_res[ESP_PCI_RES_INTR], 321 esc->sc_ih); 322 fail_xferdmam: 323 bus_dmamap_destroy(esc->sc_xferdmat, esc->sc_xferdmam); 324 fail_xferdmat: 325 bus_dma_tag_destroy(esc->sc_xferdmat); 326 fail_pdmat: 327 bus_dma_tag_destroy(esc->sc_pdmat); 328 fail_res: 329 bus_release_resources(dev, esp_pci_res_spec, esc->sc_res); 330 NCR_LOCK_DESTROY(sc); 331 332 return (error); 333 } 334 335 static int 336 esp_pci_detach(device_t dev) 337 { 338 struct ncr53c9x_softc *sc; 339 struct esp_pci_softc *esc; 340 int error; 341 342 esc = device_get_softc(dev); 343 sc = &esc->sc_ncr53c9x; 344 345 bus_teardown_intr(esc->sc_dev, esc->sc_res[ESP_PCI_RES_INTR], 346 esc->sc_ih); 347 error = ncr53c9x_detach(sc); 348 if (error != 0) 349 return (error); 350 bus_dmamap_destroy(esc->sc_xferdmat, esc->sc_xferdmam); 351 bus_dma_tag_destroy(esc->sc_xferdmat); 352 bus_dma_tag_destroy(esc->sc_pdmat); 353 bus_release_resources(dev, esp_pci_res_spec, esc->sc_res); 354 NCR_LOCK_DESTROY(sc); 355 356 return (0); 357 } 358 359 static int 360 esp_pci_suspend(device_t dev) 361 { 362 363 return (ENXIO); 364 } 365 366 static int 367 esp_pci_resume(device_t dev) 368 { 369 370 return (ENXIO); 371 } 372 373 static void 374 esp_pci_xfermap(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 375 { 376 struct esp_pci_softc *esc = (struct esp_pci_softc *)arg; 377 378 if (error != 0) 379 return; 380 381 KASSERT(nsegs == 1, ("%s: bad transfer segment count %d", __func__, 382 nsegs)); 383 KASSERT(segs[0].ds_len <= MDL_SEG_SIZE, 384 ("%s: bad transfer segment length %ld", __func__, 385 (long)segs[0].ds_len)); 386 387 /* Program the DMA Starting Physical Address. */ 388 WRITE_DMAREG(esc, DMA_SPA, segs[0].ds_addr); 389 } 390 391 /* 392 * Glue functions 393 */ 394 395 static uint8_t 396 esp_pci_read_reg(struct ncr53c9x_softc *sc, int reg) 397 { 398 struct esp_pci_softc *esc = (struct esp_pci_softc *)sc; 399 400 return (READ_ESPREG(esc, reg)); 401 } 402 403 static void 404 esp_pci_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v) 405 { 406 struct esp_pci_softc *esc = (struct esp_pci_softc *)sc; 407 408 WRITE_ESPREG(esc, reg, v); 409 } 410 411 static int 412 esp_pci_dma_isintr(struct ncr53c9x_softc *sc) 413 { 414 struct esp_pci_softc *esc = (struct esp_pci_softc *)sc; 415 416 return (READ_ESPREG(esc, NCR_STAT) & NCRSTAT_INT) != 0; 417 } 418 419 static void 420 esp_pci_dma_reset(struct ncr53c9x_softc *sc) 421 { 422 struct esp_pci_softc *esc = (struct esp_pci_softc *)sc; 423 424 WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE); 425 426 esc->sc_active = 0; 427 } 428 429 static int 430 esp_pci_dma_intr(struct ncr53c9x_softc *sc) 431 { 432 struct esp_pci_softc *esc = (struct esp_pci_softc *)sc; 433 bus_dma_tag_t xferdmat; 434 bus_dmamap_t xferdmam; 435 size_t dmasize; 436 int datain, i, resid, trans; 437 uint32_t dmastat; 438 char *p = NULL; 439 440 xferdmat = esc->sc_xferdmat; 441 xferdmam = esc->sc_xferdmam; 442 datain = esc->sc_datain; 443 444 dmastat = READ_DMAREG(esc, DMA_STAT); 445 446 if ((dmastat & DMASTAT_ERR) != 0) { 447 /* XXX not tested... */ 448 WRITE_DMAREG(esc, DMA_CMD, DMACMD_ABORT | (datain != 0 ? 449 DMACMD_DIR : 0)); 450 451 device_printf(esc->sc_dev, "DMA error detected; Aborting.\n"); 452 bus_dmamap_sync(xferdmat, xferdmam, datain != 0 ? 453 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 454 bus_dmamap_unload(xferdmat, xferdmam); 455 return (-1); 456 } 457 458 if ((dmastat & DMASTAT_ABT) != 0) { 459 /* XXX what should be done? */ 460 device_printf(esc->sc_dev, "DMA aborted.\n"); 461 WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | (datain != 0 ? 462 DMACMD_DIR : 0)); 463 esc->sc_active = 0; 464 return (0); 465 } 466 467 KASSERT(esc->sc_active != 0, ("%s: DMA wasn't active", __func__)); 468 469 /* DMA has stopped. */ 470 471 esc->sc_active = 0; 472 473 dmasize = esc->sc_dmasize; 474 if (dmasize == 0) { 475 /* A "Transfer Pad" operation completed. */ 476 NCR_DMA(("%s: discarded %d bytes (tcl=%d, tcm=%d)\n", 477 __func__, READ_ESPREG(esc, NCR_TCL) | 478 (READ_ESPREG(esc, NCR_TCM) << 8), 479 READ_ESPREG(esc, NCR_TCL), READ_ESPREG(esc, NCR_TCM))); 480 return (0); 481 } 482 483 resid = 0; 484 /* 485 * If a transfer onto the SCSI bus gets interrupted by the device 486 * (e.g. for a SAVEPOINTER message), the data in the FIFO counts 487 * as residual since the ESP counter registers get decremented as 488 * bytes are clocked into the FIFO. 489 */ 490 if (datain == 0 && 491 (resid = (READ_ESPREG(esc, NCR_FFLAG) & NCRFIFO_FF)) != 0) 492 NCR_DMA(("%s: empty esp FIFO of %d ", __func__, resid)); 493 494 if ((sc->sc_espstat & NCRSTAT_TC) == 0) { 495 /* 496 * "Terminal count" is off, so read the residue 497 * out of the ESP counter registers. 498 */ 499 if (datain != 0) { 500 resid = READ_ESPREG(esc, NCR_FFLAG) & NCRFIFO_FF; 501 while (resid > 1) 502 resid = 503 READ_ESPREG(esc, NCR_FFLAG) & NCRFIFO_FF; 504 WRITE_DMAREG(esc, DMA_CMD, DMACMD_BLAST | DMACMD_DIR); 505 506 for (i = 0; i < 0x8000; i++) /* XXX 0x8000 ? */ 507 if ((READ_DMAREG(esc, DMA_STAT) & 508 DMASTAT_BCMP) != 0) 509 break; 510 511 /* See the below comments... */ 512 if (resid != 0) 513 p = *esc->sc_dmaaddr; 514 } 515 516 resid += READ_ESPREG(esc, NCR_TCL) | 517 (READ_ESPREG(esc, NCR_TCM) << 8) | 518 (READ_ESPREG(esc, NCR_TCH) << 16); 519 } else 520 while ((dmastat & DMASTAT_DONE) == 0) 521 dmastat = READ_DMAREG(esc, DMA_STAT); 522 523 WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | (datain != 0 ? 524 DMACMD_DIR : 0)); 525 526 /* Sync the transfer buffer. */ 527 bus_dmamap_sync(xferdmat, xferdmam, datain != 0 ? 528 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 529 bus_dmamap_unload(xferdmat, xferdmam); 530 531 trans = dmasize - resid; 532 533 /* 534 * From the technical manual notes: 535 * 536 * "In some odd byte conditions, one residual byte will be left 537 * in the SCSI FIFO, and the FIFO flags will never count to 0. 538 * When this happens, the residual byte should be retrieved 539 * via PIO following completion of the BLAST operation." 540 */ 541 if (p != NULL) { 542 p += trans; 543 *p = READ_ESPREG(esc, NCR_FIFO); 544 trans++; 545 } 546 547 if (trans < 0) { /* transferred < 0 ? */ 548 #if 0 549 /* 550 * This situation can happen in perfectly normal operation 551 * if the ESP is reselected while using DMA to select 552 * another target. As such, don't print the warning. 553 */ 554 device_printf(dev, "xfer (%d) > req (%d)\n", trans, dmasize); 555 #endif 556 trans = dmasize; 557 } 558 559 NCR_DMA(("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", __func__, 560 READ_ESPREG(esc, NCR_TCL), READ_ESPREG(esc, NCR_TCM), 561 READ_ESPREG(esc, NCR_TCH), trans, resid)); 562 563 *esc->sc_dmalen -= trans; 564 *esc->sc_dmaaddr = (char *)*esc->sc_dmaaddr + trans; 565 566 return (0); 567 } 568 569 static int 570 esp_pci_dma_setup(struct ncr53c9x_softc *sc, void **addr, size_t *len, 571 int datain, size_t *dmasize) 572 { 573 struct esp_pci_softc *esc = (struct esp_pci_softc *)sc; 574 int error; 575 576 WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | (datain != 0 ? DMACMD_DIR : 577 0)); 578 579 *dmasize = esc->sc_dmasize = ulmin(*dmasize, MDL_SEG_SIZE); 580 esc->sc_dmaaddr = addr; 581 esc->sc_dmalen = len; 582 esc->sc_datain = datain; 583 584 /* 585 * There's no need to set up DMA for a "Transfer Pad" operation. 586 */ 587 if (*dmasize == 0) 588 return (0); 589 590 /* Set the transfer length. */ 591 WRITE_DMAREG(esc, DMA_STC, *dmasize); 592 593 /* 594 * Load the transfer buffer and program the DMA address. 595 * Note that the NCR53C9x core can't handle EINPROGRESS so we set 596 * BUS_DMA_NOWAIT. 597 */ 598 error = bus_dmamap_load(esc->sc_xferdmat, esc->sc_xferdmam, 599 *esc->sc_dmaaddr, *dmasize, esp_pci_xfermap, sc, BUS_DMA_NOWAIT); 600 601 return (error); 602 } 603 604 static void 605 esp_pci_dma_go(struct ncr53c9x_softc *sc) 606 { 607 struct esp_pci_softc *esc = (struct esp_pci_softc *)sc; 608 int datain; 609 610 datain = esc->sc_datain; 611 612 /* No DMA transfer for a "Transfer Pad" operation */ 613 if (esc->sc_dmasize == 0) 614 return; 615 616 /* Sync the transfer buffer. */ 617 bus_dmamap_sync(esc->sc_xferdmat, esc->sc_xferdmam, datain != 0 ? 618 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 619 620 /* Set the DMA engine to the IDLE state. */ 621 /* XXX DMA Transfer Interrupt Enable bit is broken? */ 622 WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | /* DMACMD_INTE | */ 623 (datain != 0 ? DMACMD_DIR : 0)); 624 625 /* Issue a DMA start command. */ 626 WRITE_DMAREG(esc, DMA_CMD, DMACMD_START | /* DMACMD_INTE | */ 627 (datain != 0 ? DMACMD_DIR : 0)); 628 629 esc->sc_active = 1; 630 } 631 632 static void 633 esp_pci_dma_stop(struct ncr53c9x_softc *sc) 634 { 635 struct esp_pci_softc *esc = (struct esp_pci_softc *)sc; 636 637 /* DMA stop */ 638 /* XXX what should we do here ? */ 639 WRITE_DMAREG(esc, DMA_CMD, 640 DMACMD_ABORT | (esc->sc_datain != 0 ? DMACMD_DIR : 0)); 641 bus_dmamap_unload(esc->sc_xferdmat, esc->sc_xferdmam); 642 643 esc->sc_active = 0; 644 } 645 646 static int 647 esp_pci_dma_isactive(struct ncr53c9x_softc *sc) 648 { 649 struct esp_pci_softc *esc = (struct esp_pci_softc *)sc; 650 651 /* XXX should we check esc->sc_active? */ 652 if ((READ_DMAREG(esc, DMA_CMD) & DMACMD_CMD) != DMACMD_IDLE) 653 return (1); 654 655 return (0); 656 } 657