1 /* $NetBSD: asc.c,v 1.14 2003/05/03 18:10:52 wiz Exp $ */ 2 /*- 3 * Copyright (c) 2000 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Wayne Knowles 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include <sys/types.h> 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/errno.h> 43 #include <sys/device.h> 44 #include <sys/buf.h> 45 #include <sys/malloc.h> 46 47 #include <uvm/uvm_extern.h> 48 49 #include <dev/scsipi/scsi_all.h> 50 #include <dev/scsipi/scsipi_all.h> 51 #include <dev/scsipi/scsiconf.h> 52 #include <dev/scsipi/scsi_message.h> 53 54 #include <machine/cpu.h> 55 #include <machine/autoconf.h> 56 #include <machine/mainboard.h> 57 #include <machine/bus.h> 58 59 #include <mipsco/obio/rambo.h> 60 61 #include <dev/ic/ncr53c9xreg.h> 62 #include <dev/ic/ncr53c9xvar.h> 63 64 struct asc_softc { 65 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ 66 struct evcnt sc_intrcnt; /* Interrupt counter */ 67 bus_space_tag_t sc_bst; 68 bus_space_handle_t sc_bsh; /* NCR 53c94 registers */ 69 bus_space_handle_t dm_bsh; /* RAMBO registers */ 70 bus_dma_tag_t sc_dmat; 71 bus_dmamap_t sc_dmamap; 72 caddr_t *sc_dmaaddr; 73 size_t *sc_dmalen; 74 size_t sc_dmasize; 75 int sc_flags; 76 #define DMA_IDLE 0x0 77 #define DMA_PULLUP 0x1 78 #define DMA_ACTIVE 0x2 79 #define DMA_MAPLOADED 0x4 80 u_int32_t dm_mode; 81 int dm_curseg; 82 }; 83 84 static int ascmatch (struct device *, struct cfdata *, void *); 85 static void ascattach (struct device *, struct device *, void *); 86 87 CFATTACH_DECL(asc, sizeof(struct asc_softc), 88 ascmatch, ascattach, NULL, NULL); 89 90 /* 91 * Functions and the switch for the MI code. 92 */ 93 static u_char asc_read_reg (struct ncr53c9x_softc *, int); 94 static void asc_write_reg (struct ncr53c9x_softc *, int, u_char); 95 static int asc_dma_isintr (struct ncr53c9x_softc *); 96 static void asc_dma_reset (struct ncr53c9x_softc *); 97 static int asc_dma_intr (struct ncr53c9x_softc *); 98 static int asc_dma_setup (struct ncr53c9x_softc *, caddr_t *, 99 size_t *, int, size_t *); 100 static void asc_dma_go (struct ncr53c9x_softc *); 101 static void asc_dma_stop (struct ncr53c9x_softc *); 102 static int asc_dma_isactive (struct ncr53c9x_softc *); 103 104 static struct ncr53c9x_glue asc_glue = { 105 asc_read_reg, 106 asc_write_reg, 107 asc_dma_isintr, 108 asc_dma_reset, 109 asc_dma_intr, 110 asc_dma_setup, 111 asc_dma_go, 112 asc_dma_stop, 113 asc_dma_isactive, 114 NULL, /* gl_clear_latched_intr */ 115 }; 116 117 static int asc_intr (void *); 118 119 #define MAX_SCSI_XFER (64*1024) 120 #define MAX_DMA_SZ MAX_SCSI_XFER 121 #define DMA_SEGS (MAX_DMA_SZ/PAGE_SIZE) 122 123 static int 124 ascmatch(struct device *parent, struct cfdata *cf, void *aux) 125 { 126 return 1; 127 } 128 129 static void 130 ascattach(struct device *parent, struct device *self, void *aux) 131 { 132 struct confargs *ca = aux; 133 struct asc_softc *esc = (void *)self; 134 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 135 136 /* 137 * Set up glue for MI code early; we use some of it here. 138 */ 139 sc->sc_glue = &asc_glue; 140 141 esc->sc_bst = ca->ca_bustag; 142 esc->sc_dmat = ca->ca_dmatag; 143 144 if (bus_space_map(ca->ca_bustag, ca->ca_addr, 145 16*4, /* sizeof (ncr53c9xreg) */ 146 BUS_SPACE_MAP_LINEAR, 147 &esc->sc_bsh) != 0) { 148 printf(": cannot map registers\n"); 149 return; 150 } 151 152 if (bus_space_map(ca->ca_bustag, RAMBO_BASE, sizeof(struct rambo_ch), 153 BUS_SPACE_MAP_LINEAR, 154 &esc->dm_bsh) != 0) { 155 printf(": cannot map DMA registers\n"); 156 return; 157 } 158 159 if (bus_dmamap_create(esc->sc_dmat, MAX_DMA_SZ, 160 DMA_SEGS, MAX_DMA_SZ, RB_BOUNDRY, 161 BUS_DMA_WAITOK, 162 &esc->sc_dmamap) != 0) { 163 printf(": failed to create dmamap\n"); 164 return; 165 } 166 167 evcnt_attach_dynamic(&esc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 168 self->dv_xname, "intr"); 169 170 esc->sc_flags = DMA_IDLE; 171 asc_dma_reset(sc); 172 173 /* Other settings */ 174 sc->sc_id = 7; 175 sc->sc_freq = 24; /* 24 MHz clock */ 176 177 /* 178 * Setup for genuine NCR 53C94 SCSI Controller 179 */ 180 181 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 182 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE; 183 sc->sc_cfg3 = NCRCFG3_CDB | NCRCFG3_QTE | NCRCFG3_FSCSI; 184 sc->sc_rev = NCR_VARIANT_NCR53C94; 185 186 sc->sc_minsync = (1000 / sc->sc_freq) * 5 / 4; 187 sc->sc_maxxfer = MAX_SCSI_XFER; 188 189 #ifdef OLDNCR 190 if (!NCR_READ_REG(sc, NCR_CFG3)) { 191 printf(" [old revision]"); 192 sc->sc_cfg2 = 0; 193 sc->sc_cfg3 = 0; 194 sc->sc_minsync = 0; 195 } 196 #endif 197 198 sc->sc_adapter.adapt_minphys = minphys; 199 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 200 ncr53c9x_attach(sc); 201 202 bus_intr_establish(esc->sc_bst, SYS_INTR_SCSI, 0, 0, asc_intr, esc); 203 } 204 205 /* 206 * Glue functions. 207 */ 208 209 static u_char 210 asc_read_reg(struct ncr53c9x_softc *sc, int reg) 211 { 212 struct asc_softc *esc = (struct asc_softc *)sc; 213 214 return bus_space_read_1(esc->sc_bst, esc->sc_bsh, reg * 4 + 3); 215 } 216 217 static void 218 asc_write_reg(struct ncr53c9x_softc *sc, int reg, u_char val) 219 { 220 struct asc_softc *esc = (struct asc_softc *)sc; 221 222 bus_space_write_1(esc->sc_bst, esc->sc_bsh, reg * 4 + 3, val); 223 } 224 225 static void 226 dma_status(struct ncr53c9x_softc *sc) 227 { 228 struct asc_softc *esc = (struct asc_softc *)sc; 229 int count; 230 int stat; 231 void *addr; 232 u_int32_t tc; 233 234 tc = (asc_read_reg(sc, NCR_TCM)<<8) + asc_read_reg(sc, NCR_TCL); 235 count = bus_space_read_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT); 236 stat = bus_space_read_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE); 237 addr = (void *) 238 bus_space_read_4(esc->sc_bst, esc->dm_bsh, RAMBO_CADDR); 239 240 printf("rambo status: cnt=%x addr=%p stat=%08x tc=%04x " 241 "ncr_stat=0x%02x ncr_fifo=0x%02x\n", 242 count, addr, stat, tc, 243 asc_read_reg(sc, NCR_STAT), 244 asc_read_reg(sc, NCR_FFLAG)); 245 } 246 247 static __inline void 248 check_fifo(struct asc_softc *esc) 249 { 250 register int i=100; 251 252 while (i && !(bus_space_read_4(esc->sc_bst, esc->dm_bsh, 253 RAMBO_MODE) & RB_FIFO_EMPTY)) { 254 DELAY(1); i--; 255 } 256 257 if (!i) { 258 dma_status((void *)esc); 259 panic("fifo didn't flush"); 260 } 261 } 262 263 static int 264 asc_dma_isintr(struct ncr53c9x_softc *sc) 265 { 266 return NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT; 267 } 268 269 static void 270 asc_dma_reset(struct ncr53c9x_softc *sc) 271 { 272 struct asc_softc *esc = (struct asc_softc *)sc; 273 274 bus_space_write_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT, 0); 275 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, 276 RB_CLRFIFO|RB_CLRERROR); 277 DELAY(10); 278 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, 0); 279 280 if (esc->sc_flags & DMA_MAPLOADED) 281 bus_dmamap_unload(esc->sc_dmat, esc->sc_dmamap); 282 283 esc->sc_flags = DMA_IDLE; 284 } 285 286 /* 287 * Setup a DMA transfer 288 */ 289 290 static int 291 asc_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len, 292 int datain, size_t *dmasize) 293 { 294 struct asc_softc *esc = (struct asc_softc *)sc; 295 paddr_t paddr; 296 size_t count, blocks; 297 int prime, err; 298 299 #ifdef DIAGNOSTIC 300 if (esc->sc_flags & DMA_ACTIVE) { 301 dma_status(sc); 302 panic("DMA active"); 303 } 304 #endif 305 306 esc->sc_dmaaddr = addr; 307 esc->sc_dmalen = len; 308 esc->sc_dmasize = *dmasize; 309 esc->sc_flags = datain ? DMA_PULLUP : 0; 310 311 NCR_DMA(("asc_dma_setup va=%p len=%d datain=%d count=%d\n", 312 *addr, *len, datain, esc->sc_dmasize)); 313 314 if (esc->sc_dmasize == 0) 315 return 0; 316 317 /* have dmamap for the transfering addresses */ 318 if ((err=bus_dmamap_load(esc->sc_dmat, esc->sc_dmamap, 319 *esc->sc_dmaaddr, esc->sc_dmasize, 320 NULL /* kernel address */, 321 BUS_DMA_NOWAIT)) != 0) 322 panic("%s: bus_dmamap_load err=%d", sc->sc_dev.dv_xname, err); 323 324 esc->sc_flags |= DMA_MAPLOADED; 325 326 paddr = esc->sc_dmamap->dm_segs[0].ds_addr; 327 count = esc->sc_dmamap->dm_segs[0].ds_len; 328 prime = (u_int32_t)paddr & 0x3f; 329 blocks = (prime + count + 63) >> 6; 330 331 esc->dm_mode = (datain ? RB_DMA_WR : RB_DMA_RD); 332 333 /* Set transfer direction and disable DMA */ 334 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, esc->dm_mode); 335 336 /* Load DMA transfer address */ 337 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_LADDR, 338 paddr & ~0x3f); 339 340 /* Load number of blocks to DMA (1 block = 64 bytes) */ 341 bus_space_write_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT, blocks); 342 343 /* If non block-aligned transfer prime FIFO manually */ 344 if (prime) { 345 /* Enable DMA to prime the FIFO buffer */ 346 bus_space_write_4(esc->sc_bst, esc->dm_bsh, 347 RAMBO_MODE, esc->dm_mode | RB_DMA_ENABLE); 348 349 if (esc->sc_flags & DMA_PULLUP) { 350 /* Read from NCR 53c94 controller*/ 351 u_int16_t *p; 352 353 p = (u_int16_t *)((u_int32_t)*esc->sc_dmaaddr & ~0x3f); 354 bus_space_write_multi_2(esc->sc_bst, esc->dm_bsh, 355 RAMBO_FIFO, p, prime>>1); 356 } else 357 /* Write to NCR 53C94 controller */ 358 while (prime > 0) { 359 (void)bus_space_read_2(esc->sc_bst, 360 esc->dm_bsh, 361 RAMBO_FIFO); 362 prime -= 2; 363 } 364 /* Leave DMA disabled while we setup NCR controller */ 365 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, 366 esc->dm_mode); 367 } 368 369 bus_dmamap_sync(esc->sc_dmat, esc->sc_dmamap, 0, esc->sc_dmasize, 370 datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 371 372 esc->dm_curseg = 0; 373 esc->dm_mode |= RB_DMA_ENABLE; 374 if (esc->sc_dmamap->dm_nsegs > 1) 375 esc->dm_mode |= RB_INT_ENABLE; /* Requires DMA chaining */ 376 377 return 0; 378 } 379 380 static void 381 asc_dma_go(struct ncr53c9x_softc *sc) 382 { 383 struct asc_softc *esc = (struct asc_softc *)sc; 384 385 /* Start DMA */ 386 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, esc->dm_mode); 387 388 esc->sc_flags |= DMA_ACTIVE; 389 } 390 391 static int 392 asc_dma_intr(struct ncr53c9x_softc *sc) 393 { 394 struct asc_softc *esc = (struct asc_softc *)sc; 395 396 size_t resid, len; 397 int trans; 398 u_int32_t status; 399 u_int tcl, tcm; 400 401 #ifdef DIAGNOSTIC 402 if (!(esc->sc_flags & DMA_ACTIVE)) { 403 dma_status(sc); 404 panic("DMA not active"); 405 } 406 #endif 407 408 resid = 0; 409 if (!(esc->sc_flags & DMA_PULLUP) && 410 (resid = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { 411 NCR_DMA(("asc_intr: empty FIFO of %d ", resid)); 412 DELAY(10); 413 } 414 415 resid += (tcl = NCR_READ_REG(sc, NCR_TCL)) + 416 ((tcm = NCR_READ_REG(sc, NCR_TCM)) << 8); 417 418 if (esc->sc_dmasize == 0) { /* Transfer pad operation */ 419 NCR_DMA(("asc_intr: discard %d bytes\n", resid)); 420 return 0; 421 } 422 423 trans = esc->sc_dmasize - resid; 424 if (trans < 0) { /* transferred < 0 ? */ 425 printf("asc_intr: xfer (%d) > req (%d)\n", 426 trans, esc->sc_dmasize); 427 trans = esc->sc_dmasize; 428 } 429 430 NCR_DMA(("asc_intr: tcl=%d, tcm=%d; trans=%d, resid=%d\n", 431 tcl, tcm, trans, resid)); 432 433 status = bus_space_read_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE); 434 435 if (!(status & RB_FIFO_EMPTY)) { /* Data left in RAMBO FIFO */ 436 if (esc->sc_flags & DMA_PULLUP) { /* SCSI Read */ 437 paddr_t ptr; 438 u_int16_t *p; 439 440 resid = status & 0x1f; 441 442 /* take the address of block to fixed up */ 443 ptr = bus_space_read_4(esc->sc_bst, esc->dm_bsh, 444 RAMBO_CADDR); 445 /* find the starting address of fractional data */ 446 p = (u_int16_t *)MIPS_PHYS_TO_KSEG0(ptr+(resid<<1)); 447 448 /* duplicate trailing data to FIFO for force flush */ 449 len = RB_BLK_CNT - resid; 450 bus_space_write_multi_2(esc->sc_bst, esc->dm_bsh, 451 RAMBO_FIFO, p, len); 452 check_fifo(esc); 453 } else { /* SCSI Write */ 454 bus_space_write_4(esc->sc_bst, esc->dm_bsh, 455 RAMBO_MODE, 0); 456 bus_space_write_4(esc->sc_bst, esc->dm_bsh, 457 RAMBO_MODE, RB_CLRFIFO); 458 } 459 } 460 461 bus_space_write_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT, 0); 462 463 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, 0); 464 465 bus_dmamap_sync(esc->sc_dmat, esc->sc_dmamap, 466 0, esc->sc_dmasize, 467 (esc->sc_flags & DMA_PULLUP) 468 ? BUS_DMASYNC_POSTREAD 469 : BUS_DMASYNC_POSTWRITE); 470 bus_dmamap_unload(esc->sc_dmat, esc->sc_dmamap); 471 472 *esc->sc_dmaaddr += trans; 473 *esc->sc_dmalen -= trans; 474 475 esc->sc_flags = DMA_IDLE; 476 477 return 0; 478 } 479 480 481 static void 482 asc_dma_stop(struct ncr53c9x_softc *sc) 483 { 484 struct asc_softc *esc = (struct asc_softc *)sc; 485 486 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, 0); 487 if (esc->sc_flags & DMA_MAPLOADED) 488 bus_dmamap_unload(esc->sc_dmat, esc->sc_dmamap); 489 esc->sc_flags = DMA_IDLE; 490 } 491 492 static int 493 asc_dma_isactive(struct ncr53c9x_softc *sc) 494 { 495 struct asc_softc *esc = (struct asc_softc *)sc; 496 return (esc->sc_flags & DMA_ACTIVE)? 1 : 0; 497 } 498 499 static void 500 rambo_dma_chain(struct asc_softc *esc) 501 { 502 int seg; 503 size_t count, blocks; 504 paddr_t paddr; 505 506 seg = ++esc->dm_curseg; 507 508 #ifdef DIAGNOSTIC 509 if (!(esc->sc_flags & DMA_ACTIVE) || seg > esc->sc_dmamap->dm_nsegs) 510 panic("Unexpected DMA chaining intr"); 511 512 /* Interrupt can only occur at terminal count, but double check */ 513 if (bus_space_read_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT)) { 514 dma_status((void *)esc); 515 panic("rambo blkcnt != 0"); 516 } 517 #endif 518 519 paddr = esc->sc_dmamap->dm_segs[seg].ds_addr; 520 count = esc->sc_dmamap->dm_segs[seg].ds_len; 521 blocks = (count + 63) >> 6; 522 523 /* Disable DMA interrupt if last segment */ 524 if (seg+1 > esc->sc_dmamap->dm_nsegs) { 525 bus_space_write_4(esc->sc_bst, esc->dm_bsh, 526 RAMBO_MODE, esc->dm_mode & ~RB_INT_ENABLE); 527 } 528 529 /* Load transfer address for next DMA chain */ 530 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_LADDR, paddr); 531 532 /* DMA restarts when we enter a new block count */ 533 bus_space_write_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT, blocks); 534 } 535 536 static int 537 asc_intr(void *arg) 538 { 539 register u_int32_t dma_stat; 540 struct asc_softc *esc = arg; 541 struct ncr53c9x_softc *sc = arg; 542 543 esc->sc_intrcnt.ev_count++; 544 545 /* Check for RAMBO DMA Interrupt */ 546 dma_stat = bus_space_read_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE); 547 if (dma_stat & RB_INTR_PEND) { 548 rambo_dma_chain(esc); 549 } 550 /* Check for NCR 53c94 interrupt */ 551 if (NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT) { 552 ncr53c9x_intr(sc); 553 } 554 return 0; 555 } 556