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