esp_sbus.c revision 207885
1/*- 2 * Copyright (c) 2004 Scott Long 3 * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29/* $NetBSD: esp_sbus.c,v 1.31 2005/02/27 00:27:48 perry Exp $ */ 30 31/*- 32 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 33 * All rights reserved. 34 * 35 * This code is derived from software contributed to The NetBSD Foundation 36 * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace 37 * Simulation Facility, NASA Ames Research Center; Paul Kranenburg. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgement: 49 * This product includes software developed by the NetBSD 50 * Foundation, Inc. and its contributors. 51 * 4. Neither the name of The NetBSD Foundation nor the names of its 52 * contributors may be used to endorse or promote products derived 53 * from this software without specific prior written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 56 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 57 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 58 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 59 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 60 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 61 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 65 * POSSIBILITY OF SUCH DAMAGE. 66 */ 67 68#include <sys/cdefs.h> 69__FBSDID("$FreeBSD: head/sys/dev/esp/esp_sbus.c 207885 2010-05-10 20:02:39Z marius $"); 70 71#include <sys/param.h> 72#include <sys/systm.h> 73#include <sys/bus.h> 74#include <sys/kernel.h> 75#include <sys/lock.h> 76#include <sys/module.h> 77#include <sys/mutex.h> 78 79#include <dev/ofw/ofw_bus.h> 80#include <dev/ofw/openfirm.h> 81#include <machine/bus.h> 82#include <machine/ofw_machdep.h> 83#include <machine/resource.h> 84#include <sys/rman.h> 85 86#include <cam/cam.h> 87#include <cam/cam_ccb.h> 88#include <cam/scsi/scsi_all.h> 89#include <cam/scsi/scsi_message.h> 90 91#include <sparc64/sbus/lsi64854reg.h> 92#include <sparc64/sbus/lsi64854var.h> 93#include <sparc64/sbus/sbusvar.h> 94 95#include <dev/esp/ncr53c9xreg.h> 96#include <dev/esp/ncr53c9xvar.h> 97 98/* #define ESP_SBUS_DEBUG */ 99 100struct esp_softc { 101 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ 102 struct device *sc_dev; 103 104 struct resource *sc_res; 105 106 struct resource *sc_irqres; 107 void *sc_irq; 108 109 struct lsi64854_softc *sc_dma; /* pointer to my DMA */ 110}; 111 112static devclass_t esp_devclass; 113 114static int esp_probe(device_t); 115static int esp_dma_attach(device_t); 116static int esp_dma_detach(device_t); 117static int esp_sbus_attach(device_t); 118static int esp_sbus_detach(device_t); 119static int esp_suspend(device_t); 120static int esp_resume(device_t); 121 122static device_method_t esp_dma_methods[] = { 123 DEVMETHOD(device_probe, esp_probe), 124 DEVMETHOD(device_attach, esp_dma_attach), 125 DEVMETHOD(device_detach, esp_dma_detach), 126 DEVMETHOD(device_suspend, esp_suspend), 127 DEVMETHOD(device_resume, esp_resume), 128 {0, 0} 129}; 130 131static driver_t esp_dma_driver = { 132 "esp", 133 esp_dma_methods, 134 sizeof(struct esp_softc) 135}; 136 137DRIVER_MODULE(esp, dma, esp_dma_driver, esp_devclass, 0, 0); 138MODULE_DEPEND(esp, dma, 1, 1, 1); 139 140static device_method_t esp_sbus_methods[] = { 141 DEVMETHOD(device_probe, esp_probe), 142 DEVMETHOD(device_attach, esp_sbus_attach), 143 DEVMETHOD(device_detach, esp_sbus_detach), 144 DEVMETHOD(device_suspend, esp_suspend), 145 DEVMETHOD(device_resume, esp_resume), 146 {0, 0} 147}; 148 149static driver_t esp_sbus_driver = { 150 "esp", 151 esp_sbus_methods, 152 sizeof(struct esp_softc) 153}; 154 155DRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0); 156MODULE_DEPEND(esp, sbus, 1, 1, 1); 157 158/* 159 * Functions and the switch for the MI code 160 */ 161static u_char esp_read_reg(struct ncr53c9x_softc *sc, int reg); 162static void esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v); 163static int esp_dma_isintr(struct ncr53c9x_softc *sc); 164static void esp_dma_reset(struct ncr53c9x_softc *sc); 165static int esp_dma_intr(struct ncr53c9x_softc *sc); 166static int esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, 167 size_t *len, int datain, size_t *dmasize); 168static void esp_dma_go(struct ncr53c9x_softc *sc); 169static void esp_dma_stop(struct ncr53c9x_softc *sc); 170static int esp_dma_isactive(struct ncr53c9x_softc *sc); 171static int espattach(struct esp_softc *esc, 172 const struct ncr53c9x_glue *gluep); 173static int espdetach(struct esp_softc *esc); 174 175static const struct ncr53c9x_glue esp_sbus_glue = { 176 esp_read_reg, 177 esp_write_reg, 178 esp_dma_isintr, 179 esp_dma_reset, 180 esp_dma_intr, 181 esp_dma_setup, 182 esp_dma_go, 183 esp_dma_stop, 184 esp_dma_isactive, 185 NULL, /* gl_clear_latched_intr */ 186}; 187 188static int 189esp_probe(device_t dev) 190{ 191 const char *name; 192 193 name = ofw_bus_get_name(dev); 194 if (strcmp("SUNW,fas", name) == 0) { 195 device_set_desc(dev, "Sun FAS366 Fast-Wide SCSI"); 196 return (BUS_PROBE_DEFAULT); 197 } else if (strcmp("esp", name) == 0) { 198 device_set_desc(dev, "Sun ESP SCSI/Sun FAS Fast-SCSI"); 199 return (BUS_PROBE_DEFAULT); 200 } 201 202 return (ENXIO); 203} 204 205static int 206esp_sbus_attach(device_t dev) 207{ 208 struct esp_softc *esc; 209 struct ncr53c9x_softc *sc; 210 struct lsi64854_softc *lsc; 211 device_t *children; 212 int error, i, nchildren; 213 214 esc = device_get_softc(dev); 215 sc = &esc->sc_ncr53c9x; 216 217 lsc = NULL; 218 esc->sc_dev = dev; 219 sc->sc_freq = sbus_get_clockfreq(dev); 220 221 if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") == 0) { 222 /* 223 * Allocate space for DMA, in SUNW,fas there are no 224 * separate DMA devices. 225 */ 226 lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF, 227 M_NOWAIT | M_ZERO); 228 if (lsc == NULL) { 229 device_printf(dev, "out of memory (lsi64854_softc)\n"); 230 return (ENOMEM); 231 } 232 esc->sc_dma = lsc; 233 234 /* 235 * SUNW,fas have 2 register spaces: DMA (lsi64854) and 236 * SCSI core (ncr53c9x). 237 */ 238 239 /* Allocate DMA registers. */ 240 i = 0; 241 if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 242 &i, RF_ACTIVE)) == NULL) { 243 device_printf(dev, "cannot allocate DMA registers\n"); 244 error = ENXIO; 245 goto fail_sbus_lsc; 246 } 247 248 /* Create a parent DMA tag based on this bus. */ 249 error = bus_dma_tag_create( 250 bus_get_dma_tag(dev), /* parent */ 251 1, 0, /* alignment, boundary */ 252 BUS_SPACE_MAXADDR, /* lowaddr */ 253 BUS_SPACE_MAXADDR, /* highaddr */ 254 NULL, NULL, /* filter, filterarg */ 255 BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 256 0, /* nsegments */ 257 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 258 0, /* flags */ 259 NULL, NULL, /* no locking */ 260 &lsc->sc_parent_dmat); 261 if (error != 0) { 262 device_printf(dev, "cannot allocate parent DMA tag\n"); 263 goto fail_sbus_lres; 264 } 265 266 i = sbus_get_burstsz(dev); 267 268#ifdef ESP_SBUS_DEBUG 269 printf("%s: burst 0x%x\n", __func__, i); 270#endif 271 272 lsc->sc_burst = (i & SBUS_BURST_32) ? 32 : 273 (i & SBUS_BURST_16) ? 16 : 0; 274 275 lsc->sc_channel = L64854_CHANNEL_SCSI; 276 lsc->sc_client = sc; 277 lsc->sc_dev = dev; 278 279 /* 280 * Allocate SCSI core registers. 281 */ 282 i = 1; 283 if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 284 &i, RF_ACTIVE)) == NULL) { 285 device_printf(dev, 286 "cannot allocate SCSI core registers\n"); 287 error = ENXIO; 288 goto fail_sbus_lpdma; 289 } 290 } else { 291 /* 292 * Search accompanying DMA engine. It should have been 293 * already attached otherwise there isn't much we can do. 294 */ 295 if (device_get_children(device_get_parent(dev), &children, 296 &nchildren) != 0) { 297 device_printf(dev, "cannot determine siblings\n"); 298 return (ENXIO); 299 } 300 for (i = 0; i < nchildren; i++) { 301 if (device_is_attached(children[i]) && 302 sbus_get_slot(children[i]) == sbus_get_slot(dev) && 303 strcmp(ofw_bus_get_name(children[i]), "dma") == 0) { 304 /* XXX hackery */ 305 esc->sc_dma = (struct lsi64854_softc *) 306 device_get_softc(children[i]); 307 break; 308 } 309 } 310 free(children, M_TEMP); 311 if (esc->sc_dma == NULL) { 312 device_printf(dev, "cannot find DMA engine\n"); 313 return (ENXIO); 314 } 315 esc->sc_dma->sc_client = sc; 316 317 /* 318 * Allocate SCSI core registers. 319 */ 320 i = 0; 321 if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 322 &i, RF_ACTIVE)) == NULL) { 323 device_printf(dev, 324 "cannot allocate SCSI core registers\n"); 325 return (ENXIO); 326 } 327 } 328 329 error = espattach(esc, &esp_sbus_glue); 330 if (error != 0) { 331 device_printf(dev, "espattach failed\n"); 332 goto fail_sbus_eres; 333 } 334 335 return (0); 336 337 fail_sbus_eres: 338 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 339 esc->sc_res); 340 if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0) 341 return (error); 342 fail_sbus_lpdma: 343 bus_dma_tag_destroy(lsc->sc_parent_dmat); 344 fail_sbus_lres: 345 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res), 346 lsc->sc_res); 347 fail_sbus_lsc: 348 free(lsc, M_DEVBUF); 349 return (error); 350} 351 352static int 353esp_sbus_detach(device_t dev) 354{ 355 struct esp_softc *esc; 356 struct lsi64854_softc *lsc; 357 int error; 358 359 esc = device_get_softc(dev); 360 lsc = esc->sc_dma; 361 362 error = espdetach(esc); 363 if (error != 0) 364 return (error); 365 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 366 esc->sc_res); 367 if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0) 368 return (0); 369 bus_dma_tag_destroy(lsc->sc_parent_dmat); 370 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res), 371 lsc->sc_res); 372 free(lsc, M_DEVBUF); 373 374 return (0); 375} 376 377static int 378esp_dma_attach(device_t dev) 379{ 380 struct esp_softc *esc; 381 struct ncr53c9x_softc *sc; 382 int error, i; 383 384 esc = device_get_softc(dev); 385 sc = &esc->sc_ncr53c9x; 386 387 esc->sc_dev = dev; 388 if (OF_getprop(ofw_bus_get_node(dev), "clock-frequency", 389 &sc->sc_freq, sizeof(sc->sc_freq)) == -1) { 390 printf("failed to query OFW for clock-frequency\n"); 391 return (ENXIO); 392 } 393 394 /* XXX hackery */ 395 esc->sc_dma = (struct lsi64854_softc *) 396 device_get_softc(device_get_parent(dev)); 397 esc->sc_dma->sc_client = sc; 398 399 /* 400 * Allocate SCSI core registers. 401 */ 402 i = 0; 403 if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 404 &i, RF_ACTIVE)) == NULL) { 405 device_printf(dev, "cannot allocate SCSI core registers\n"); 406 return (ENXIO); 407 } 408 409 error = espattach(esc, &esp_sbus_glue); 410 if (error != 0) { 411 device_printf(dev, "espattach failed\n"); 412 goto fail_dma_eres; 413 } 414 415 return (0); 416 417 fail_dma_eres: 418 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 419 esc->sc_res); 420 return (error); 421} 422 423static int 424esp_dma_detach(device_t dev) 425{ 426 struct esp_softc *esc; 427 int error; 428 429 esc = device_get_softc(dev); 430 431 error = espdetach(esc); 432 if (error != 0) 433 return (error); 434 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 435 esc->sc_res); 436 437 return (0); 438} 439 440static int 441esp_suspend(device_t dev) 442{ 443 444 return (ENXIO); 445} 446 447static int 448esp_resume(device_t dev) 449{ 450 451 return (ENXIO); 452} 453 454static int 455espattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep) 456{ 457 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 458 unsigned int uid = 0; 459 int error, i; 460 461 NCR_LOCK_INIT(sc); 462 463 /* Attach the DMA engine. */ 464 error = lsi64854_attach(esc->sc_dma); 465 if (error != 0) { 466 device_printf(esc->sc_dev, "lsi64854_attach failed\n"); 467 goto fail_lock; 468 } 469 470 sc->sc_id = OF_getscsinitid(esc->sc_dev); 471 472#ifdef ESP_SBUS_DEBUG 473 device_printf(esc->sc_dev, "%s: sc_id %d, freq %d\n", 474 __func__, sc->sc_id, sc->sc_freq); 475#endif 476 477 /* 478 * The `ESC' DMA chip must be reset before we can access 479 * the ESP registers. 480 */ 481 if (esc->sc_dma->sc_rev == DMAREV_ESC) 482 DMA_RESET(esc->sc_dma); 483 484 /* 485 * Set up glue for MI code early; we use some of it here. 486 */ 487 sc->sc_glue = gluep; 488 489 /* gimme MHz */ 490 sc->sc_freq /= 1000000; 491 492 /* 493 * XXX More of this should be in ncr53c9x_attach(), but 494 * XXX should we really poke around the chip that much in 495 * XXX the MI code? Think about this more... 496 */ 497 498 /* 499 * Read the part-unique ID code of the SCSI chip. The contained 500 * value is only valid if all of the following conditions are met: 501 * - After power-up or chip reset. 502 * - Before any value is written to this register. 503 * - The NCRCFG2_FE bit is set. 504 * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued. 505 */ 506 NCRCMD(sc, NCRCMD_RSTCHIP); 507 NCRCMD(sc, NCRCMD_NOP); 508 sc->sc_cfg2 = NCRCFG2_FE; 509 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 510 NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA); 511 uid = NCR_READ_REG(sc, NCR_UID); 512 513 /* 514 * It is necessary to try to load the 2nd config register here, 515 * to find out what rev the esp chip is, else the ncr53c9x_reset 516 * will not set up the defaults correctly. 517 */ 518 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 519 NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1); 520 sc->sc_cfg2 = 0; 521 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 522 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE; 523 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 524 525 if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) != 526 (NCRCFG2_SCSI2 | NCRCFG2_RPE)) { 527 sc->sc_rev = NCR_VARIANT_ESP100; 528 } else { 529 sc->sc_cfg2 = NCRCFG2_SCSI2; 530 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 531 sc->sc_cfg3 = 0; 532 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 533 sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK); 534 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 535 if (NCR_READ_REG(sc, NCR_CFG3) != 536 (NCRCFG3_CDB | NCRCFG3_FCLK)) { 537 sc->sc_rev = NCR_VARIANT_ESP100A; 538 } else { 539 /* NCRCFG2_FE enables > 64K transfers. */ 540 sc->sc_cfg2 |= NCRCFG2_FE; 541 sc->sc_cfg3 = 0; 542 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 543 if (sc->sc_freq <= 25) 544 sc->sc_rev = NCR_VARIANT_ESP200; 545 else { 546 switch ((uid & 0xf8) >> 3) { 547 case 0x00: 548 sc->sc_rev = NCR_VARIANT_FAS100A; 549 break; 550 551 case 0x02: 552 if ((uid & 0x07) == 0x02) 553 sc->sc_rev = NCR_VARIANT_FAS216; 554 else 555 sc->sc_rev = NCR_VARIANT_FAS236; 556 break; 557 558 case 0x0a: 559 sc->sc_rev = NCR_VARIANT_FAS366; 560 break; 561 562 default: 563 /* 564 * We could just treat unknown chips 565 * as ESP200 but then we would most 566 * likely drive them out of specs. 567 */ 568 device_printf(esc->sc_dev, 569 "Unknown chip\n"); 570 goto fail_lsi; 571 } 572 } 573 } 574 } 575 576#ifdef ESP_SBUS_DEBUG 577 printf("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid); 578#endif 579 580 /* 581 * XXX minsync and maxxfer _should_ be set up in MI code, 582 * XXX but it appears to have some dependency on what sort 583 * XXX of DMA we're hooked up to, etc. 584 */ 585 586 /* 587 * This is the value used to start sync negotiations 588 * Note that the NCR register "SYNCTP" is programmed 589 * in "clocks per byte", and has a minimum value of 4. 590 * The SCSI period used in negotiation is one-fourth 591 * of the time (in nanoseconds) needed to transfer one byte. 592 * Since the chip's clock is given in MHz, we have the following 593 * formula: 4 * period = (1000 / freq) * 4 594 */ 595 sc->sc_minsync = 1000 / sc->sc_freq; 596 597 sc->sc_maxoffset = 15; 598 sc->sc_extended_geom = 1; 599 600 /* 601 * Alas, we must now modify the value a bit, because it's 602 * only valid when can switch on FASTCLK and FASTSCSI bits 603 * in config register 3... 604 */ 605 switch (sc->sc_rev) { 606 case NCR_VARIANT_ESP100: 607 sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 608 sc->sc_maxxfer = 64 * 1024; 609 sc->sc_minsync = 0; /* No synch on old chip? */ 610 break; 611 612 case NCR_VARIANT_ESP100A: 613 sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 614 sc->sc_maxxfer = 64 * 1024; 615 /* Min clocks/byte is 5 */ 616 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5); 617 break; 618 619 case NCR_VARIANT_ESP200: 620 sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 621 sc->sc_maxxfer = 16 * 1024 * 1024; 622 /* Min clocks/byte is 5 */ 623 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5); 624 break; 625 626 case NCR_VARIANT_FAS100A: 627 case NCR_VARIANT_FAS216: 628 case NCR_VARIANT_FAS236: 629 /* 630 * The onboard SCSI chips in Sun Ultra 1 are actually 631 * documented to be NCR53C9X which use NCRCFG3_FCLK and 632 * NCRCFG3_FSCSI. BSD/OS however probes these chips as 633 * FAS100A and uses NCRF9XCFG3_FCLK and NCRF9XCFG3_FSCSI 634 * instead which seems to be correct as otherwise sync 635 * negotiation just doesn't work. Using NCRF9XCFG3_FCLK 636 * and NCRF9XCFG3_FSCSI with these chips in fact also 637 * yields Fast-SCSI speed. 638 */ 639 sc->sc_features = NCR_F_FASTSCSI; 640 sc->sc_cfg3 = NCRF9XCFG3_FCLK; 641 sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI; 642 sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 643 sc->sc_maxxfer = 16 * 1024 * 1024; 644 break; 645 646 case NCR_VARIANT_FAS366: 647 sc->sc_maxwidth = MSG_EXT_WDTR_BUS_16_BIT; 648 sc->sc_maxxfer = 16 * 1024 * 1024; 649 break; 650 } 651 652 /* Establish interrupt channel. */ 653 i = 0; 654 if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ, 655 &i, RF_SHAREABLE|RF_ACTIVE)) == NULL) { 656 device_printf(esc->sc_dev, "cannot allocate interrupt\n"); 657 goto fail_lsi; 658 } 659 if (bus_setup_intr(esc->sc_dev, esc->sc_irqres, 660 INTR_MPSAFE | INTR_TYPE_CAM, NULL, ncr53c9x_intr, sc, 661 &esc->sc_irq)) { 662 device_printf(esc->sc_dev, "cannot set up interrupt\n"); 663 error = ENXIO; 664 goto fail_ires; 665 } 666 667 /* Turn on target selection using the `DMA' method. */ 668 if (sc->sc_rev != NCR_VARIANT_FAS366) 669 sc->sc_features |= NCR_F_DMASELECT; 670 671 /* Do the common parts of attachment. */ 672 sc->sc_dev = esc->sc_dev; 673 error = ncr53c9x_attach(sc); 674 if (error != 0) { 675 device_printf(esc->sc_dev, "ncr53c9x_attach failed\n"); 676 goto fail_intr; 677 } 678 679 return (0); 680 681 fail_intr: 682 bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq); 683 fail_ires: 684 bus_release_resource(esc->sc_dev, SYS_RES_IRQ, 685 rman_get_rid(esc->sc_irqres), esc->sc_irqres); 686 fail_lsi: 687 lsi64854_detach(esc->sc_dma); 688 fail_lock: 689 NCR_LOCK_DESTROY(sc); 690 return (error); 691} 692 693static int 694espdetach(struct esp_softc *esc) 695{ 696 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 697 int error; 698 699 bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq); 700 error = ncr53c9x_detach(sc); 701 if (error != 0) 702 return (error); 703 error = lsi64854_detach(esc->sc_dma); 704 if (error != 0) 705 return (error); 706 NCR_LOCK_DESTROY(sc); 707 bus_release_resource(esc->sc_dev, SYS_RES_IRQ, 708 rman_get_rid(esc->sc_irqres), esc->sc_irqres); 709 710 return (0); 711} 712 713/* 714 * Glue functions 715 */ 716 717#ifdef ESP_SBUS_DEBUG 718static int esp_sbus_debug = 0; 719 720static const struct { 721 char *r_name; 722 int r_flag; 723} esp__read_regnames [] = { 724 { "TCL", 0}, /* 0/00 */ 725 { "TCM", 0}, /* 1/04 */ 726 { "FIFO", 0}, /* 2/08 */ 727 { "CMD", 0}, /* 3/0c */ 728 { "STAT", 0}, /* 4/10 */ 729 { "INTR", 0}, /* 5/14 */ 730 { "STEP", 0}, /* 6/18 */ 731 { "FFLAGS", 1}, /* 7/1c */ 732 { "CFG1", 1}, /* 8/20 */ 733 { "STAT2", 0}, /* 9/24 */ 734 { "CFG4", 1}, /* a/28 */ 735 { "CFG2", 1}, /* b/2c */ 736 { "CFG3", 1}, /* c/30 */ 737 { "-none", 1}, /* d/34 */ 738 { "TCH", 1}, /* e/38 */ 739 { "TCX", 1}, /* f/3c */ 740}; 741 742static const struct { 743 char *r_name; 744 int r_flag; 745} esp__write_regnames[] = { 746 { "TCL", 1}, /* 0/00 */ 747 { "TCM", 1}, /* 1/04 */ 748 { "FIFO", 0}, /* 2/08 */ 749 { "CMD", 0}, /* 3/0c */ 750 { "SELID", 1}, /* 4/10 */ 751 { "TIMEOUT", 1}, /* 5/14 */ 752 { "SYNCTP", 1}, /* 6/18 */ 753 { "SYNCOFF", 1}, /* 7/1c */ 754 { "CFG1", 1}, /* 8/20 */ 755 { "CCF", 1}, /* 9/24 */ 756 { "TEST", 1}, /* a/28 */ 757 { "CFG2", 1}, /* b/2c */ 758 { "CFG3", 1}, /* c/30 */ 759 { "-none", 1}, /* d/34 */ 760 { "TCH", 1}, /* e/38 */ 761 { "TCX", 1}, /* f/3c */ 762}; 763#endif 764 765static u_char 766esp_read_reg(struct ncr53c9x_softc *sc, int reg) 767{ 768 struct esp_softc *esc = (struct esp_softc *)sc; 769 u_char v; 770 771 v = bus_read_1(esc->sc_res, reg * 4); 772 773#ifdef ESP_SBUS_DEBUG 774 if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag) 775 printf("RD:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ? 776 esp__read_regnames[reg].r_name : "<***>", v); 777#endif 778 779 return (v); 780} 781 782static void 783esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v) 784{ 785 struct esp_softc *esc = (struct esp_softc *)sc; 786 787#ifdef ESP_SBUS_DEBUG 788 if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag) 789 printf("WR:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ? 790 esp__write_regnames[reg].r_name : "<***>", v); 791#endif 792 793 bus_write_1(esc->sc_res, reg * 4, v); 794} 795 796static int 797esp_dma_isintr(struct ncr53c9x_softc *sc) 798{ 799 struct esp_softc *esc = (struct esp_softc *)sc; 800 801 return (DMA_ISINTR(esc->sc_dma)); 802} 803 804static void 805esp_dma_reset(struct ncr53c9x_softc *sc) 806{ 807 struct esp_softc *esc = (struct esp_softc *)sc; 808 809 DMA_RESET(esc->sc_dma); 810} 811 812static int 813esp_dma_intr(struct ncr53c9x_softc *sc) 814{ 815 struct esp_softc *esc = (struct esp_softc *)sc; 816 817 return (DMA_INTR(esc->sc_dma)); 818} 819 820static int 821esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len, 822 int datain, size_t *dmasize) 823{ 824 struct esp_softc *esc = (struct esp_softc *)sc; 825 826 return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize)); 827} 828 829static void 830esp_dma_go(struct ncr53c9x_softc *sc) 831{ 832 struct esp_softc *esc = (struct esp_softc *)sc; 833 834 DMA_GO(esc->sc_dma); 835} 836 837static void 838esp_dma_stop(struct ncr53c9x_softc *sc) 839{ 840 struct esp_softc *esc = (struct esp_softc *)sc; 841 842 L64854_SCSR(esc->sc_dma, L64854_GCSR(esc->sc_dma) & ~D_EN_DMA); 843} 844 845static int 846esp_dma_isactive(struct ncr53c9x_softc *sc) 847{ 848 struct esp_softc *esc = (struct esp_softc *)sc; 849 850 return (DMA_ISACTIVE(esc->sc_dma)); 851} 852