1130293Sscottl/*- 2130293Sscottl * Copyright (c) 2004 Scott Long 3182876Smarius * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org> 4130293Sscottl * All rights reserved. 5130293Sscottl * 6130293Sscottl * Redistribution and use in source and binary forms, with or without 7130293Sscottl * modification, are permitted provided that the following conditions 8130293Sscottl * are met: 9130293Sscottl * 1. Redistributions of source code must retain the above copyright 10130293Sscottl * notice, this list of conditions and the following disclaimer. 11130293Sscottl * 2. Redistributions in binary form must reproduce the above copyright 12130293Sscottl * notice, this list of conditions and the following disclaimer in the 13130293Sscottl * documentation and/or other materials provided with the distribution. 14130293Sscottl * 15130293Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16130293Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17130293Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18130293Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19130293Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20130293Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21130293Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22130293Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23130293Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24130293Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25130293Sscottl * SUCH DAMAGE. 26130293Sscottl * 27130293Sscottl */ 28130293Sscottl 29226381Smarius/* $NetBSD: esp_sbus.c,v 1.51 2009/09/17 16:28:12 tsutsui Exp $ */ 30130293Sscottl 31130293Sscottl/*- 32130293Sscottl * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 33130293Sscottl * All rights reserved. 34130293Sscottl * 35130293Sscottl * This code is derived from software contributed to The NetBSD Foundation 36130293Sscottl * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace 37130293Sscottl * Simulation Facility, NASA Ames Research Center; Paul Kranenburg. 38130293Sscottl * 39130293Sscottl * Redistribution and use in source and binary forms, with or without 40130293Sscottl * modification, are permitted provided that the following conditions 41130293Sscottl * are met: 42130293Sscottl * 1. Redistributions of source code must retain the above copyright 43130293Sscottl * notice, this list of conditions and the following disclaimer. 44130293Sscottl * 2. Redistributions in binary form must reproduce the above copyright 45130293Sscottl * notice, this list of conditions and the following disclaimer in the 46130293Sscottl * documentation and/or other materials provided with the distribution. 47130293Sscottl * 48130293Sscottl * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 49130293Sscottl * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 50130293Sscottl * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 51130293Sscottl * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 52130293Sscottl * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 53130293Sscottl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 54130293Sscottl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 55130293Sscottl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 56130293Sscottl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 57130293Sscottl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 58130293Sscottl * POSSIBILITY OF SUCH DAMAGE. 59130293Sscottl */ 60130293Sscottl 61130293Sscottl#include <sys/cdefs.h> 62130293Sscottl__FBSDID("$FreeBSD$"); 63130293Sscottl 64130293Sscottl#include <sys/param.h> 65130293Sscottl#include <sys/systm.h> 66130293Sscottl#include <sys/bus.h> 67130293Sscottl#include <sys/kernel.h> 68182876Smarius#include <sys/lock.h> 69130833Sscottl#include <sys/module.h> 70182876Smarius#include <sys/mutex.h> 71226947Smarius#include <sys/rman.h> 72130293Sscottl 73133589Smarius#include <dev/ofw/ofw_bus.h> 74133589Smarius#include <dev/ofw/openfirm.h> 75130293Sscottl#include <machine/bus.h> 76207885Smarius#include <machine/ofw_machdep.h> 77130293Sscottl#include <machine/resource.h> 78130293Sscottl 79130293Sscottl#include <cam/cam.h> 80130293Sscottl#include <cam/cam_ccb.h> 81130293Sscottl#include <cam/scsi/scsi_all.h> 82182876Smarius#include <cam/scsi/scsi_message.h> 83130293Sscottl 84137533Strhodes#include <sparc64/sbus/lsi64854reg.h> 85137533Strhodes#include <sparc64/sbus/lsi64854var.h> 86137533Strhodes#include <sparc64/sbus/sbusvar.h> 87130293Sscottl 88130293Sscottl#include <dev/esp/ncr53c9xreg.h> 89130293Sscottl#include <dev/esp/ncr53c9xvar.h> 90130293Sscottl 91130293Sscottl/* #define ESP_SBUS_DEBUG */ 92130293Sscottl 93130293Sscottlstruct esp_softc { 94130293Sscottl struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ 95226947Smarius device_t sc_dev; 96130293Sscottl 97130293Sscottl struct resource *sc_res; 98130293Sscottl 99130293Sscottl struct resource *sc_irqres; 100130293Sscottl void *sc_irq; 101130293Sscottl 102133039Strhodes struct lsi64854_softc *sc_dma; /* pointer to my DMA */ 103130293Sscottl}; 104130293Sscottl 105146392Smariusstatic int esp_probe(device_t); 106146392Smariusstatic int esp_dma_attach(device_t); 107146392Smariusstatic int esp_dma_detach(device_t); 108130293Sscottlstatic int esp_sbus_attach(device_t); 109130293Sscottlstatic int esp_sbus_detach(device_t); 110146392Smariusstatic int esp_suspend(device_t); 111146392Smariusstatic int esp_resume(device_t); 112130293Sscottl 113146392Smariusstatic device_method_t esp_dma_methods[] = { 114146392Smarius DEVMETHOD(device_probe, esp_probe), 115146392Smarius DEVMETHOD(device_attach, esp_dma_attach), 116146392Smarius DEVMETHOD(device_detach, esp_dma_detach), 117146392Smarius DEVMETHOD(device_suspend, esp_suspend), 118146392Smarius DEVMETHOD(device_resume, esp_resume), 119226947Smarius 120227848Smarius DEVMETHOD_END 121146392Smarius}; 122146392Smarius 123146392Smariusstatic driver_t esp_dma_driver = { 124146392Smarius "esp", 125146392Smarius esp_dma_methods, 126146392Smarius sizeof(struct esp_softc) 127146392Smarius}; 128146392Smarius 129146392SmariusDRIVER_MODULE(esp, dma, esp_dma_driver, esp_devclass, 0, 0); 130165102SmjacobMODULE_DEPEND(esp, dma, 1, 1, 1); 131146392Smarius 132130293Sscottlstatic device_method_t esp_sbus_methods[] = { 133146392Smarius DEVMETHOD(device_probe, esp_probe), 134130293Sscottl DEVMETHOD(device_attach, esp_sbus_attach), 135130293Sscottl DEVMETHOD(device_detach, esp_sbus_detach), 136146392Smarius DEVMETHOD(device_suspend, esp_suspend), 137146392Smarius DEVMETHOD(device_resume, esp_resume), 138226947Smarius 139227848Smarius DEVMETHOD_END 140130293Sscottl}; 141130293Sscottl 142130293Sscottlstatic driver_t esp_sbus_driver = { 143130293Sscottl "esp", 144130293Sscottl esp_sbus_methods, 145130293Sscottl sizeof(struct esp_softc) 146130293Sscottl}; 147130293Sscottl 148130293SscottlDRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0); 149165102SmjacobMODULE_DEPEND(esp, sbus, 1, 1, 1); 150130293Sscottl 151130293Sscottl/* 152180692Smarius * Functions and the switch for the MI code 153130293Sscottl */ 154226381Smariusstatic uint8_t esp_read_reg(struct ncr53c9x_softc *sc, int reg); 155226381Smariusstatic void esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v); 156180692Smariusstatic int esp_dma_isintr(struct ncr53c9x_softc *sc); 157180692Smariusstatic void esp_dma_reset(struct ncr53c9x_softc *sc); 158180692Smariusstatic int esp_dma_intr(struct ncr53c9x_softc *sc); 159226381Smariusstatic int esp_dma_setup(struct ncr53c9x_softc *sc, void **addr, 160180692Smarius size_t *len, int datain, size_t *dmasize); 161180692Smariusstatic void esp_dma_go(struct ncr53c9x_softc *sc); 162180692Smariusstatic void esp_dma_stop(struct ncr53c9x_softc *sc); 163180692Smariusstatic int esp_dma_isactive(struct ncr53c9x_softc *sc); 164182876Smariusstatic int espattach(struct esp_softc *esc, 165182876Smarius const struct ncr53c9x_glue *gluep); 166182876Smariusstatic int espdetach(struct esp_softc *esc); 167130293Sscottl 168263763Sdimstatic const struct ncr53c9x_glue esp_sbus_glue = { 169130293Sscottl esp_read_reg, 170130293Sscottl esp_write_reg, 171130293Sscottl esp_dma_isintr, 172130293Sscottl esp_dma_reset, 173130293Sscottl esp_dma_intr, 174130293Sscottl esp_dma_setup, 175130293Sscottl esp_dma_go, 176130293Sscottl esp_dma_stop, 177130293Sscottl esp_dma_isactive, 178130293Sscottl}; 179130293Sscottl 180130293Sscottlstatic int 181146392Smariusesp_probe(device_t dev) 182130293Sscottl{ 183133589Smarius const char *name; 184130293Sscottl 185133589Smarius name = ofw_bus_get_name(dev); 186130293Sscottl if (strcmp("SUNW,fas", name) == 0) { 187130293Sscottl device_set_desc(dev, "Sun FAS366 Fast-Wide SCSI"); 188145201Smarius return (BUS_PROBE_DEFAULT); 189146392Smarius } else if (strcmp("esp", name) == 0) { 190146392Smarius device_set_desc(dev, "Sun ESP SCSI/Sun FAS Fast-SCSI"); 191146392Smarius return (BUS_PROBE_DEFAULT); 192130293Sscottl } 193130293Sscottl 194130293Sscottl return (ENXIO); 195130293Sscottl} 196130293Sscottl 197130293Sscottlstatic int 198130293Sscottlesp_sbus_attach(device_t dev) 199130293Sscottl{ 200145201Smarius struct esp_softc *esc; 201145201Smarius struct ncr53c9x_softc *sc; 202130293Sscottl struct lsi64854_softc *lsc; 203146392Smarius device_t *children; 204182876Smarius int error, i, nchildren; 205130293Sscottl 206145201Smarius esc = device_get_softc(dev); 207145201Smarius sc = &esc->sc_ncr53c9x; 208145201Smarius 209146392Smarius lsc = NULL; 210130293Sscottl esc->sc_dev = dev; 211146392Smarius sc->sc_freq = sbus_get_clockfreq(dev); 212130293Sscottl 213182876Smarius if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") == 0) { 214146392Smarius /* 215146392Smarius * Allocate space for DMA, in SUNW,fas there are no 216146392Smarius * separate DMA devices. 217146392Smarius */ 218146392Smarius lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF, 219146392Smarius M_NOWAIT | M_ZERO); 220146392Smarius if (lsc == NULL) { 221146392Smarius device_printf(dev, "out of memory (lsi64854_softc)\n"); 222146392Smarius return (ENOMEM); 223146392Smarius } 224146392Smarius esc->sc_dma = lsc; 225146392Smarius 226146392Smarius /* 227146392Smarius * SUNW,fas have 2 register spaces: DMA (lsi64854) and 228146392Smarius * SCSI core (ncr53c9x). 229146392Smarius */ 230146392Smarius 231146392Smarius /* Allocate DMA registers. */ 232182876Smarius i = 0; 233146392Smarius if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 234182876Smarius &i, RF_ACTIVE)) == NULL) { 235146392Smarius device_printf(dev, "cannot allocate DMA registers\n"); 236146392Smarius error = ENXIO; 237146392Smarius goto fail_sbus_lsc; 238146392Smarius } 239146392Smarius 240146392Smarius /* Create a parent DMA tag based on this bus. */ 241146392Smarius error = bus_dma_tag_create( 242166165Smarius bus_get_dma_tag(dev), /* parent */ 243182876Smarius 1, 0, /* alignment, boundary */ 244146392Smarius BUS_SPACE_MAXADDR, /* lowaddr */ 245146392Smarius BUS_SPACE_MAXADDR, /* highaddr */ 246146392Smarius NULL, NULL, /* filter, filterarg */ 247226947Smarius BUS_SPACE_MAXSIZE, /* maxsize */ 248226947Smarius BUS_SPACE_UNRESTRICTED, /* nsegments */ 249226947Smarius BUS_SPACE_MAXSIZE, /* maxsegsize */ 250146392Smarius 0, /* flags */ 251146392Smarius NULL, NULL, /* no locking */ 252146392Smarius &lsc->sc_parent_dmat); 253146392Smarius if (error != 0) { 254146392Smarius device_printf(dev, "cannot allocate parent DMA tag\n"); 255146392Smarius goto fail_sbus_lres; 256146392Smarius } 257146392Smarius 258182876Smarius i = sbus_get_burstsz(dev); 259182876Smarius 260146392Smarius#ifdef ESP_SBUS_DEBUG 261182876Smarius printf("%s: burst 0x%x\n", __func__, i); 262146392Smarius#endif 263146392Smarius 264182876Smarius lsc->sc_burst = (i & SBUS_BURST_32) ? 32 : 265182876Smarius (i & SBUS_BURST_16) ? 16 : 0; 266146392Smarius 267146392Smarius lsc->sc_channel = L64854_CHANNEL_SCSI; 268146392Smarius lsc->sc_client = sc; 269146392Smarius lsc->sc_dev = dev; 270146392Smarius 271146392Smarius /* 272146392Smarius * Allocate SCSI core registers. 273146392Smarius */ 274182876Smarius i = 1; 275146392Smarius if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 276182876Smarius &i, RF_ACTIVE)) == NULL) { 277146392Smarius device_printf(dev, 278146392Smarius "cannot allocate SCSI core registers\n"); 279146392Smarius error = ENXIO; 280182876Smarius goto fail_sbus_lpdma; 281146392Smarius } 282146392Smarius } else { 283146392Smarius /* 284180692Smarius * Search accompanying DMA engine. It should have been 285146392Smarius * already attached otherwise there isn't much we can do. 286146392Smarius */ 287146392Smarius if (device_get_children(device_get_parent(dev), &children, 288146392Smarius &nchildren) != 0) { 289146392Smarius device_printf(dev, "cannot determine siblings\n"); 290146392Smarius return (ENXIO); 291146392Smarius } 292146392Smarius for (i = 0; i < nchildren; i++) { 293146392Smarius if (device_is_attached(children[i]) && 294226947Smarius sbus_get_slot(children[i]) == 295226947Smarius sbus_get_slot(dev) && 296226947Smarius strcmp(ofw_bus_get_name(children[i]), 297226947Smarius "dma") == 0) { 298146392Smarius /* XXX hackery */ 299146392Smarius esc->sc_dma = (struct lsi64854_softc *) 300146392Smarius device_get_softc(children[i]); 301146392Smarius break; 302146392Smarius } 303146392Smarius } 304146392Smarius free(children, M_TEMP); 305146392Smarius if (esc->sc_dma == NULL) { 306146392Smarius device_printf(dev, "cannot find DMA engine\n"); 307146392Smarius return (ENXIO); 308146392Smarius } 309146392Smarius esc->sc_dma->sc_client = sc; 310146392Smarius 311146392Smarius /* 312146392Smarius * Allocate SCSI core registers. 313146392Smarius */ 314182876Smarius i = 0; 315146392Smarius if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 316182876Smarius &i, RF_ACTIVE)) == NULL) { 317146392Smarius device_printf(dev, 318146392Smarius "cannot allocate SCSI core registers\n"); 319146392Smarius return (ENXIO); 320146392Smarius } 321130293Sscottl } 322130293Sscottl 323146392Smarius error = espattach(esc, &esp_sbus_glue); 324146392Smarius if (error != 0) { 325146392Smarius device_printf(dev, "espattach failed\n"); 326146392Smarius goto fail_sbus_eres; 327146392Smarius } 328130293Sscottl 329146392Smarius return (0); 330146392Smarius 331146392Smarius fail_sbus_eres: 332182876Smarius bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 333182876Smarius esc->sc_res); 334182876Smarius if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0) 335146392Smarius return (error); 336146392Smarius fail_sbus_lpdma: 337146392Smarius bus_dma_tag_destroy(lsc->sc_parent_dmat); 338146392Smarius fail_sbus_lres: 339182876Smarius bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res), 340182876Smarius lsc->sc_res); 341146392Smarius fail_sbus_lsc: 342146392Smarius free(lsc, M_DEVBUF); 343146392Smarius return (error); 344146392Smarius} 345146392Smarius 346146392Smariusstatic int 347146392Smariusesp_sbus_detach(device_t dev) 348146392Smarius{ 349146392Smarius struct esp_softc *esc; 350146392Smarius struct lsi64854_softc *lsc; 351146392Smarius int error; 352146392Smarius 353146392Smarius esc = device_get_softc(dev); 354146392Smarius lsc = esc->sc_dma; 355146392Smarius 356182876Smarius error = espdetach(esc); 357146392Smarius if (error != 0) 358146392Smarius return (error); 359182876Smarius bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 360182876Smarius esc->sc_res); 361146392Smarius if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0) 362146392Smarius return (0); 363146392Smarius bus_dma_tag_destroy(lsc->sc_parent_dmat); 364182876Smarius bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res), 365182876Smarius lsc->sc_res); 366146392Smarius free(lsc, M_DEVBUF); 367146392Smarius 368146392Smarius return (0); 369146392Smarius} 370146392Smarius 371146392Smariusstatic int 372146392Smariusesp_dma_attach(device_t dev) 373146392Smarius{ 374146392Smarius struct esp_softc *esc; 375146392Smarius struct ncr53c9x_softc *sc; 376182876Smarius int error, i; 377146392Smarius 378146392Smarius esc = device_get_softc(dev); 379146392Smarius sc = &esc->sc_ncr53c9x; 380146392Smarius 381146392Smarius esc->sc_dev = dev; 382182876Smarius if (OF_getprop(ofw_bus_get_node(dev), "clock-frequency", 383182876Smarius &sc->sc_freq, sizeof(sc->sc_freq)) == -1) { 384146392Smarius printf("failed to query OFW for clock-frequency\n"); 385130293Sscottl return (ENXIO); 386130293Sscottl } 387130293Sscottl 388146392Smarius /* XXX hackery */ 389146392Smarius esc->sc_dma = (struct lsi64854_softc *) 390146392Smarius device_get_softc(device_get_parent(dev)); 391146392Smarius esc->sc_dma->sc_client = sc; 392130293Sscottl 393130293Sscottl /* 394146392Smarius * Allocate SCSI core registers. 395130293Sscottl */ 396182876Smarius i = 0; 397130293Sscottl if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 398182876Smarius &i, RF_ACTIVE)) == NULL) { 399145201Smarius device_printf(dev, "cannot allocate SCSI core registers\n"); 400130293Sscottl return (ENXIO); 401130293Sscottl } 402130293Sscottl 403146392Smarius error = espattach(esc, &esp_sbus_glue); 404146392Smarius if (error != 0) { 405146392Smarius device_printf(dev, "espattach failed\n"); 406146392Smarius goto fail_dma_eres; 407146392Smarius } 408130293Sscottl 409130293Sscottl return (0); 410146392Smarius 411146392Smarius fail_dma_eres: 412182876Smarius bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 413182876Smarius esc->sc_res); 414146392Smarius return (error); 415130293Sscottl} 416130293Sscottl 417130293Sscottlstatic int 418146392Smariusesp_dma_detach(device_t dev) 419130293Sscottl{ 420146392Smarius struct esp_softc *esc; 421146392Smarius int error; 422130293Sscottl 423130293Sscottl esc = device_get_softc(dev); 424146392Smarius 425182876Smarius error = espdetach(esc); 426146392Smarius if (error != 0) 427146392Smarius return (error); 428182876Smarius bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 429182876Smarius esc->sc_res); 430146392Smarius 431146392Smarius return (0); 432130293Sscottl} 433130293Sscottl 434130293Sscottlstatic int 435146392Smariusesp_suspend(device_t dev) 436130293Sscottl{ 437145201Smarius 438130293Sscottl return (ENXIO); 439130293Sscottl} 440130293Sscottl 441130293Sscottlstatic int 442146392Smariusesp_resume(device_t dev) 443130293Sscottl{ 444145201Smarius 445130293Sscottl return (ENXIO); 446130293Sscottl} 447130293Sscottl 448146392Smariusstatic int 449182876Smariusespattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep) 450130293Sscottl{ 451130293Sscottl struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 452130293Sscottl unsigned int uid = 0; 453182876Smarius int error, i; 454130293Sscottl 455182876Smarius NCR_LOCK_INIT(sc); 456182876Smarius 457207281Smarius sc->sc_id = OF_getscsinitid(esc->sc_dev); 458182876Smarius 459182876Smarius#ifdef ESP_SBUS_DEBUG 460182876Smarius device_printf(esc->sc_dev, "%s: sc_id %d, freq %d\n", 461182876Smarius __func__, sc->sc_id, sc->sc_freq); 462182876Smarius#endif 463182876Smarius 464130293Sscottl /* 465146392Smarius * The `ESC' DMA chip must be reset before we can access 466146392Smarius * the ESP registers. 467146392Smarius */ 468146392Smarius if (esc->sc_dma->sc_rev == DMAREV_ESC) 469146392Smarius DMA_RESET(esc->sc_dma); 470146392Smarius 471146392Smarius /* 472130293Sscottl * Set up glue for MI code early; we use some of it here. 473130293Sscottl */ 474130293Sscottl sc->sc_glue = gluep; 475130293Sscottl 476130293Sscottl /* gimme MHz */ 477130293Sscottl sc->sc_freq /= 1000000; 478130293Sscottl 479130293Sscottl /* 480130293Sscottl * XXX More of this should be in ncr53c9x_attach(), but 481130293Sscottl * XXX should we really poke around the chip that much in 482130293Sscottl * XXX the MI code? Think about this more... 483130293Sscottl */ 484130293Sscottl 485130293Sscottl /* 486180692Smarius * Read the part-unique ID code of the SCSI chip. The contained 487146392Smarius * value is only valid if all of the following conditions are met: 488146392Smarius * - After power-up or chip reset. 489146392Smarius * - Before any value is written to this register. 490146392Smarius * - The NCRCFG2_FE bit is set. 491146392Smarius * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued. 492146392Smarius */ 493146392Smarius NCRCMD(sc, NCRCMD_RSTCHIP); 494146392Smarius NCRCMD(sc, NCRCMD_NOP); 495146392Smarius sc->sc_cfg2 = NCRCFG2_FE; 496146392Smarius NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 497146392Smarius NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA); 498146392Smarius uid = NCR_READ_REG(sc, NCR_UID); 499146392Smarius 500146392Smarius /* 501130293Sscottl * It is necessary to try to load the 2nd config register here, 502130293Sscottl * to find out what rev the esp chip is, else the ncr53c9x_reset 503130293Sscottl * will not set up the defaults correctly. 504130293Sscottl */ 505130293Sscottl sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 506146392Smarius NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1); 507146392Smarius sc->sc_cfg2 = 0; 508146392Smarius NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 509130293Sscottl sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE; 510130293Sscottl NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 511130293Sscottl 512130293Sscottl if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) != 513226947Smarius (NCRCFG2_SCSI2 | NCRCFG2_RPE)) 514130293Sscottl sc->sc_rev = NCR_VARIANT_ESP100; 515226947Smarius else { 516130293Sscottl sc->sc_cfg2 = NCRCFG2_SCSI2; 517130293Sscottl NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 518130293Sscottl sc->sc_cfg3 = 0; 519130293Sscottl NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 520130293Sscottl sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK); 521130293Sscottl NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 522130293Sscottl if (NCR_READ_REG(sc, NCR_CFG3) != 523226947Smarius (NCRCFG3_CDB | NCRCFG3_FCLK)) 524130293Sscottl sc->sc_rev = NCR_VARIANT_ESP100A; 525226947Smarius else { 526180692Smarius /* NCRCFG2_FE enables > 64K transfers. */ 527130293Sscottl sc->sc_cfg2 |= NCRCFG2_FE; 528130293Sscottl sc->sc_cfg3 = 0; 529130293Sscottl NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 530146392Smarius if (sc->sc_freq <= 25) 531146392Smarius sc->sc_rev = NCR_VARIANT_ESP200; 532146392Smarius else { 533146392Smarius switch ((uid & 0xf8) >> 3) { 534146392Smarius case 0x00: 535146392Smarius sc->sc_rev = NCR_VARIANT_FAS100A; 536146392Smarius break; 537180692Smarius 538146392Smarius case 0x02: 539146392Smarius if ((uid & 0x07) == 0x02) 540226947Smarius sc->sc_rev = 541226947Smarius NCR_VARIANT_FAS216; 542146392Smarius else 543226947Smarius sc->sc_rev = 544226947Smarius NCR_VARIANT_FAS236; 545146392Smarius break; 546180692Smarius 547146392Smarius case 0x0a: 548146392Smarius sc->sc_rev = NCR_VARIANT_FAS366; 549146392Smarius break; 550180692Smarius 551146392Smarius default: 552146392Smarius /* 553146392Smarius * We could just treat unknown chips 554146392Smarius * as ESP200 but then we would most 555146392Smarius * likely drive them out of specs. 556146392Smarius */ 557146392Smarius device_printf(esc->sc_dev, 558146392Smarius "Unknown chip\n"); 559226947Smarius error = ENXIO; 560226947Smarius goto fail_lock; 561146392Smarius } 562146392Smarius } 563130293Sscottl } 564130293Sscottl } 565130293Sscottl 566130293Sscottl#ifdef ESP_SBUS_DEBUG 567145201Smarius printf("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid); 568130293Sscottl#endif 569130293Sscottl 570130293Sscottl /* 571130293Sscottl * This is the value used to start sync negotiations 572130293Sscottl * Note that the NCR register "SYNCTP" is programmed 573130293Sscottl * in "clocks per byte", and has a minimum value of 4. 574130293Sscottl * The SCSI period used in negotiation is one-fourth 575130293Sscottl * of the time (in nanoseconds) needed to transfer one byte. 576130293Sscottl * Since the chip's clock is given in MHz, we have the following 577130293Sscottl * formula: 4 * period = (1000 / freq) * 4 578130293Sscottl */ 579130293Sscottl sc->sc_minsync = 1000 / sc->sc_freq; 580130293Sscottl 581226947Smarius /* 582226947Smarius * Except for some variants the maximum transfer size is 64k. 583226947Smarius */ 584226947Smarius sc->sc_maxxfer = 64 * 1024; 585130293Sscottl sc->sc_maxoffset = 15; 586130370Sscottl sc->sc_extended_geom = 1; 587130349Sscottl 588130293Sscottl /* 589130293Sscottl * Alas, we must now modify the value a bit, because it's 590226947Smarius * only valid when we can switch on FASTCLK and FASTSCSI bits 591226947Smarius * in the config register 3... 592130293Sscottl */ 593130293Sscottl switch (sc->sc_rev) { 594130293Sscottl case NCR_VARIANT_ESP100: 595182876Smarius sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 596130293Sscottl sc->sc_minsync = 0; /* No synch on old chip? */ 597130293Sscottl break; 598130293Sscottl 599130293Sscottl case NCR_VARIANT_ESP100A: 600130293Sscottl case NCR_VARIANT_ESP200: 601182876Smarius sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 602146392Smarius /* Min clocks/byte is 5 */ 603146392Smarius sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5); 604146392Smarius break; 605146392Smarius 606146392Smarius case NCR_VARIANT_FAS100A: 607146392Smarius case NCR_VARIANT_FAS216: 608146392Smarius case NCR_VARIANT_FAS236: 609146392Smarius /* 610146392Smarius * The onboard SCSI chips in Sun Ultra 1 are actually 611146392Smarius * documented to be NCR53C9X which use NCRCFG3_FCLK and 612180692Smarius * NCRCFG3_FSCSI. BSD/OS however probes these chips as 613146392Smarius * FAS100A and uses NCRF9XCFG3_FCLK and NCRF9XCFG3_FSCSI 614146392Smarius * instead which seems to be correct as otherwise sync 615180692Smarius * negotiation just doesn't work. Using NCRF9XCFG3_FCLK 616146392Smarius * and NCRF9XCFG3_FSCSI with these chips in fact also 617146392Smarius * yields Fast-SCSI speed. 618146392Smarius */ 619146392Smarius sc->sc_features = NCR_F_FASTSCSI; 620146392Smarius sc->sc_cfg3 = NCRF9XCFG3_FCLK; 621146392Smarius sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI; 622182876Smarius sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 623146392Smarius sc->sc_maxxfer = 16 * 1024 * 1024; 624146392Smarius break; 625146392Smarius 626130293Sscottl case NCR_VARIANT_FAS366: 627182876Smarius sc->sc_maxwidth = MSG_EXT_WDTR_BUS_16_BIT; 628130293Sscottl sc->sc_maxxfer = 16 * 1024 * 1024; 629130293Sscottl break; 630130293Sscottl } 631130293Sscottl 632226947Smarius /* 633226947Smarius * Given that we allocate resources based on sc->sc_maxxfer it doesn't 634226947Smarius * make sense to supply a value higher than the maximum actually used. 635226947Smarius */ 636226947Smarius sc->sc_maxxfer = min(sc->sc_maxxfer, MAXPHYS); 637226947Smarius 638226947Smarius /* Attach the DMA engine. */ 639226947Smarius error = lsi64854_attach(esc->sc_dma); 640226947Smarius if (error != 0) { 641226947Smarius device_printf(esc->sc_dev, "lsi64854_attach failed\n"); 642226947Smarius goto fail_lock; 643226947Smarius } 644226947Smarius 645180692Smarius /* Establish interrupt channel. */ 646182876Smarius i = 0; 647130293Sscottl if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ, 648182876Smarius &i, RF_SHAREABLE|RF_ACTIVE)) == NULL) { 649146392Smarius device_printf(esc->sc_dev, "cannot allocate interrupt\n"); 650182876Smarius goto fail_lsi; 651130293Sscottl } 652130293Sscottl if (bus_setup_intr(esc->sc_dev, esc->sc_irqres, 653182876Smarius INTR_MPSAFE | INTR_TYPE_CAM, NULL, ncr53c9x_intr, sc, 654182876Smarius &esc->sc_irq)) { 655146392Smarius device_printf(esc->sc_dev, "cannot set up interrupt\n"); 656146392Smarius error = ENXIO; 657146392Smarius goto fail_ires; 658130293Sscottl } 659130293Sscottl 660180692Smarius /* Turn on target selection using the `DMA' method. */ 661130293Sscottl if (sc->sc_rev != NCR_VARIANT_FAS366) 662130293Sscottl sc->sc_features |= NCR_F_DMASELECT; 663130293Sscottl 664130293Sscottl /* Do the common parts of attachment. */ 665130293Sscottl sc->sc_dev = esc->sc_dev; 666146392Smarius error = ncr53c9x_attach(sc); 667146392Smarius if (error != 0) { 668146392Smarius device_printf(esc->sc_dev, "ncr53c9x_attach failed\n"); 669146392Smarius goto fail_intr; 670146392Smarius } 671146392Smarius 672146392Smarius return (0); 673146392Smarius 674146392Smarius fail_intr: 675146392Smarius bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq); 676146392Smarius fail_ires: 677182876Smarius bus_release_resource(esc->sc_dev, SYS_RES_IRQ, 678182876Smarius rman_get_rid(esc->sc_irqres), esc->sc_irqres); 679182876Smarius fail_lsi: 680182876Smarius lsi64854_detach(esc->sc_dma); 681182876Smarius fail_lock: 682182876Smarius NCR_LOCK_DESTROY(sc); 683146392Smarius return (error); 684130293Sscottl} 685130293Sscottl 686182876Smariusstatic int 687182876Smariusespdetach(struct esp_softc *esc) 688182876Smarius{ 689182876Smarius struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 690182876Smarius int error; 691182876Smarius 692182876Smarius bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq); 693182876Smarius error = ncr53c9x_detach(sc); 694182876Smarius if (error != 0) 695182876Smarius return (error); 696182876Smarius error = lsi64854_detach(esc->sc_dma); 697182876Smarius if (error != 0) 698182876Smarius return (error); 699182876Smarius NCR_LOCK_DESTROY(sc); 700182876Smarius bus_release_resource(esc->sc_dev, SYS_RES_IRQ, 701182876Smarius rman_get_rid(esc->sc_irqres), esc->sc_irqres); 702182876Smarius 703182876Smarius return (0); 704182876Smarius} 705182876Smarius 706130293Sscottl/* 707180692Smarius * Glue functions 708130293Sscottl */ 709130293Sscottl 710130293Sscottl#ifdef ESP_SBUS_DEBUG 711182876Smariusstatic int esp_sbus_debug = 0; 712130293Sscottl 713182876Smariusstatic const struct { 714226381Smarius const char *r_name; 715226381Smarius int r_flag; 716226381Smarius} const esp__read_regnames [] = { 717130293Sscottl { "TCL", 0}, /* 0/00 */ 718130293Sscottl { "TCM", 0}, /* 1/04 */ 719130293Sscottl { "FIFO", 0}, /* 2/08 */ 720130293Sscottl { "CMD", 0}, /* 3/0c */ 721130293Sscottl { "STAT", 0}, /* 4/10 */ 722130293Sscottl { "INTR", 0}, /* 5/14 */ 723130293Sscottl { "STEP", 0}, /* 6/18 */ 724130293Sscottl { "FFLAGS", 1}, /* 7/1c */ 725130293Sscottl { "CFG1", 1}, /* 8/20 */ 726130293Sscottl { "STAT2", 0}, /* 9/24 */ 727130293Sscottl { "CFG4", 1}, /* a/28 */ 728130293Sscottl { "CFG2", 1}, /* b/2c */ 729130293Sscottl { "CFG3", 1}, /* c/30 */ 730130293Sscottl { "-none", 1}, /* d/34 */ 731130293Sscottl { "TCH", 1}, /* e/38 */ 732130293Sscottl { "TCX", 1}, /* f/3c */ 733130293Sscottl}; 734130293Sscottl 735226381Smariusstatic const const struct { 736226381Smarius const char *r_name; 737226381Smarius int r_flag; 738226381Smarius} const esp__write_regnames[] = { 739130293Sscottl { "TCL", 1}, /* 0/00 */ 740130293Sscottl { "TCM", 1}, /* 1/04 */ 741130293Sscottl { "FIFO", 0}, /* 2/08 */ 742130293Sscottl { "CMD", 0}, /* 3/0c */ 743130293Sscottl { "SELID", 1}, /* 4/10 */ 744130293Sscottl { "TIMEOUT", 1}, /* 5/14 */ 745130293Sscottl { "SYNCTP", 1}, /* 6/18 */ 746130293Sscottl { "SYNCOFF", 1}, /* 7/1c */ 747130293Sscottl { "CFG1", 1}, /* 8/20 */ 748130293Sscottl { "CCF", 1}, /* 9/24 */ 749130293Sscottl { "TEST", 1}, /* a/28 */ 750130293Sscottl { "CFG2", 1}, /* b/2c */ 751130293Sscottl { "CFG3", 1}, /* c/30 */ 752130293Sscottl { "-none", 1}, /* d/34 */ 753130293Sscottl { "TCH", 1}, /* e/38 */ 754130293Sscottl { "TCX", 1}, /* f/3c */ 755130293Sscottl}; 756130293Sscottl#endif 757130293Sscottl 758226381Smariusstatic uint8_t 759130293Sscottlesp_read_reg(struct ncr53c9x_softc *sc, int reg) 760130293Sscottl{ 761130293Sscottl struct esp_softc *esc = (struct esp_softc *)sc; 762226381Smarius uint8_t v; 763130293Sscottl 764182876Smarius v = bus_read_1(esc->sc_res, reg * 4); 765182876Smarius 766130293Sscottl#ifdef ESP_SBUS_DEBUG 767130293Sscottl if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag) 768182876Smarius printf("RD:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ? 769182876Smarius esp__read_regnames[reg].r_name : "<***>", v); 770130293Sscottl#endif 771182876Smarius 772182876Smarius return (v); 773130293Sscottl} 774130293Sscottl 775145201Smariusstatic void 776226381Smariusesp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v) 777130293Sscottl{ 778130293Sscottl struct esp_softc *esc = (struct esp_softc *)sc; 779130293Sscottl 780130293Sscottl#ifdef ESP_SBUS_DEBUG 781130293Sscottl if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag) 782182876Smarius printf("WR:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ? 783182876Smarius esp__write_regnames[reg].r_name : "<***>", v); 784130293Sscottl#endif 785182876Smarius 786182876Smarius bus_write_1(esc->sc_res, reg * 4, v); 787130293Sscottl} 788130293Sscottl 789145201Smariusstatic int 790130293Sscottlesp_dma_isintr(struct ncr53c9x_softc *sc) 791130293Sscottl{ 792130293Sscottl struct esp_softc *esc = (struct esp_softc *)sc; 793130293Sscottl 794130293Sscottl return (DMA_ISINTR(esc->sc_dma)); 795130293Sscottl} 796130293Sscottl 797145201Smariusstatic void 798130293Sscottlesp_dma_reset(struct ncr53c9x_softc *sc) 799130293Sscottl{ 800130293Sscottl struct esp_softc *esc = (struct esp_softc *)sc; 801130293Sscottl 802130293Sscottl DMA_RESET(esc->sc_dma); 803130293Sscottl} 804130293Sscottl 805145201Smariusstatic int 806130293Sscottlesp_dma_intr(struct ncr53c9x_softc *sc) 807130293Sscottl{ 808130293Sscottl struct esp_softc *esc = (struct esp_softc *)sc; 809130293Sscottl 810130293Sscottl return (DMA_INTR(esc->sc_dma)); 811130293Sscottl} 812130293Sscottl 813145201Smariusstatic int 814226381Smariusesp_dma_setup(struct ncr53c9x_softc *sc, void **addr, size_t *len, 815226381Smarius int datain, size_t *dmasize) 816130293Sscottl{ 817130293Sscottl struct esp_softc *esc = (struct esp_softc *)sc; 818130293Sscottl 819130293Sscottl return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize)); 820130293Sscottl} 821130293Sscottl 822145201Smariusstatic void 823130293Sscottlesp_dma_go(struct ncr53c9x_softc *sc) 824130293Sscottl{ 825130293Sscottl struct esp_softc *esc = (struct esp_softc *)sc; 826130293Sscottl 827130293Sscottl DMA_GO(esc->sc_dma); 828130293Sscottl} 829130293Sscottl 830145201Smariusstatic void 831130293Sscottlesp_dma_stop(struct ncr53c9x_softc *sc) 832130293Sscottl{ 833130293Sscottl struct esp_softc *esc = (struct esp_softc *)sc; 834130293Sscottl 835180692Smarius L64854_SCSR(esc->sc_dma, L64854_GCSR(esc->sc_dma) & ~D_EN_DMA); 836130293Sscottl} 837130293Sscottl 838145201Smariusstatic int 839130293Sscottlesp_dma_isactive(struct ncr53c9x_softc *sc) 840130293Sscottl{ 841130293Sscottl struct esp_softc *esc = (struct esp_softc *)sc; 842130293Sscottl 843130293Sscottl return (DMA_ISACTIVE(esc->sc_dma)); 844130293Sscottl} 845