1 /* $NetBSD: flsc.c,v 1.17 1997/10/24 01:50:03 mhitch Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Michael L. Hitch 5 * Copyright (c) 1995 Daniel Widenfalk 6 * Copyright (c) 1994 Christian E. Hopps 7 * Copyright (c) 1982, 1990 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Daniel Widenfalk 21 * and Michael L. Hitch. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 /* 40 * Initial amiga Fastlane driver by Daniel Widenfalk. Conversion to 41 * 53c9x MI driver by Michael L. Hitch (mhitch@montana.edu). 42 */ 43 44 #include <sys/types.h> 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/errno.h> 49 #include <sys/ioctl.h> 50 #include <sys/device.h> 51 #include <sys/buf.h> 52 #include <sys/proc.h> 53 #include <sys/user.h> 54 #include <sys/queue.h> 55 56 #include <dev/scsipi/scsi_all.h> 57 #include <dev/scsipi/scsipi_all.h> 58 #include <dev/scsipi/scsiconf.h> 59 #include <dev/scsipi/scsi_message.h> 60 61 #include <machine/cpu.h> 62 #include <machine/param.h> 63 64 #include <dev/ic/ncr53c9xreg.h> 65 #include <dev/ic/ncr53c9xvar.h> 66 67 #include <amiga/amiga/isr.h> 68 #include <amiga/dev/flscvar.h> 69 #include <amiga/dev/zbusvar.h> 70 71 void flscattach __P((struct device *, struct device *, void *)); 72 int flscmatch __P((struct device *, struct cfdata *, void *)); 73 74 /* Linkup to the rest of the kernel */ 75 struct cfattach flsc_ca = { 76 sizeof(struct flsc_softc), flscmatch, flscattach 77 }; 78 79 struct cfdriver flsc_cd = { 80 NULL, "flsc", DV_DULL 81 }; 82 83 struct scsipi_adapter flsc_switch = { 84 ncr53c9x_scsi_cmd, 85 minphys, /* no max at this level; handled by DMA code */ 86 NULL, 87 NULL, 88 }; 89 90 struct scsipi_device flsc_dev = { 91 NULL, /* Use default error handler */ 92 NULL, /* have a queue, served by this */ 93 NULL, /* have no async handler */ 94 NULL, /* Use default 'done' routine */ 95 }; 96 97 /* 98 * Functions and the switch for the MI code. 99 */ 100 u_char flsc_read_reg __P((struct ncr53c9x_softc *, int)); 101 void flsc_write_reg __P((struct ncr53c9x_softc *, int, u_char)); 102 int flsc_dma_isintr __P((struct ncr53c9x_softc *)); 103 void flsc_dma_reset __P((struct ncr53c9x_softc *)); 104 int flsc_dma_intr __P((struct ncr53c9x_softc *)); 105 int flsc_dma_setup __P((struct ncr53c9x_softc *, caddr_t *, 106 size_t *, int, size_t *)); 107 void flsc_dma_go __P((struct ncr53c9x_softc *)); 108 void flsc_dma_stop __P((struct ncr53c9x_softc *)); 109 int flsc_dma_isactive __P((struct ncr53c9x_softc *)); 110 void flsc_clear_latched_intr __P((struct ncr53c9x_softc *)); 111 112 struct ncr53c9x_glue flsc_glue = { 113 flsc_read_reg, 114 flsc_write_reg, 115 flsc_dma_isintr, 116 flsc_dma_reset, 117 flsc_dma_intr, 118 flsc_dma_setup, 119 flsc_dma_go, 120 flsc_dma_stop, 121 flsc_dma_isactive, 122 flsc_clear_latched_intr, 123 }; 124 125 /* Maximum DMA transfer length to reduce impact on high-speed serial input */ 126 u_long flsc_max_dma = 1024; 127 extern int ser_open_speed; 128 129 extern int ncr53c9x_debug; 130 extern u_long scsi_nosync; 131 extern int shift_nosync; 132 133 /* 134 * if we are an Advanced Systems & Software FastlaneZ3 135 */ 136 int 137 flscmatch(parent, cf, aux) 138 struct device *parent; 139 struct cfdata *cf; 140 void *aux; 141 { 142 struct zbus_args *zap; 143 144 if (!is_a4000() && !is_a3000()) 145 return(0); 146 147 zap = aux; 148 if (zap->manid == 0x2140 && zap->prodid == 11 149 && iszthreepa(zap->pa)) 150 return(1); 151 152 return(0); 153 } 154 155 /* 156 * Attach this instance, and then all the sub-devices 157 */ 158 void 159 flscattach(parent, self, aux) 160 struct device *parent, *self; 161 void *aux; 162 { 163 struct flsc_softc *fsc = (void *)self; 164 struct ncr53c9x_softc *sc = &fsc->sc_ncr53c9x; 165 struct zbus_args *zap; 166 167 /* 168 * Set up the glue for MI code early; we use some of it here. 169 */ 170 sc->sc_glue = &flsc_glue; 171 172 /* 173 * Save the regs 174 */ 175 zap = aux; 176 fsc->sc_dmabase = (volatile u_char *)zap->va; 177 fsc->sc_reg = &((volatile u_char *)zap->va)[0x1000001]; 178 179 sc->sc_freq = 40; /* Clocked at 40Mhz */ 180 181 printf(": address %p", fsc->sc_reg); 182 183 sc->sc_id = 7; 184 185 /* 186 * It is necessary to try to load the 2nd config register here, 187 * to find out what rev the flsc chip is, else the flsc_reset 188 * will not set up the defaults correctly. 189 */ 190 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 191 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE; 192 sc->sc_cfg3 = 0x08 /*FCLK*/ | NCRESPCFG3_FSCSI | NCRESPCFG3_CDB; 193 sc->sc_rev = NCR_VARIANT_FAS216; 194 195 /* 196 * This is the value used to start sync negotiations 197 * Note that the NCR register "SYNCTP" is programmed 198 * in "clocks per byte", and has a minimum value of 4. 199 * The SCSI period used in negotiation is one-fourth 200 * of the time (in nanoseconds) needed to transfer one byte. 201 * Since the chip's clock is given in MHz, we have the following 202 * formula: 4 * period = (1000 / freq) * 4 203 */ 204 sc->sc_minsync = 1000 / sc->sc_freq; 205 206 if (((scsi_nosync >> shift_nosync) & 0xff00) == 0xff00) 207 sc->sc_minsync = 0; 208 209 /* Really no limit, but since we want to fit into the TCR... */ 210 sc->sc_maxxfer = 64 * 1024; 211 212 fsc->sc_portbits = 0xa0 | FLSC_PB_EDI | FLSC_PB_ESI; 213 fsc->sc_hardbits = fsc->sc_reg[0x40]; 214 215 fsc->sc_alignbuf = (char *)((u_long)fsc->sc_unalignbuf & -4); 216 217 sc->sc_dev.dv_cfdata->cf_flags |= (scsi_nosync >> shift_nosync) & 0xffff; 218 shift_nosync += 16; 219 ncr53c9x_debug |= (scsi_nosync >> shift_nosync) & 0xffff; 220 shift_nosync += 16; 221 222 /* 223 * Configure interrupts. 224 */ 225 fsc->sc_isr.isr_intr = (int (*)(void *))ncr53c9x_intr; 226 fsc->sc_isr.isr_arg = sc; 227 fsc->sc_isr.isr_ipl = 2; 228 add_isr(&fsc->sc_isr); 229 230 fsc->sc_reg[0x40] = fsc->sc_portbits; 231 232 /* 233 * Now try to attach all the sub-devices 234 */ 235 ncr53c9x_attach(sc, &flsc_switch, &flsc_dev); 236 } 237 238 /* 239 * Glue functions. 240 */ 241 242 u_char 243 flsc_read_reg(sc, reg) 244 struct ncr53c9x_softc *sc; 245 int reg; 246 { 247 struct flsc_softc *fsc = (struct flsc_softc *)sc; 248 249 return fsc->sc_reg[reg * 4]; 250 } 251 252 void 253 flsc_write_reg(sc, reg, val) 254 struct ncr53c9x_softc *sc; 255 int reg; 256 u_char val; 257 { 258 struct flsc_softc *fsc = (struct flsc_softc *)sc; 259 struct ncr53c9x_tinfo *ti; 260 u_char v = val; 261 262 if (fsc->sc_piomode && reg == NCR_CMD && 263 v == (NCRCMD_TRANS|NCRCMD_DMA)) { 264 v = NCRCMD_TRANS; 265 } 266 /* 267 * Can't do synchronous transfers in SCSI_POLL mode: 268 * If starting SCSI_POLL command, clear defer sync negotiation 269 * by clearing the T_NEGOTIATE flag. If starting SCSI_POLL and 270 * the device is currently running synchronous, force another 271 * T_NEGOTIATE with 0 offset. 272 */ 273 if (reg == NCR_SELID) { 274 ti = &sc->sc_tinfo[ 275 sc->sc_nexus->xs->sc_link->scsipi_scsi.target]; 276 if (sc->sc_nexus->xs->flags & SCSI_POLL) { 277 if (ti->flags & T_SYNCMODE) { 278 ti->flags ^= T_SYNCMODE | T_NEGOTIATE; 279 } else if (ti->flags & T_NEGOTIATE) { 280 ti->flags ^= T_NEGOTIATE | T_SYNCHOFF; 281 /* save T_NEGOTIATE in private flags? */ 282 } 283 } else { 284 /* 285 * If we haven't attempted sync negotiation yet, 286 * do it now. 287 */ 288 if ((ti->flags & (T_SYNCMODE | T_SYNCHOFF)) == 289 T_SYNCHOFF && 290 sc->sc_minsync != 0) /* XXX */ 291 ti->flags ^= T_NEGOTIATE | T_SYNCHOFF; 292 } 293 } 294 if (reg == NCR_CMD && v == NCRCMD_SETATN && 295 sc->sc_flags & NCR_SYNCHNEGO && 296 sc->sc_nexus->xs->flags & SCSI_POLL) { 297 ti = &sc->sc_tinfo[ 298 sc->sc_nexus->xs->sc_link->scsipi_scsi.target]; 299 ti->offset = 0; 300 } 301 fsc->sc_reg[reg * 4] = v; 302 } 303 304 int 305 flsc_dma_isintr(sc) 306 struct ncr53c9x_softc *sc; 307 { 308 struct flsc_softc *fsc = (struct flsc_softc *)sc; 309 unsigned hardbits; 310 311 hardbits = fsc->sc_reg[0x40]; 312 if (hardbits & FLSC_HB_IACT) 313 return (fsc->sc_csr = 0); 314 315 if (sc->sc_state == NCR_CONNECTED || sc->sc_state == NCR_SELECTING) 316 fsc->sc_portbits |= FLSC_PB_LED; 317 else 318 fsc->sc_portbits &= ~FLSC_PB_LED; 319 320 if ((hardbits & FLSC_HB_CREQ) && !(hardbits & FLSC_HB_MINT) && 321 fsc->sc_reg[NCR_STAT * 4] & NCRSTAT_INT) { 322 return 1; 323 } 324 /* Do I still need this? */ 325 if (fsc->sc_piomode && fsc->sc_reg[NCR_STAT * 4] & NCRSTAT_INT && 326 !(hardbits & FLSC_HB_MINT)) 327 return 1; 328 329 fsc->sc_reg[0x40] = fsc->sc_portbits & ~FLSC_PB_INT_BITS; 330 fsc->sc_reg[0x40] = fsc->sc_portbits; 331 return 0; 332 } 333 334 void 335 flsc_clear_latched_intr(sc) 336 struct ncr53c9x_softc *sc; 337 { 338 struct flsc_softc *fsc = (struct flsc_softc *)sc; 339 340 fsc->sc_reg[0x40] = fsc->sc_portbits & ~FLSC_PB_INT_BITS; 341 fsc->sc_reg[0x40] = fsc->sc_portbits; 342 } 343 344 void 345 flsc_dma_reset(sc) 346 struct ncr53c9x_softc *sc; 347 { 348 struct flsc_softc *fsc = (struct flsc_softc *)sc; 349 struct ncr53c9x_tinfo *ti; 350 351 if (sc->sc_nexus) 352 ti = &sc->sc_tinfo[sc->sc_nexus->xs->sc_link->scsipi_scsi.target]; 353 else 354 ti = &sc->sc_tinfo[1]; /* XXX */ 355 if (fsc->sc_active) { 356 printf("dmaaddr %p dmasize %d stat %x flags %x off %d per %d ff %x", 357 *fsc->sc_dmaaddr, fsc->sc_dmasize, fsc->sc_reg[NCR_STAT * 4], 358 ti->flags, ti->offset, ti->period, fsc->sc_reg[NCR_FFLAG * 4]); 359 printf(" intr %x\n", fsc->sc_reg[NCR_INTR * 4]); 360 #ifdef DDB 361 Debugger(); 362 #endif 363 } 364 fsc->sc_portbits &= ~FLSC_PB_DMA_BITS; 365 fsc->sc_reg[0x40] = fsc->sc_portbits; 366 fsc->sc_reg[0x80] = 0; 367 *((u_long *)fsc->sc_dmabase) = 0; 368 fsc->sc_active = 0; 369 fsc->sc_piomode = 0; 370 } 371 372 int 373 flsc_dma_intr(sc) 374 struct ncr53c9x_softc *sc; 375 { 376 register struct flsc_softc *fsc = (struct flsc_softc *)sc; 377 register u_char *p; 378 volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg; 379 register u_int flscphase, flscstat, flscintr; 380 register int cnt; 381 382 NCR_DMA(("flsc_dma_intr: pio %d cnt %d int %x stat %x fifo %d ", 383 fsc->sc_piomode, fsc->sc_dmasize, sc->sc_espintr, sc->sc_espstat, 384 fsc->sc_reg[NCR_FFLAG * 4] & NCRFIFO_FF)); 385 if (!(fsc->sc_reg[0x40] & FLSC_HB_CREQ)) 386 printf("flsc_dma_intr: csr %x stat %x intr %x\n", fsc->sc_csr, 387 sc->sc_espstat, sc->sc_espintr); 388 if (fsc->sc_active == 0) { 389 printf("flsc_intr--inactive DMA\n"); 390 return -1; 391 } 392 393 /* if DMA transfer, update sc_dmaaddr and sc_pdmalen, else PIO xfer */ 394 if (fsc->sc_piomode == 0) { 395 fsc->sc_portbits &= ~FLSC_PB_DMA_BITS; 396 fsc->sc_reg[0x40] = fsc->sc_portbits; 397 fsc->sc_reg[0x80] = 0; 398 *((u_long *)fsc->sc_dmabase) = 0; 399 cnt = fsc->sc_reg[NCR_TCL * 4]; 400 cnt += fsc->sc_reg[NCR_TCM * 4] << 8; 401 cnt += fsc->sc_reg[NCR_TCH * 4] << 16; 402 if (!fsc->sc_datain) { 403 cnt += fsc->sc_reg[NCR_FFLAG * 4] & NCRFIFO_FF; 404 fsc->sc_reg[NCR_CMD * 4] = NCRCMD_FLUSH; 405 } 406 cnt = fsc->sc_dmasize - cnt; /* number of bytes transferred */ 407 NCR_DMA(("DMA xferred %d\n", cnt)); 408 if (fsc->sc_xfr_align) { 409 int i; 410 for (i = 0; i < cnt; ++i) 411 (*fsc->sc_dmaaddr)[i] = fsc->sc_alignbuf[i]; 412 fsc->sc_xfr_align = 0; 413 } 414 *fsc->sc_dmaaddr += cnt; 415 *fsc->sc_pdmalen -= cnt; 416 fsc->sc_active = 0; 417 return 0; 418 } 419 420 if ((sc->sc_espintr & NCRINTR_BS) == 0) { 421 fsc->sc_active = 0; 422 fsc->sc_piomode = 0; 423 NCR_DMA(("no NCRINTR_BS\n")); 424 return 0; 425 } 426 427 cnt = fsc->sc_dmasize; 428 #if 0 429 if (cnt == 0) { 430 printf("data interrupt, but no count left."); 431 } 432 #endif 433 434 p = *fsc->sc_dmaaddr; 435 flscphase = sc->sc_phase; 436 flscstat = (u_int) sc->sc_espstat; 437 flscintr = (u_int) sc->sc_espintr; 438 cmdreg = fsc->sc_reg + NCR_CMD * 4; 439 fiforeg = fsc->sc_reg + NCR_FIFO * 4; 440 statreg = fsc->sc_reg + NCR_STAT * 4; 441 intrreg = fsc->sc_reg + NCR_INTR * 4; 442 NCR_DMA(("PIO %d datain %d phase %d stat %x intr %x\n", 443 cnt, fsc->sc_datain, flscphase, flscstat, flscintr)); 444 do { 445 if (fsc->sc_datain) { 446 *p++ = *fiforeg; 447 cnt--; 448 if (flscphase == DATA_IN_PHASE) { 449 *cmdreg = NCRCMD_TRANS; 450 } else { 451 fsc->sc_active = 0; 452 } 453 } else { 454 NCR_DMA(("flsc_dma_intr: PIO out- phase %d cnt %d active %d\n", flscphase, cnt, 455 fsc->sc_active)); 456 if ( (flscphase == DATA_OUT_PHASE) 457 || (flscphase == MESSAGE_OUT_PHASE)) { 458 int n; 459 n = 16 - (fsc->sc_reg[NCR_FFLAG * 4] & NCRFIFO_FF); 460 if (n > cnt) 461 n = cnt; 462 cnt -= n; 463 while (n-- > 0) 464 *fiforeg = *p++; 465 *cmdreg = NCRCMD_TRANS; 466 } else { 467 fsc->sc_active = 0; 468 } 469 } 470 471 if (fsc->sc_active && cnt) { 472 while (!(*statreg & 0x80)); 473 flscstat = *statreg; 474 flscintr = *intrreg; 475 flscphase = (flscintr & NCRINTR_DIS) 476 ? /* Disconnected */ BUSFREE_PHASE 477 : flscstat & PHASE_MASK; 478 } 479 } while (cnt && fsc->sc_active && (flscintr & NCRINTR_BS)); 480 #if 1 481 if (fsc->sc_dmasize < 8 && cnt) 482 printf("flsc_dma_intr: short transfer: dmasize %d cnt %d\n", 483 fsc->sc_dmasize, cnt); 484 #endif 485 NCR_DMA(("flsc_dma_intr: PIO transfer [%d], %d->%d phase %d stat %x intr %x\n", 486 *fsc->sc_pdmalen, fsc->sc_dmasize, cnt, flscphase, flscstat, flscintr)); 487 sc->sc_phase = flscphase; 488 sc->sc_espstat = (u_char) flscstat; 489 sc->sc_espintr = (u_char) flscintr; 490 *fsc->sc_dmaaddr = p; 491 *fsc->sc_pdmalen -= fsc->sc_dmasize - cnt; 492 fsc->sc_dmasize = cnt; 493 494 if (*fsc->sc_pdmalen == 0) { 495 sc->sc_espstat |= NCRSTAT_TC; 496 fsc->sc_piomode = 0; 497 } 498 return 0; 499 } 500 501 int 502 flsc_dma_setup(sc, addr, len, datain, dmasize) 503 struct ncr53c9x_softc *sc; 504 caddr_t *addr; 505 size_t *len; 506 int datain; 507 size_t *dmasize; 508 { 509 struct flsc_softc *fsc = (struct flsc_softc *)sc; 510 vm_offset_t pa; 511 u_char *ptr; 512 size_t xfer; 513 514 fsc->sc_dmaaddr = addr; 515 fsc->sc_pdmalen = len; 516 fsc->sc_datain = datain; 517 fsc->sc_dmasize = *dmasize; 518 if (sc->sc_nexus->xs->flags & SCSI_POLL) { 519 /* polling mode, use PIO */ 520 *dmasize = fsc->sc_dmasize; 521 NCR_DMA(("pfsc_dma_setup: PIO %p/%d [%d]\n", *addr, 522 fsc->sc_dmasize, *len)); 523 fsc->sc_piomode = 1; 524 if (datain == 0) { 525 int n; 526 n = fsc->sc_dmasize; 527 if (n > 16) 528 n = 16; 529 while (n-- > 0) { 530 fsc->sc_reg[NCR_FIFO * 4] = **fsc->sc_dmaaddr; 531 (*fsc->sc_pdmalen)--; 532 (*fsc->sc_dmaaddr)++; 533 --fsc->sc_dmasize; 534 } 535 } 536 return 0; 537 } 538 /* 539 * DMA can be nasty for high-speed serial input, so limit the 540 * size of this DMA operation if the serial port is running at 541 * a high speed (higher than 19200 for now - should be adjusted 542 * based on cpu type and speed?). 543 * XXX - add serial speed check XXX 544 */ 545 if (ser_open_speed > 19200 && flsc_max_dma != 0 && 546 fsc->sc_dmasize > flsc_max_dma) 547 fsc->sc_dmasize = flsc_max_dma; 548 ptr = *addr; /* Kernel virtual address */ 549 pa = kvtop(ptr); /* Physical address of DMA */ 550 xfer = min(fsc->sc_dmasize, NBPG - (pa & (NBPG - 1))); 551 fsc->sc_xfr_align = 0; 552 fsc->sc_piomode = 0; 553 fsc->sc_portbits &= ~FLSC_PB_DMA_BITS; 554 fsc->sc_reg[0x40] = fsc->sc_portbits; 555 fsc->sc_reg[0x80] = 0; 556 *((u_long *)fsc->sc_dmabase) = 0; 557 558 /* 559 * If output and length < 16, copy to fifo 560 */ 561 if (datain == 0 && fsc->sc_dmasize < 16) { 562 int n; 563 for (n = 0; n < fsc->sc_dmasize; ++n) 564 fsc->sc_reg[NCR_FIFO * 4] = *ptr++; 565 NCR_DMA(("flsc_dma_setup: %d bytes written to fifo\n", n)); 566 fsc->sc_piomode = 1; 567 fsc->sc_active = 1; 568 *fsc->sc_pdmalen -= fsc->sc_dmasize; 569 *fsc->sc_dmaaddr += fsc->sc_dmasize; 570 *dmasize = fsc->sc_dmasize; 571 fsc->sc_dmasize = 0; 572 return 0; /* All done */ 573 } 574 /* 575 * If output and unaligned, copy unaligned data to fifo 576 */ 577 else if (datain == 0 && (int)ptr & 3) { 578 int n = 4 - ((int)ptr & 3); 579 NCR_DMA(("flsc_dma_setup: align %d bytes written to fifo\n", n)); 580 pa += n; 581 xfer -= n; 582 while (n--) 583 fsc->sc_reg[NCR_FIFO * 4] = *ptr++; 584 } 585 /* 586 * If unaligned address, read unaligned bytes into alignment buffer 587 */ 588 else if ((int)ptr & 3 || xfer & 3) { 589 pa = kvtop((caddr_t)fsc->sc_alignbuf); 590 xfer = fsc->sc_dmasize = min(xfer, sizeof (fsc->sc_unalignbuf)); 591 NCR_DMA(("flsc_dma_setup: align read by %d bytes\n", xfer)); 592 fsc->sc_xfr_align = 1; 593 } 594 /* 595 * If length smaller than longword, read into alignment buffer 596 * XXX doesn't work for 1 or 2 bytes !!!! 597 */ 598 else if (fsc->sc_dmasize < 4) { 599 NCR_DMA(("flsc_dma_setup: read remaining %d bytes\n", 600 fsc->sc_dmasize)); 601 pa = kvtop((caddr_t)fsc->sc_alignbuf); 602 fsc->sc_xfr_align = 1; 603 } 604 /* 605 * Finally, limit transfer length to multiple of 4 bytes. 606 */ 607 else { 608 fsc->sc_dmasize &= -4; 609 xfer &= -4; 610 } 611 612 while (xfer < fsc->sc_dmasize) { 613 if ((pa + xfer) != kvtop(*addr + xfer)) 614 break; 615 if ((fsc->sc_dmasize - xfer) < NBPG) 616 xfer = fsc->sc_dmasize; 617 else 618 xfer += NBPG; 619 } 620 621 fsc->sc_dmasize = xfer; 622 *dmasize = fsc->sc_dmasize; 623 fsc->sc_pa = pa; 624 #if defined(M68040) || defined(M68060) 625 if (mmutype == MMU_68040) { 626 if (fsc->sc_xfr_align) { 627 int n; 628 for (n = 0; n < sizeof (fsc->sc_unalignbuf); ++n) 629 fsc->sc_alignbuf[n] = n | 0x80; 630 dma_cachectl(fsc->sc_alignbuf, 631 sizeof(fsc->sc_unalignbuf)); 632 } 633 else 634 dma_cachectl(*fsc->sc_dmaaddr, fsc->sc_dmasize); 635 } 636 #endif 637 fsc->sc_reg[0x80] = 0; 638 *((u_long *)(fsc->sc_dmabase + (pa & 0x00fffffc))) = pa; 639 fsc->sc_portbits &= ~FLSC_PB_DMA_BITS; 640 fsc->sc_portbits |= FLSC_PB_ENABLE_DMA | 641 (fsc->sc_datain ? FLSC_PB_DMA_READ : FLSC_PB_DMA_WRITE); 642 fsc->sc_reg[0x40] = fsc->sc_portbits; 643 NCR_DMA(("flsc_dma_setup: DMA %p->%lx/%d [%d]\n", 644 ptr, pa, fsc->sc_dmasize, *len)); 645 fsc->sc_active = 1; 646 return 0; 647 } 648 649 void 650 flsc_dma_go(sc) 651 struct ncr53c9x_softc *sc; 652 { 653 struct flsc_softc *fsc = (struct flsc_softc *)sc; 654 655 NCR_DMA(("flsc_dma_go: datain %d size %d\n", fsc->sc_datain, 656 fsc->sc_dmasize)); 657 if (sc->sc_nexus->xs->flags & SCSI_POLL) { 658 fsc->sc_active = 1; 659 return; 660 } else if (fsc->sc_piomode == 0) { 661 fsc->sc_portbits &= ~FLSC_PB_DMA_BITS; 662 fsc->sc_portbits |= FLSC_PB_ENABLE_DMA | 663 (fsc->sc_datain ? FLSC_PB_DMA_READ : FLSC_PB_DMA_WRITE); 664 fsc->sc_reg[0x40] = fsc->sc_portbits; 665 } 666 } 667 668 void 669 flsc_dma_stop(sc) 670 struct ncr53c9x_softc *sc; 671 { 672 struct flsc_softc *fsc = (struct flsc_softc *)sc; 673 674 fsc->sc_portbits &= ~FLSC_PB_DMA_BITS; 675 fsc->sc_reg[0x40] = fsc->sc_portbits; 676 677 fsc->sc_reg[0x80] = 0; 678 *((u_long *)fsc->sc_dmabase) = 0; 679 fsc->sc_piomode = 0; 680 } 681 682 int 683 flsc_dma_isactive(sc) 684 struct ncr53c9x_softc *sc; 685 { 686 struct flsc_softc *fsc = (struct flsc_softc *)sc; 687 688 return fsc->sc_active; 689 } 690