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