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