1 /* $NetBSD: esp_sbus.c,v 1.12 2000/12/03 23:31:13 eeh Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace 9 * Simulation Facility, NASA Ames Research Center; Paul Kranenburg. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/types.h> 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/errno.h> 45 #include <sys/device.h> 46 #include <sys/buf.h> 47 48 #include <dev/scsipi/scsi_all.h> 49 #include <dev/scsipi/scsipi_all.h> 50 #include <dev/scsipi/scsiconf.h> 51 #include <dev/scsipi/scsi_message.h> 52 53 #include <machine/bus.h> 54 #include <machine/intr.h> 55 #include <machine/autoconf.h> 56 57 #include <dev/ic/lsi64854reg.h> 58 #include <dev/ic/lsi64854var.h> 59 60 #include <dev/ic/ncr53c9xreg.h> 61 #include <dev/ic/ncr53c9xvar.h> 62 63 #include <dev/sbus/sbusvar.h> 64 65 struct esp_softc { 66 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ 67 struct sbusdev sc_sd; /* sbus device */ 68 69 bus_space_tag_t sc_bustag; 70 bus_dma_tag_t sc_dmatag; 71 72 bus_space_handle_t sc_reg; /* the registers */ 73 struct lsi64854_softc *sc_dma; /* pointer to my dma */ 74 75 int sc_pri; /* SBUS priority */ 76 }; 77 78 void espattach_sbus __P((struct device *, struct device *, void *)); 79 void espattach_dma __P((struct device *, struct device *, void *)); 80 int espmatch_sbus __P((struct device *, struct cfdata *, void *)); 81 82 83 /* Linkup to the rest of the kernel */ 84 struct cfattach esp_sbus_ca = { 85 sizeof(struct esp_softc), espmatch_sbus, espattach_sbus 86 }; 87 struct cfattach esp_dma_ca = { 88 sizeof(struct esp_softc), espmatch_sbus, espattach_dma 89 }; 90 91 /* 92 * Functions and the switch for the MI code. 93 */ 94 static u_char esp_read_reg __P((struct ncr53c9x_softc *, int)); 95 static void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char)); 96 static u_char esp_rdreg1 __P((struct ncr53c9x_softc *, int)); 97 static void esp_wrreg1 __P((struct ncr53c9x_softc *, int, u_char)); 98 static int esp_dma_isintr __P((struct ncr53c9x_softc *)); 99 static void esp_dma_reset __P((struct ncr53c9x_softc *)); 100 static int esp_dma_intr __P((struct ncr53c9x_softc *)); 101 static int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *, 102 size_t *, int, size_t *)); 103 static void esp_dma_go __P((struct ncr53c9x_softc *)); 104 static void esp_dma_stop __P((struct ncr53c9x_softc *)); 105 static int esp_dma_isactive __P((struct ncr53c9x_softc *)); 106 107 static struct ncr53c9x_glue esp_sbus_glue = { 108 esp_read_reg, 109 esp_write_reg, 110 esp_dma_isintr, 111 esp_dma_reset, 112 esp_dma_intr, 113 esp_dma_setup, 114 esp_dma_go, 115 esp_dma_stop, 116 esp_dma_isactive, 117 NULL, /* gl_clear_latched_intr */ 118 }; 119 120 static struct ncr53c9x_glue esp_sbus_glue1 = { 121 esp_rdreg1, 122 esp_wrreg1, 123 esp_dma_isintr, 124 esp_dma_reset, 125 esp_dma_intr, 126 esp_dma_setup, 127 esp_dma_go, 128 esp_dma_stop, 129 esp_dma_isactive, 130 NULL, /* gl_clear_latched_intr */ 131 }; 132 133 static void espattach __P((struct esp_softc *, struct ncr53c9x_glue *)); 134 135 int 136 espmatch_sbus(parent, cf, aux) 137 struct device *parent; 138 struct cfdata *cf; 139 void *aux; 140 { 141 int rv; 142 struct sbus_attach_args *sa = aux; 143 144 rv = (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0 || 145 strcmp("ptscII", sa->sa_name) == 0); 146 return (rv); 147 } 148 149 void 150 espattach_sbus(parent, self, aux) 151 struct device *parent, *self; 152 void *aux; 153 { 154 struct esp_softc *esc = (void *)self; 155 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 156 struct sbus_attach_args *sa = aux; 157 158 esc->sc_bustag = sa->sa_bustag; 159 esc->sc_dmatag = sa->sa_dmatag; 160 161 sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7); 162 sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1); 163 if (sc->sc_freq < 0) 164 sc->sc_freq = ((struct sbus_softc *) 165 sc->sc_dev.dv_parent)->sc_clockfreq; 166 167 /* 168 * Find the DMA by poking around the dma device structures 169 * 170 * What happens here is that if the dma driver has not been 171 * configured, then this returns a NULL pointer. Then when the 172 * dma actually gets configured, it does the opposing test, and 173 * if the sc->sc_esp field in it's softc is NULL, then tries to 174 * find the matching esp driver. 175 */ 176 esc->sc_dma = (struct lsi64854_softc *) 177 getdevunit("dma", sc->sc_dev.dv_unit); 178 179 /* 180 * and a back pointer to us, for DMA 181 */ 182 if (esc->sc_dma) 183 esc->sc_dma->sc_client = sc; 184 else { 185 printf("\n"); 186 panic("espattach: no dma found"); 187 } 188 189 /* 190 * Map my registers in, if they aren't already in virtual 191 * address space. 192 */ 193 if (sa->sa_npromvaddrs) 194 esc->sc_reg = (bus_space_handle_t)sa->sa_promvaddrs[0]; 195 else { 196 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, 197 sa->sa_offset, 198 sa->sa_size, 199 BUS_SPACE_MAP_LINEAR, 200 0, &esc->sc_reg) != 0) { 201 printf("%s @ sbus: cannot map registers\n", 202 self->dv_xname); 203 return; 204 } 205 } 206 207 if (sa->sa_nintr == 0) { 208 /* 209 * No interrupt properties: we quit; this might 210 * happen on e.g. a Sparc X terminal. 211 */ 212 printf("\n%s: no interrupt property\n", self->dv_xname); 213 return; 214 } 215 216 esc->sc_pri = sa->sa_pri; 217 218 /* add me to the sbus structures */ 219 esc->sc_sd.sd_reset = (void *) ncr53c9x_reset; 220 sbus_establish(&esc->sc_sd, &sc->sc_dev); 221 222 if (strcmp("ptscII", sa->sa_name) == 0) { 223 espattach(esc, &esp_sbus_glue1); 224 } else { 225 espattach(esc, &esp_sbus_glue); 226 } 227 } 228 229 void 230 espattach_dma(parent, self, aux) 231 struct device *parent, *self; 232 void *aux; 233 { 234 struct esp_softc *esc = (void *)self; 235 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 236 struct sbus_attach_args *sa = aux; 237 238 if (strcmp("ptscII", sa->sa_name) == 0) { 239 return; 240 } 241 242 esc->sc_bustag = sa->sa_bustag; 243 esc->sc_dmatag = sa->sa_dmatag; 244 245 sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7); 246 sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1); 247 248 esc->sc_dma = (struct lsi64854_softc *)parent; 249 esc->sc_dma->sc_client = sc; 250 251 /* 252 * Map my registers in, if they aren't already in virtual 253 * address space. 254 */ 255 if (sa->sa_npromvaddrs) 256 esc->sc_reg = (bus_space_handle_t)sa->sa_promvaddrs[0]; 257 else { 258 if (bus_space_map2(sa->sa_bustag, 259 sa->sa_slot, 260 sa->sa_offset, 261 sa->sa_size, 262 BUS_SPACE_MAP_LINEAR, 263 0, &esc->sc_reg) != 0) { 264 printf("%s @ dma: cannot map registers\n", 265 self->dv_xname); 266 return; 267 } 268 } 269 270 if (sa->sa_nintr == 0) { 271 /* 272 * No interrupt properties: we quit; this might 273 * happen on e.g. a Sparc X terminal. 274 */ 275 printf("\n%s: no interrupt property\n", self->dv_xname); 276 return; 277 } 278 279 esc->sc_pri = sa->sa_pri; 280 281 /* Assume SBus is grandparent */ 282 esc->sc_sd.sd_reset = (void *) ncr53c9x_reset; 283 sbus_establish(&esc->sc_sd, parent); 284 285 espattach(esc, &esp_sbus_glue); 286 } 287 288 289 /* 290 * Attach this instance, and then all the sub-devices 291 */ 292 void 293 espattach(esc, gluep) 294 struct esp_softc *esc; 295 struct ncr53c9x_glue *gluep; 296 { 297 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 298 void *icookie; 299 300 /* 301 * Set up glue for MI code early; we use some of it here. 302 */ 303 sc->sc_glue = gluep; 304 305 /* gimme Mhz */ 306 sc->sc_freq /= 1000000; 307 308 /* 309 * XXX More of this should be in ncr53c9x_attach(), but 310 * XXX should we really poke around the chip that much in 311 * XXX the MI code? Think about this more... 312 */ 313 314 /* 315 * It is necessary to try to load the 2nd config register here, 316 * to find out what rev the esp chip is, else the ncr53c9x_reset 317 * will not set up the defaults correctly. 318 */ 319 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 320 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE; 321 sc->sc_cfg3 = NCRCFG3_CDB | NCRCFG3_QTE; 322 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 323 324 if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) != 325 (NCRCFG2_SCSI2 | NCRCFG2_RPE)) { 326 sc->sc_rev = NCR_VARIANT_ESP100; 327 } else { 328 sc->sc_cfg2 = NCRCFG2_SCSI2; 329 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 330 sc->sc_cfg3 = 0; 331 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 332 sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK | NCRCFG3_QTE); 333 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 334 if (NCR_READ_REG(sc, NCR_CFG3) != 335 (NCRCFG3_CDB | NCRCFG3_FCLK)) { 336 sc->sc_rev = NCR_VARIANT_ESP100A; 337 } else { 338 /* NCRCFG2_FE enables > 64K transfers */ 339 sc->sc_cfg2 |= NCRCFG2_FE; 340 sc->sc_cfg3 = 0 | NCRF9XCFG3_QTE; 341 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 342 sc->sc_rev = NCR_VARIANT_ESP200; 343 } 344 } 345 346 /* 347 * XXX minsync and maxxfer _should_ be set up in MI code, 348 * XXX but it appears to have some dependency on what sort 349 * XXX of DMA we're hooked up to, etc. 350 */ 351 352 /* 353 * This is the value used to start sync negotiations 354 * Note that the NCR register "SYNCTP" is programmed 355 * in "clocks per byte", and has a minimum value of 4. 356 * The SCSI period used in negotiation is one-fourth 357 * of the time (in nanoseconds) needed to transfer one byte. 358 * Since the chip's clock is given in MHz, we have the following 359 * formula: 4 * period = (1000 / freq) * 4 360 */ 361 sc->sc_minsync = 1000 / sc->sc_freq; 362 363 /* 364 * Alas, we must now modify the value a bit, because it's 365 * only valid when can switch on FASTCLK and FASTSCSI bits 366 * in config register 3... 367 */ 368 switch (sc->sc_rev) { 369 case NCR_VARIANT_ESP100: 370 sc->sc_maxxfer = 64 * 1024; 371 sc->sc_minsync = 0; /* No synch on old chip? */ 372 break; 373 374 case NCR_VARIANT_ESP100A: 375 sc->sc_maxxfer = 64 * 1024; 376 /* Min clocks/byte is 5 */ 377 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5); 378 break; 379 380 case NCR_VARIANT_ESP200: 381 sc->sc_maxxfer = 16 * 1024 * 1024; 382 /* XXX - do actually set FAST* bits */ 383 break; 384 } 385 386 /* Establish interrupt channel */ 387 icookie = bus_intr_establish(esc->sc_bustag, esc->sc_pri, IPL_BIO, 0, 388 ncr53c9x_intr, sc); 389 390 /* register interrupt stats */ 391 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 392 sc->sc_dev.dv_xname, "intr"); 393 394 /* Do the common parts of attachment. */ 395 ncr53c9x_attach(sc, NULL, NULL); 396 397 /* Turn on target selection using the `dma' method */ 398 ncr53c9x_dmaselect = 1; 399 } 400 401 /* 402 * Glue functions. 403 */ 404 405 u_char 406 esp_read_reg(sc, reg) 407 struct ncr53c9x_softc *sc; 408 int reg; 409 { 410 struct esp_softc *esc = (struct esp_softc *)sc; 411 412 return (bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg * 4)); 413 } 414 415 void 416 esp_write_reg(sc, reg, v) 417 struct ncr53c9x_softc *sc; 418 int reg; 419 u_char v; 420 { 421 struct esp_softc *esc = (struct esp_softc *)sc; 422 423 bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg * 4, v); 424 } 425 426 u_char 427 esp_rdreg1(sc, reg) 428 struct ncr53c9x_softc *sc; 429 int reg; 430 { 431 struct esp_softc *esc = (struct esp_softc *)sc; 432 433 return (bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg)); 434 } 435 436 void 437 esp_wrreg1(sc, reg, v) 438 struct ncr53c9x_softc *sc; 439 int reg; 440 u_char v; 441 { 442 struct esp_softc *esc = (struct esp_softc *)sc; 443 444 bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg, v); 445 } 446 447 int 448 esp_dma_isintr(sc) 449 struct ncr53c9x_softc *sc; 450 { 451 struct esp_softc *esc = (struct esp_softc *)sc; 452 453 return (DMA_ISINTR(esc->sc_dma)); 454 } 455 456 void 457 esp_dma_reset(sc) 458 struct ncr53c9x_softc *sc; 459 { 460 struct esp_softc *esc = (struct esp_softc *)sc; 461 462 DMA_RESET(esc->sc_dma); 463 } 464 465 int 466 esp_dma_intr(sc) 467 struct ncr53c9x_softc *sc; 468 { 469 struct esp_softc *esc = (struct esp_softc *)sc; 470 471 return (DMA_INTR(esc->sc_dma)); 472 } 473 474 int 475 esp_dma_setup(sc, addr, len, datain, dmasize) 476 struct ncr53c9x_softc *sc; 477 caddr_t *addr; 478 size_t *len; 479 int datain; 480 size_t *dmasize; 481 { 482 struct esp_softc *esc = (struct esp_softc *)sc; 483 484 return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize)); 485 } 486 487 void 488 esp_dma_go(sc) 489 struct ncr53c9x_softc *sc; 490 { 491 struct esp_softc *esc = (struct esp_softc *)sc; 492 493 DMA_GO(esc->sc_dma); 494 } 495 496 void 497 esp_dma_stop(sc) 498 struct ncr53c9x_softc *sc; 499 { 500 struct esp_softc *esc = (struct esp_softc *)sc; 501 u_int32_t csr; 502 503 csr = L64854_GCSR(esc->sc_dma); 504 csr &= ~D_EN_DMA; 505 L64854_SCSR(esc->sc_dma, csr); 506 } 507 508 int 509 esp_dma_isactive(sc) 510 struct ncr53c9x_softc *sc; 511 { 512 struct esp_softc *esc = (struct esp_softc *)sc; 513 514 return (DMA_ISACTIVE(esc->sc_dma)); 515 } 516 517 #include "opt_ddb.h" 518 #ifdef DDB 519 #include <machine/db_machdep.h> 520 #include <ddb/db_output.h> 521 522 void db_esp __P((db_expr_t, int, db_expr_t, char*)); 523 524 void 525 db_esp(addr, have_addr, count, modif) 526 db_expr_t addr; 527 int have_addr; 528 db_expr_t count; 529 char *modif; 530 { 531 struct ncr53c9x_softc *sc; 532 struct ncr53c9x_ecb *ecb; 533 struct ncr53c9x_linfo *li; 534 int u, t, i; 535 536 for (u=0; u<10; u++) { 537 sc = (struct ncr53c9x_softc *) 538 getdevunit("esp", u); 539 if (!sc) continue; 540 541 db_printf("esp%d: nexus %p phase %x prev %x dp %p dleft %lx ify %x\n", 542 u, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase, 543 sc->sc_dp, sc->sc_dleft, sc->sc_msgify); 544 db_printf("\tmsgout %x msgpriq %x msgin %x:%x:%x:%x:%x\n", 545 sc->sc_msgout, sc->sc_msgpriq, sc->sc_imess[0], 546 sc->sc_imess[1], sc->sc_imess[2], sc->sc_imess[3], 547 sc->sc_imess[0]); 548 db_printf("ready: "); 549 for (ecb = sc->ready_list.tqh_first; ecb; ecb = ecb->chain.tqe_next) { 550 db_printf("ecb %p ", ecb); 551 if (ecb == ecb->chain.tqe_next) { 552 db_printf("\nWARNING: tailq loop on ecb %p", ecb); 553 break; 554 } 555 } 556 db_printf("\n"); 557 558 for (t=0; t<NCR_NTARG; t++) { 559 LIST_FOREACH(li, &sc->sc_tinfo[t].luns, link) { 560 db_printf("t%d lun %d untagged %p busy %d used %x\n", 561 t, (int)li->lun, li->untagged, li->busy, 562 li->used); 563 for (i=0; i<256; i++) 564 if ((ecb = li->queued[i])) { 565 db_printf("ecb %p tag %x\n", ecb, i); 566 } 567 } 568 } 569 } 570 } 571 #endif 572