esp_sbus.c revision 330897
1139735Simp/*- 2129198Scognet * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-2-Clause-NetBSD 3129198Scognet * 4129198Scognet * Copyright (c) 2004 Scott Long 5129198Scognet * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org> 6129198Scognet * All rights reserved. 7129198Scognet * 8129198Scognet * Redistribution and use in source and binary forms, with or without 9129198Scognet * modification, are permitted provided that the following conditions 10129198Scognet * are met: 11129198Scognet * 1. Redistributions of source code must retain the above copyright 12129198Scognet * notice, this list of conditions and the following disclaimer. 13129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 14129198Scognet * notice, this list of conditions and the following disclaimer in the 15129198Scognet * documentation and/or other materials provided with the distribution. 16129198Scognet * 17129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18129198Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19129198Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20129198Scognet * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21129198Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22129198Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23129198Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27129198Scognet * SUCH DAMAGE. 28129198Scognet * 29129198Scognet */ 30129198Scognet 31129198Scognet/* $NetBSD: esp_sbus.c,v 1.51 2009/09/17 16:28:12 tsutsui Exp $ */ 32129198Scognet 33129198Scognet/*- 34129198Scognet * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 35129198Scognet * All rights reserved. 36129198Scognet * 37129198Scognet * This code is derived from software contributed to The NetBSD Foundation 38129198Scognet * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace 39129198Scognet * Simulation Facility, NASA Ames Research Center; Paul Kranenburg. 40129198Scognet * 41129198Scognet * Redistribution and use in source and binary forms, with or without 42129198Scognet * modification, are permitted provided that the following conditions 43129198Scognet * are met: 44129198Scognet * 1. Redistributions of source code must retain the above copyright 45129198Scognet * notice, this list of conditions and the following disclaimer. 46129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 47129198Scognet * notice, this list of conditions and the following disclaimer in the 48129198Scognet * documentation and/or other materials provided with the distribution. 49129198Scognet * 50129198Scognet * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 51129198Scognet * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 52129198Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53129198Scognet * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 54159100Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55129198Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56129198Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57129198Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58129198Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59129198Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 60137362Scognet * POSSIBILITY OF SUCH DAMAGE. 61129198Scognet */ 62129198Scognet 63129198Scognet#include <sys/cdefs.h> 64129198Scognet__FBSDID("$FreeBSD: stable/11/sys/dev/esp/esp_sbus.c 330897 2018-03-14 03:19:51Z eadler $"); 65159325Salc 66159325Salc#include <sys/param.h> 67129198Scognet#include <sys/systm.h> 68129198Scognet#include <sys/bus.h> 69129198Scognet#include <sys/kernel.h> 70129198Scognet#include <sys/lock.h> 71129198Scognet#include <sys/module.h> 72129198Scognet#include <sys/mutex.h> 73135641Scognet#include <sys/rman.h> 74135641Scognet 75129198Scognet#include <dev/ofw/ofw_bus.h> 76129198Scognet#include <dev/ofw/openfirm.h> 77129198Scognet#include <machine/bus.h> 78135641Scognet#include <machine/ofw_machdep.h> 79129198Scognet#include <machine/resource.h> 80137362Scognet 81129198Scognet#include <cam/cam.h> 82129198Scognet#include <cam/cam_ccb.h> 83129198Scognet#include <cam/scsi/scsi_all.h> 84129198Scognet#include <cam/scsi/scsi_message.h> 85129198Scognet 86129198Scognet#include <sparc64/sbus/lsi64854reg.h> 87129198Scognet#include <sparc64/sbus/lsi64854var.h> 88129198Scognet#include <sparc64/sbus/sbusvar.h> 89129198Scognet 90129198Scognet#include <dev/esp/ncr53c9xreg.h> 91129198Scognet#include <dev/esp/ncr53c9xvar.h> 92129198Scognet 93129198Scognet/* #define ESP_SBUS_DEBUG */ 94129198Scognet 95129198Scognetstruct esp_softc { 96129198Scognet struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ 97194459Sthompsa device_t sc_dev; 98129198Scognet 99129198Scognet struct resource *sc_res; 100129198Scognet 101129198Scognet struct resource *sc_irqres; 102129198Scognet void *sc_irq; 103129198Scognet 104129198Scognet struct lsi64854_softc *sc_dma; /* pointer to my DMA */ 105129198Scognet}; 106129198Scognet 107129198Scognetstatic int esp_probe(device_t); 108129198Scognetstatic int esp_dma_attach(device_t); 109129198Scognetstatic int esp_dma_detach(device_t); 110129198Scognetstatic int esp_sbus_attach(device_t); 111129198Scognetstatic int esp_sbus_detach(device_t); 112129198Scognetstatic int esp_suspend(device_t); 113129198Scognetstatic int esp_resume(device_t); 114129198Scognet 115129198Scognetstatic device_method_t esp_dma_methods[] = { 116129198Scognet DEVMETHOD(device_probe, esp_probe), 117129198Scognet DEVMETHOD(device_attach, esp_dma_attach), 118129198Scognet DEVMETHOD(device_detach, esp_dma_detach), 119129198Scognet DEVMETHOD(device_suspend, esp_suspend), 120129198Scognet DEVMETHOD(device_resume, esp_resume), 121129198Scognet 122129198Scognet DEVMETHOD_END 123129198Scognet}; 124129198Scognet 125129198Scognetstatic driver_t esp_dma_driver = { 126129198Scognet "esp", 127129198Scognet esp_dma_methods, 128129198Scognet sizeof(struct esp_softc) 129159325Salc}; 130129198Scognet 131129198ScognetDRIVER_MODULE(esp, dma, esp_dma_driver, esp_devclass, 0, 0); 132129198ScognetMODULE_DEPEND(esp, dma, 1, 1, 1); 133129198Scognet 134129198Scognetstatic device_method_t esp_sbus_methods[] = { 135129198Scognet DEVMETHOD(device_probe, esp_probe), 136144760Scognet DEVMETHOD(device_attach, esp_sbus_attach), 137129198Scognet DEVMETHOD(device_detach, esp_sbus_detach), 138129198Scognet DEVMETHOD(device_suspend, esp_suspend), 139129198Scognet DEVMETHOD(device_resume, esp_resume), 140129198Scognet 141129198Scognet DEVMETHOD_END 142191873Salc}; 143191873Salc 144129198Scognetstatic driver_t esp_sbus_driver = { 145137362Scognet "esp", 146159325Salc esp_sbus_methods, 147159325Salc sizeof(struct esp_softc) 148159325Salc}; 149159325Salc 150159325SalcDRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0); 151159325SalcMODULE_DEPEND(esp, sbus, 1, 1, 1); 152159325Salc 153159325Salc/* 154159325Salc * Functions and the switch for the MI code 155159325Salc */ 156129198Scognetstatic uint8_t esp_read_reg(struct ncr53c9x_softc *sc, int reg); 157129198Scognetstatic void esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v); 158135641Scognetstatic int esp_dma_isintr(struct ncr53c9x_softc *sc); 159129198Scognetstatic void esp_dma_reset(struct ncr53c9x_softc *sc); 160129198Scognetstatic int esp_dma_intr(struct ncr53c9x_softc *sc); 161164250Srustatic int esp_dma_setup(struct ncr53c9x_softc *sc, void **addr, 162129198Scognet size_t *len, int datain, size_t *dmasize); 163129198Scognetstatic void esp_dma_go(struct ncr53c9x_softc *sc); 164138413Scognetstatic void esp_dma_stop(struct ncr53c9x_softc *sc); 165138413Scognetstatic int esp_dma_isactive(struct ncr53c9x_softc *sc); 166138413Scognetstatic int espattach(struct esp_softc *esc, 167144760Scognet const struct ncr53c9x_glue *gluep); 168129198Scognetstatic int espdetach(struct esp_softc *esc); 169129198Scognet 170129198Scognetstatic const struct ncr53c9x_glue esp_sbus_glue = { 171129198Scognet esp_read_reg, 172129198Scognet esp_write_reg, 173129198Scognet esp_dma_isintr, 174129198Scognet esp_dma_reset, 175129198Scognet esp_dma_intr, 176129198Scognet esp_dma_setup, 177129198Scognet esp_dma_go, 178129198Scognet esp_dma_stop, 179129198Scognet esp_dma_isactive, 180129198Scognet}; 181129198Scognet 182135641Scognetstatic int 183135641Scognetesp_probe(device_t dev) 184135641Scognet{ 185135641Scognet const char *name; 186135641Scognet 187132056Scognet name = ofw_bus_get_name(dev); 188132056Scognet if (strcmp("SUNW,fas", name) == 0) { 189129198Scognet device_set_desc(dev, "Sun FAS366 Fast-Wide SCSI"); 190129198Scognet return (BUS_PROBE_DEFAULT); 191129198Scognet } else if (strcmp("esp", name) == 0) { 192129198Scognet device_set_desc(dev, "Sun ESP SCSI/Sun FAS Fast-SCSI"); 193129198Scognet return (BUS_PROBE_DEFAULT); 194129198Scognet } 195129198Scognet 196129198Scognet return (ENXIO); 197129198Scognet} 198129198Scognet 199129198Scognetstatic int 200129198Scognetesp_sbus_attach(device_t dev) 201129198Scognet{ 202129198Scognet struct esp_softc *esc; 203129198Scognet struct ncr53c9x_softc *sc; 204129198Scognet struct lsi64854_softc *lsc; 205129198Scognet device_t *children; 206129198Scognet int error, i, nchildren; 207129198Scognet 208156191Scognet esc = device_get_softc(dev); 209184728Sraj sc = &esc->sc_ncr53c9x; 210142570Scognet 211129198Scognet lsc = NULL; 212129198Scognet esc->sc_dev = dev; 213129198Scognet sc->sc_freq = sbus_get_clockfreq(dev); 214129198Scognet 215129198Scognet if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") == 0) { 216129198Scognet /* 217129198Scognet * Allocate space for DMA, in SUNW,fas there are no 218129198Scognet * separate DMA devices. 219129198Scognet */ 220129198Scognet lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF, 221129198Scognet M_NOWAIT | M_ZERO); 222129198Scognet if (lsc == NULL) { 223129198Scognet device_printf(dev, "out of memory (lsi64854_softc)\n"); 224129198Scognet return (ENOMEM); 225129198Scognet } 226129198Scognet esc->sc_dma = lsc; 227169756Scognet 228169756Scognet /* 229129198Scognet * SUNW,fas have 2 register spaces: DMA (lsi64854) and 230129198Scognet * SCSI core (ncr53c9x). 231129198Scognet */ 232129198Scognet 233129198Scognet /* Allocate DMA registers. */ 234129198Scognet i = 0; 235129198Scognet if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 236129198Scognet &i, RF_ACTIVE)) == NULL) { 237129198Scognet device_printf(dev, "cannot allocate DMA registers\n"); 238129198Scognet error = ENXIO; 239129198Scognet goto fail_sbus_lsc; 240129198Scognet } 241129198Scognet 242129198Scognet /* Create a parent DMA tag based on this bus. */ 243129198Scognet error = bus_dma_tag_create( 244129198Scognet bus_get_dma_tag(dev), /* parent */ 245129198Scognet 1, 0, /* alignment, boundary */ 246129198Scognet BUS_SPACE_MAXADDR, /* lowaddr */ 247129198Scognet BUS_SPACE_MAXADDR, /* highaddr */ 248129198Scognet NULL, NULL, /* filter, filterarg */ 249129198Scognet BUS_SPACE_MAXSIZE, /* maxsize */ 250129198Scognet BUS_SPACE_UNRESTRICTED, /* nsegments */ 251129198Scognet BUS_SPACE_MAXSIZE, /* maxsegsize */ 252129198Scognet 0, /* flags */ 253129198Scognet NULL, NULL, /* no locking */ 254171620Scognet &lsc->sc_parent_dmat); 255171620Scognet if (error != 0) { 256129198Scognet device_printf(dev, "cannot allocate parent DMA tag\n"); 257129198Scognet goto fail_sbus_lres; 258129198Scognet } 259129198Scognet 260129198Scognet i = sbus_get_burstsz(dev); 261129198Scognet 262171620Scognet#ifdef ESP_SBUS_DEBUG 263171620Scognet printf("%s: burst 0x%x\n", __func__, i); 264129198Scognet#endif 265129198Scognet 266129198Scognet lsc->sc_burst = (i & SBUS_BURST_32) ? 32 : 267129198Scognet (i & SBUS_BURST_16) ? 16 : 0; 268129198Scognet 269129198Scognet lsc->sc_channel = L64854_CHANNEL_SCSI; 270129198Scognet lsc->sc_client = sc; 271129198Scognet lsc->sc_dev = dev; 272129198Scognet 273129198Scognet /* 274171620Scognet * Allocate SCSI core registers. 275171620Scognet */ 276129198Scognet i = 1; 277129198Scognet if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 278129198Scognet &i, RF_ACTIVE)) == NULL) { 279129198Scognet device_printf(dev, 280129198Scognet "cannot allocate SCSI core registers\n"); 281129198Scognet error = ENXIO; 282129198Scognet goto fail_sbus_lpdma; 283129198Scognet } 284129198Scognet } else { 285129198Scognet /* 286129198Scognet * Search accompanying DMA engine. It should have been 287129198Scognet * already attached otherwise there isn't much we can do. 288129198Scognet */ 289129198Scognet if (device_get_children(device_get_parent(dev), &children, 290129198Scognet &nchildren) != 0) { 291129198Scognet device_printf(dev, "cannot determine siblings\n"); 292129198Scognet return (ENXIO); 293129198Scognet } 294129198Scognet for (i = 0; i < nchildren; i++) { 295129198Scognet if (device_is_attached(children[i]) && 296129198Scognet sbus_get_slot(children[i]) == 297129198Scognet sbus_get_slot(dev) && 298129198Scognet strcmp(ofw_bus_get_name(children[i]), 299129198Scognet "dma") == 0) { 300129198Scognet /* XXX hackery */ 301129198Scognet esc->sc_dma = (struct lsi64854_softc *) 302129198Scognet device_get_softc(children[i]); 303129198Scognet break; 304129198Scognet } 305129198Scognet } 306129198Scognet free(children, M_TEMP); 307129198Scognet if (esc->sc_dma == NULL) { 308129198Scognet device_printf(dev, "cannot find DMA engine\n"); 309129198Scognet return (ENXIO); 310129198Scognet } 311129198Scognet esc->sc_dma->sc_client = sc; 312129198Scognet 313129198Scognet /* 314129198Scognet * Allocate SCSI core registers. 315129198Scognet */ 316129198Scognet i = 0; 317129198Scognet if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 318129198Scognet &i, RF_ACTIVE)) == NULL) { 319129198Scognet device_printf(dev, 320129198Scognet "cannot allocate SCSI core registers\n"); 321129198Scognet return (ENXIO); 322129198Scognet } 323129198Scognet } 324129198Scognet 325129198Scognet error = espattach(esc, &esp_sbus_glue); 326129198Scognet if (error != 0) { 327129198Scognet device_printf(dev, "espattach failed\n"); 328129198Scognet goto fail_sbus_eres; 329129198Scognet } 330129198Scognet 331129198Scognet return (0); 332129198Scognet 333129198Scognet fail_sbus_eres: 334158531Scognet bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 335158531Scognet esc->sc_res); 336158531Scognet if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0) 337158531Scognet return (error); 338129198Scognet fail_sbus_lpdma: 339129198Scognet bus_dma_tag_destroy(lsc->sc_parent_dmat); 340129198Scognet fail_sbus_lres: 341171620Scognet bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res), 342171620Scognet lsc->sc_res); 343171620Scognet fail_sbus_lsc: 344129198Scognet free(lsc, M_DEVBUF); 345129198Scognet return (error); 346129198Scognet} 347158531Scognet 348129198Scognetstatic int 349129198Scognetesp_sbus_detach(device_t dev) 350129198Scognet{ 351129198Scognet struct esp_softc *esc; 352129198Scognet struct lsi64854_softc *lsc; 353129198Scognet int error; 354129198Scognet 355129198Scognet esc = device_get_softc(dev); 356129198Scognet lsc = esc->sc_dma; 357129198Scognet 358129198Scognet error = espdetach(esc); 359129198Scognet if (error != 0) 360129198Scognet return (error); 361129198Scognet bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 362129198Scognet esc->sc_res); 363129198Scognet if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0) 364129198Scognet return (0); 365129198Scognet bus_dma_tag_destroy(lsc->sc_parent_dmat); 366129198Scognet bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res), 367129198Scognet lsc->sc_res); 368129198Scognet free(lsc, M_DEVBUF); 369129198Scognet 370129198Scognet return (0); 371129198Scognet} 372129198Scognet 373129198Scognetstatic int 374129198Scognetesp_dma_attach(device_t dev) 375129198Scognet{ 376129198Scognet struct esp_softc *esc; 377129198Scognet struct ncr53c9x_softc *sc; 378129198Scognet int error, i; 379129198Scognet 380129198Scognet esc = device_get_softc(dev); 381129198Scognet sc = &esc->sc_ncr53c9x; 382129198Scognet 383171620Scognet esc->sc_dev = dev; 384129198Scognet if (OF_getprop(ofw_bus_get_node(dev), "clock-frequency", 385171620Scognet &sc->sc_freq, sizeof(sc->sc_freq)) == -1) { 386171620Scognet printf("failed to query OFW for clock-frequency\n"); 387129198Scognet return (ENXIO); 388129198Scognet } 389129198Scognet 390129198Scognet /* XXX hackery */ 391129198Scognet esc->sc_dma = (struct lsi64854_softc *) 392129198Scognet device_get_softc(device_get_parent(dev)); 393129198Scognet esc->sc_dma->sc_client = sc; 394171620Scognet 395171620Scognet /* 396129198Scognet * Allocate SCSI core registers. 397129198Scognet */ 398129198Scognet i = 0; 399129198Scognet if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 400129198Scognet &i, RF_ACTIVE)) == NULL) { 401129198Scognet device_printf(dev, "cannot allocate SCSI core registers\n"); 402129198Scognet return (ENXIO); 403129198Scognet } 404129198Scognet 405129198Scognet error = espattach(esc, &esp_sbus_glue); 406129198Scognet if (error != 0) { 407129198Scognet device_printf(dev, "espattach failed\n"); 408129198Scognet goto fail_dma_eres; 409129198Scognet } 410129198Scognet 411129198Scognet return (0); 412129198Scognet 413129198Scognet fail_dma_eres: 414129198Scognet bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 415129198Scognet esc->sc_res); 416129198Scognet return (error); 417129198Scognet} 418129198Scognet 419129198Scognetstatic int 420129198Scognetesp_dma_detach(device_t dev) 421129198Scognet{ 422129198Scognet struct esp_softc *esc; 423164080Scognet int error; 424129198Scognet 425129198Scognet esc = device_get_softc(dev); 426129198Scognet 427129198Scognet error = espdetach(esc); 428129198Scognet if (error != 0) 429129198Scognet return (error); 430129198Scognet bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res), 431129198Scognet esc->sc_res); 432129198Scognet 433129198Scognet return (0); 434129198Scognet} 435129198Scognet 436129198Scognetstatic int 437129198Scognetesp_suspend(device_t dev) 438129198Scognet{ 439129198Scognet 440129198Scognet return (ENXIO); 441129198Scognet} 442129198Scognet 443129198Scognetstatic int 444129198Scognetesp_resume(device_t dev) 445129198Scognet{ 446129198Scognet 447129198Scognet return (ENXIO); 448129198Scognet} 449129198Scognet 450129198Scognetstatic int 451135641Scognetespattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep) 452129198Scognet{ 453171620Scognet struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 454171620Scognet unsigned int uid = 0; 455171620Scognet int error, i; 456171620Scognet 457129198Scognet NCR_LOCK_INIT(sc); 458129198Scognet 459129198Scognet sc->sc_id = OF_getscsinitid(esc->sc_dev); 460129198Scognet 461129198Scognet#ifdef ESP_SBUS_DEBUG 462129198Scognet device_printf(esc->sc_dev, "%s: sc_id %d, freq %d\n", 463129198Scognet __func__, sc->sc_id, sc->sc_freq); 464129198Scognet#endif 465129198Scognet 466129198Scognet /* 467129198Scognet * The `ESC' DMA chip must be reset before we can access 468129198Scognet * the ESP registers. 469129198Scognet */ 470129198Scognet if (esc->sc_dma->sc_rev == DMAREV_ESC) 471129198Scognet DMA_RESET(esc->sc_dma); 472129198Scognet 473129198Scognet /* 474129198Scognet * Set up glue for MI code early; we use some of it here. 475129198Scognet */ 476129198Scognet sc->sc_glue = gluep; 477129198Scognet 478129198Scognet /* gimme MHz */ 479129198Scognet sc->sc_freq /= 1000000; 480129198Scognet 481129198Scognet /* 482129198Scognet * XXX More of this should be in ncr53c9x_attach(), but 483129198Scognet * XXX should we really poke around the chip that much in 484129198Scognet * XXX the MI code? Think about this more... 485129198Scognet */ 486129198Scognet 487129198Scognet /* 488129198Scognet * Read the part-unique ID code of the SCSI chip. The contained 489129198Scognet * value is only valid if all of the following conditions are met: 490129198Scognet * - After power-up or chip reset. 491129198Scognet * - Before any value is written to this register. 492129198Scognet * - The NCRCFG2_FE bit is set. 493129198Scognet * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued. 494129198Scognet */ 495129198Scognet NCRCMD(sc, NCRCMD_RSTCHIP); 496175840Scognet NCRCMD(sc, NCRCMD_NOP); 497175840Scognet sc->sc_cfg2 = NCRCFG2_FE; 498194459Sthompsa NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 499129198Scognet NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA); 500129198Scognet uid = NCR_READ_REG(sc, NCR_UID); 501135641Scognet 502135641Scognet /* 503135641Scognet * It is necessary to try to load the 2nd config register here, 504129198Scognet * to find out what rev the esp chip is, else the ncr53c9x_reset 505135641Scognet * will not set up the defaults correctly. 506135641Scognet */ 507129198Scognet sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 508135641Scognet NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1); 509135641Scognet sc->sc_cfg2 = 0; 510135641Scognet NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 511135641Scognet sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE; 512135641Scognet NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 513135641Scognet 514135641Scognet if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) != 515129198Scognet (NCRCFG2_SCSI2 | NCRCFG2_RPE)) 516135641Scognet sc->sc_rev = NCR_VARIANT_ESP100; 517135641Scognet else { 518129198Scognet sc->sc_cfg2 = NCRCFG2_SCSI2; 519135641Scognet NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 520135641Scognet sc->sc_cfg3 = 0; 521137362Scognet NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 522147114Scognet sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK); 523147114Scognet NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 524147114Scognet if (NCR_READ_REG(sc, NCR_CFG3) != 525171620Scognet (NCRCFG3_CDB | NCRCFG3_FCLK)) 526170582Scognet sc->sc_rev = NCR_VARIANT_ESP100A; 527171620Scognet else { 528147114Scognet /* NCRCFG2_FE enables > 64K transfers. */ 529137362Scognet sc->sc_cfg2 |= NCRCFG2_FE; 530137362Scognet sc->sc_cfg3 = 0; 531152128Scognet NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 532152128Scognet if (sc->sc_freq <= 25) 533147114Scognet sc->sc_rev = NCR_VARIANT_ESP200; 534147114Scognet else { 535161105Scognet switch ((uid & 0xf8) >> 3) { 536161105Scognet case 0x00: 537147114Scognet sc->sc_rev = NCR_VARIANT_FAS100A; 538147114Scognet break; 539147114Scognet 540147114Scognet case 0x02: 541150867Scognet if ((uid & 0x07) == 0x02) 542150936Scognet sc->sc_rev = 543156191Scognet NCR_VARIANT_FAS216; 544166063Scognet else 545156191Scognet sc->sc_rev = 546156191Scognet NCR_VARIANT_FAS236; 547156191Scognet break; 548156191Scognet 549150867Scognet case 0x0a: 550129198Scognet sc->sc_rev = NCR_VARIANT_FAS366; 551129198Scognet break; 552129198Scognet 553129198Scognet default: 554129198Scognet /* 555 * We could just treat unknown chips 556 * as ESP200 but then we would most 557 * likely drive them out of specs. 558 */ 559 device_printf(esc->sc_dev, 560 "Unknown chip\n"); 561 error = ENXIO; 562 goto fail_lock; 563 } 564 } 565 } 566 } 567 568#ifdef ESP_SBUS_DEBUG 569 printf("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid); 570#endif 571 572 /* 573 * This is the value used to start sync negotiations 574 * Note that the NCR register "SYNCTP" is programmed 575 * in "clocks per byte", and has a minimum value of 4. 576 * The SCSI period used in negotiation is one-fourth 577 * of the time (in nanoseconds) needed to transfer one byte. 578 * Since the chip's clock is given in MHz, we have the following 579 * formula: 4 * period = (1000 / freq) * 4 580 */ 581 sc->sc_minsync = 1000 / sc->sc_freq; 582 583 /* 584 * Except for some variants the maximum transfer size is 64k. 585 */ 586 sc->sc_maxxfer = 64 * 1024; 587 sc->sc_maxoffset = 15; 588 sc->sc_extended_geom = 1; 589 590 /* 591 * Alas, we must now modify the value a bit, because it's 592 * only valid when we can switch on FASTCLK and FASTSCSI bits 593 * in the config register 3... 594 */ 595 switch (sc->sc_rev) { 596 case NCR_VARIANT_ESP100: 597 sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 598 sc->sc_minsync = 0; /* No synch on old chip? */ 599 break; 600 601 case NCR_VARIANT_ESP100A: 602 case NCR_VARIANT_ESP200: 603 sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 604 /* Min clocks/byte is 5 */ 605 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5); 606 break; 607 608 case NCR_VARIANT_FAS100A: 609 case NCR_VARIANT_FAS216: 610 case NCR_VARIANT_FAS236: 611 /* 612 * The onboard SCSI chips in Sun Ultra 1 are actually 613 * documented to be NCR53C9X which use NCRCFG3_FCLK and 614 * NCRCFG3_FSCSI. BSD/OS however probes these chips as 615 * FAS100A and uses NCRF9XCFG3_FCLK and NCRF9XCFG3_FSCSI 616 * instead which seems to be correct as otherwise sync 617 * negotiation just doesn't work. Using NCRF9XCFG3_FCLK 618 * and NCRF9XCFG3_FSCSI with these chips in fact also 619 * yields Fast-SCSI speed. 620 */ 621 sc->sc_features = NCR_F_FASTSCSI; 622 sc->sc_cfg3 = NCRF9XCFG3_FCLK; 623 sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI; 624 sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; 625 sc->sc_maxxfer = 16 * 1024 * 1024; 626 break; 627 628 case NCR_VARIANT_FAS366: 629 sc->sc_maxwidth = MSG_EXT_WDTR_BUS_16_BIT; 630 sc->sc_maxxfer = 16 * 1024 * 1024; 631 break; 632 } 633 634 /* 635 * Given that we allocate resources based on sc->sc_maxxfer it doesn't 636 * make sense to supply a value higher than the maximum actually used. 637 */ 638 sc->sc_maxxfer = min(sc->sc_maxxfer, MAXPHYS); 639 640 /* Attach the DMA engine. */ 641 error = lsi64854_attach(esc->sc_dma); 642 if (error != 0) { 643 device_printf(esc->sc_dev, "lsi64854_attach failed\n"); 644 goto fail_lock; 645 } 646 647 /* Establish interrupt channel. */ 648 i = 0; 649 if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ, 650 &i, RF_SHAREABLE|RF_ACTIVE)) == NULL) { 651 device_printf(esc->sc_dev, "cannot allocate interrupt\n"); 652 goto fail_lsi; 653 } 654 if (bus_setup_intr(esc->sc_dev, esc->sc_irqres, 655 INTR_MPSAFE | INTR_TYPE_CAM, NULL, ncr53c9x_intr, sc, 656 &esc->sc_irq)) { 657 device_printf(esc->sc_dev, "cannot set up interrupt\n"); 658 error = ENXIO; 659 goto fail_ires; 660 } 661 662 /* Turn on target selection using the `DMA' method. */ 663 if (sc->sc_rev != NCR_VARIANT_FAS366) 664 sc->sc_features |= NCR_F_DMASELECT; 665 666 /* Do the common parts of attachment. */ 667 sc->sc_dev = esc->sc_dev; 668 error = ncr53c9x_attach(sc); 669 if (error != 0) { 670 device_printf(esc->sc_dev, "ncr53c9x_attach failed\n"); 671 goto fail_intr; 672 } 673 674 return (0); 675 676 fail_intr: 677 bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq); 678 fail_ires: 679 bus_release_resource(esc->sc_dev, SYS_RES_IRQ, 680 rman_get_rid(esc->sc_irqres), esc->sc_irqres); 681 fail_lsi: 682 lsi64854_detach(esc->sc_dma); 683 fail_lock: 684 NCR_LOCK_DESTROY(sc); 685 return (error); 686} 687 688static int 689espdetach(struct esp_softc *esc) 690{ 691 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 692 int error; 693 694 bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq); 695 error = ncr53c9x_detach(sc); 696 if (error != 0) 697 return (error); 698 error = lsi64854_detach(esc->sc_dma); 699 if (error != 0) 700 return (error); 701 NCR_LOCK_DESTROY(sc); 702 bus_release_resource(esc->sc_dev, SYS_RES_IRQ, 703 rman_get_rid(esc->sc_irqres), esc->sc_irqres); 704 705 return (0); 706} 707 708/* 709 * Glue functions 710 */ 711 712#ifdef ESP_SBUS_DEBUG 713static int esp_sbus_debug = 0; 714 715static const struct { 716 const char *r_name; 717 int r_flag; 718} const esp__read_regnames [] = { 719 { "TCL", 0}, /* 0/00 */ 720 { "TCM", 0}, /* 1/04 */ 721 { "FIFO", 0}, /* 2/08 */ 722 { "CMD", 0}, /* 3/0c */ 723 { "STAT", 0}, /* 4/10 */ 724 { "INTR", 0}, /* 5/14 */ 725 { "STEP", 0}, /* 6/18 */ 726 { "FFLAGS", 1}, /* 7/1c */ 727 { "CFG1", 1}, /* 8/20 */ 728 { "STAT2", 0}, /* 9/24 */ 729 { "CFG4", 1}, /* a/28 */ 730 { "CFG2", 1}, /* b/2c */ 731 { "CFG3", 1}, /* c/30 */ 732 { "-none", 1}, /* d/34 */ 733 { "TCH", 1}, /* e/38 */ 734 { "TCX", 1}, /* f/3c */ 735}; 736 737static const const struct { 738 const char *r_name; 739 int r_flag; 740} const esp__write_regnames[] = { 741 { "TCL", 1}, /* 0/00 */ 742 { "TCM", 1}, /* 1/04 */ 743 { "FIFO", 0}, /* 2/08 */ 744 { "CMD", 0}, /* 3/0c */ 745 { "SELID", 1}, /* 4/10 */ 746 { "TIMEOUT", 1}, /* 5/14 */ 747 { "SYNCTP", 1}, /* 6/18 */ 748 { "SYNCOFF", 1}, /* 7/1c */ 749 { "CFG1", 1}, /* 8/20 */ 750 { "CCF", 1}, /* 9/24 */ 751 { "TEST", 1}, /* a/28 */ 752 { "CFG2", 1}, /* b/2c */ 753 { "CFG3", 1}, /* c/30 */ 754 { "-none", 1}, /* d/34 */ 755 { "TCH", 1}, /* e/38 */ 756 { "TCX", 1}, /* f/3c */ 757}; 758#endif 759 760static uint8_t 761esp_read_reg(struct ncr53c9x_softc *sc, int reg) 762{ 763 struct esp_softc *esc = (struct esp_softc *)sc; 764 uint8_t v; 765 766 v = bus_read_1(esc->sc_res, reg * 4); 767 768#ifdef ESP_SBUS_DEBUG 769 if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag) 770 printf("RD:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ? 771 esp__read_regnames[reg].r_name : "<***>", v); 772#endif 773 774 return (v); 775} 776 777static void 778esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v) 779{ 780 struct esp_softc *esc = (struct esp_softc *)sc; 781 782#ifdef ESP_SBUS_DEBUG 783 if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag) 784 printf("WR:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ? 785 esp__write_regnames[reg].r_name : "<***>", v); 786#endif 787 788 bus_write_1(esc->sc_res, reg * 4, v); 789} 790 791static int 792esp_dma_isintr(struct ncr53c9x_softc *sc) 793{ 794 struct esp_softc *esc = (struct esp_softc *)sc; 795 796 return (DMA_ISINTR(esc->sc_dma)); 797} 798 799static void 800esp_dma_reset(struct ncr53c9x_softc *sc) 801{ 802 struct esp_softc *esc = (struct esp_softc *)sc; 803 804 DMA_RESET(esc->sc_dma); 805} 806 807static int 808esp_dma_intr(struct ncr53c9x_softc *sc) 809{ 810 struct esp_softc *esc = (struct esp_softc *)sc; 811 812 return (DMA_INTR(esc->sc_dma)); 813} 814 815static int 816esp_dma_setup(struct ncr53c9x_softc *sc, void **addr, size_t *len, 817 int datain, size_t *dmasize) 818{ 819 struct esp_softc *esc = (struct esp_softc *)sc; 820 821 return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize)); 822} 823 824static void 825esp_dma_go(struct ncr53c9x_softc *sc) 826{ 827 struct esp_softc *esc = (struct esp_softc *)sc; 828 829 DMA_GO(esc->sc_dma); 830} 831 832static void 833esp_dma_stop(struct ncr53c9x_softc *sc) 834{ 835 struct esp_softc *esc = (struct esp_softc *)sc; 836 837 L64854_SCSR(esc->sc_dma, L64854_GCSR(esc->sc_dma) & ~D_EN_DMA); 838} 839 840static int 841esp_dma_isactive(struct ncr53c9x_softc *sc) 842{ 843 struct esp_softc *esc = (struct esp_softc *)sc; 844 845 return (DMA_ISACTIVE(esc->sc_dma)); 846} 847