Annotation of sys/dev/sbus/esp_sbus.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: esp_sbus.c,v 1.20 2007/04/10 17:47:55 miod Exp $ */
! 2: /* $NetBSD: esp_sbus.c,v 1.14 2001/04/25 17:53:37 bouyer Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
! 10: * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
! 11: *
! 12: * Redistribution and use in source and binary forms, with or without
! 13: * modification, are permitted provided that the following conditions
! 14: * are met:
! 15: * 1. Redistributions of source code must retain the above copyright
! 16: * notice, this list of conditions and the following disclaimer.
! 17: * 2. Redistributions in binary form must reproduce the above copyright
! 18: * notice, this list of conditions and the following disclaimer in the
! 19: * documentation and/or other materials provided with the distribution.
! 20: * 3. All advertising materials mentioning features or use of this software
! 21: * must display the following acknowledgement:
! 22: * This product includes software developed by the NetBSD
! 23: * Foundation, Inc. and its contributors.
! 24: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 25: * contributors may be used to endorse or promote products derived
! 26: * from this software without specific prior written permission.
! 27: *
! 28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 38: * POSSIBILITY OF SUCH DAMAGE.
! 39: */
! 40:
! 41: #include <sys/types.h>
! 42: #include <sys/param.h>
! 43: #include <sys/systm.h>
! 44: #include <sys/device.h>
! 45: #include <sys/buf.h>
! 46: #include <sys/malloc.h>
! 47:
! 48: #include <scsi/scsi_all.h>
! 49: #include <scsi/scsiconf.h>
! 50: #include <scsi/scsi_message.h>
! 51:
! 52: #include <machine/bus.h>
! 53: #include <machine/intr.h>
! 54: #include <machine/autoconf.h>
! 55:
! 56: #include <dev/ic/lsi64854reg.h>
! 57: #include <dev/ic/lsi64854var.h>
! 58:
! 59: #include <dev/ic/ncr53c9xreg.h>
! 60: #include <dev/ic/ncr53c9xvar.h>
! 61:
! 62: #include <dev/sbus/sbusvar.h>
! 63:
! 64: struct scsi_adapter esp_switch = {
! 65: ncr53c9x_scsi_cmd,
! 66: minphys, /* no max at this level; handled by DMA code */
! 67: NULL,
! 68: NULL,
! 69: };
! 70:
! 71: struct scsi_device esp_dev = {
! 72: NULL, /* Use default error handler */
! 73: NULL, /* have a queue, served by this */
! 74: NULL, /* have no async handler */
! 75: NULL, /* Use default 'done' routine */
! 76: };
! 77:
! 78: /* #define ESP_SBUS_DEBUG */
! 79:
! 80: static int esp_unit_offset;
! 81:
! 82: struct esp_softc {
! 83: struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */
! 84:
! 85: bus_space_tag_t sc_bustag;
! 86: bus_dma_tag_t sc_dmatag;
! 87:
! 88: bus_space_handle_t sc_reg; /* the registers */
! 89: struct lsi64854_softc *sc_dma; /* pointer to my dma */
! 90:
! 91: int sc_pri; /* SBUS priority */
! 92: };
! 93:
! 94: void espattach_sbus(struct device *, struct device *, void *);
! 95: void espattach_dma(struct device *, struct device *, void *);
! 96: int espmatch_sbus(struct device *, void *, void *);
! 97:
! 98:
! 99: /* Linkup to the rest of the kernel */
! 100: struct cfattach esp_sbus_ca = {
! 101: sizeof(struct esp_softc), espmatch_sbus, espattach_sbus
! 102: };
! 103: struct cfattach esp_dma_ca = {
! 104: sizeof(struct esp_softc), espmatch_sbus, espattach_dma
! 105: };
! 106:
! 107: /*
! 108: * Functions and the switch for the MI code.
! 109: */
! 110: static u_char esp_read_reg(struct ncr53c9x_softc *, int);
! 111: static void esp_write_reg(struct ncr53c9x_softc *, int, u_char);
! 112: static u_char esp_rdreg1(struct ncr53c9x_softc *, int);
! 113: static void esp_wrreg1(struct ncr53c9x_softc *, int, u_char);
! 114: static int esp_dma_isintr(struct ncr53c9x_softc *);
! 115: static void esp_dma_reset(struct ncr53c9x_softc *);
! 116: static int esp_dma_intr(struct ncr53c9x_softc *);
! 117: static int esp_dma_setup(struct ncr53c9x_softc *, caddr_t *,
! 118: size_t *, int, size_t *);
! 119: static void esp_dma_go(struct ncr53c9x_softc *);
! 120: static void esp_dma_stop(struct ncr53c9x_softc *);
! 121: static int esp_dma_isactive(struct ncr53c9x_softc *);
! 122:
! 123: static struct ncr53c9x_glue esp_sbus_glue = {
! 124: esp_read_reg,
! 125: esp_write_reg,
! 126: esp_dma_isintr,
! 127: esp_dma_reset,
! 128: esp_dma_intr,
! 129: esp_dma_setup,
! 130: esp_dma_go,
! 131: esp_dma_stop,
! 132: esp_dma_isactive,
! 133: NULL, /* gl_clear_latched_intr */
! 134: };
! 135:
! 136: static struct ncr53c9x_glue esp_sbus_glue1 = {
! 137: esp_rdreg1,
! 138: esp_wrreg1,
! 139: esp_dma_isintr,
! 140: esp_dma_reset,
! 141: esp_dma_intr,
! 142: esp_dma_setup,
! 143: esp_dma_go,
! 144: esp_dma_stop,
! 145: esp_dma_isactive,
! 146: NULL, /* gl_clear_latched_intr */
! 147: };
! 148:
! 149: static void espattach(struct esp_softc *, struct ncr53c9x_glue *);
! 150:
! 151: int
! 152: espmatch_sbus(struct device *parent, void *vcf, void *aux)
! 153: {
! 154: struct cfdata *cf = vcf;
! 155: int rv;
! 156: struct sbus_attach_args *sa = aux;
! 157:
! 158: if (strcmp("SUNW,fas", sa->sa_name) == 0)
! 159: return 1;
! 160:
! 161: rv = (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0 ||
! 162: strcmp("ptscII", sa->sa_name) == 0);
! 163: return (rv);
! 164: }
! 165:
! 166: void
! 167: espattach_sbus(struct device *parent, struct device *self, void *aux)
! 168: {
! 169: struct esp_softc *esc = (void *)self;
! 170: struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
! 171: struct sbus_attach_args *sa = aux;
! 172: struct lsi64854_softc *lsc;
! 173: int burst, sbusburst;
! 174:
! 175: esc->sc_bustag = sa->sa_bustag;
! 176: esc->sc_dmatag = sa->sa_dmatag;
! 177:
! 178: sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
! 179: sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
! 180: if (sc->sc_freq < 0)
! 181: sc->sc_freq = sa->sa_frequency;
! 182:
! 183: #ifdef ESP_SBUS_DEBUG
! 184: printf("%s: espattach_sbus: sc_id %d, freq %d\n",
! 185: self->dv_xname, sc->sc_id, sc->sc_freq);
! 186: #endif
! 187:
! 188: if (strcmp("SUNW,fas", sa->sa_name) == 0) {
! 189: /*
! 190: * offset searches for other esp/dma devices.
! 191: */
! 192: esp_unit_offset++;
! 193:
! 194: /*
! 195: * fas has 2 register spaces: dma(lsi64854) and SCSI core (ncr53c9x)
! 196: */
! 197: if (sa->sa_nreg != 2) {
! 198: printf("%s: %d register spaces\n", self->dv_xname, sa->sa_nreg);
! 199: return;
! 200: }
! 201:
! 202: /*
! 203: * allocate space for dma, in SUNW,fas there are no separate
! 204: * dma device
! 205: */
! 206: lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF, M_NOWAIT);
! 207:
! 208: if (lsc == NULL) {
! 209: printf("%s: out of memory (lsi64854_softc)\n",
! 210: self->dv_xname);
! 211: return;
! 212: }
! 213: esc->sc_dma = lsc;
! 214:
! 215: lsc->sc_bustag = sa->sa_bustag;
! 216: lsc->sc_dmatag = sa->sa_dmatag;
! 217:
! 218: bcopy(sc->sc_dev.dv_xname, lsc->sc_dev.dv_xname,
! 219: sizeof (lsc->sc_dev.dv_xname));
! 220:
! 221: /* Map dma registers */
! 222: if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
! 223: sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
! 224: 0, 0, &lsc->sc_regs) != 0) {
! 225: printf("%s: cannot map dma registers\n", self->dv_xname);
! 226: return;
! 227: }
! 228:
! 229: /*
! 230: * XXX is this common(from bpp.c), the same in dma_sbus...etc.
! 231: *
! 232: * Get transfer burst size from PROM and plug it into the
! 233: * controller registers. This is needed on the Sun4m; do
! 234: * others need it too?
! 235: */
! 236: sbusburst = ((struct sbus_softc *)parent)->sc_burst;
! 237: if (sbusburst == 0)
! 238: sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
! 239:
! 240: burst = getpropint(sa->sa_node, "burst-sizes", -1);
! 241:
! 242: #ifdef ESP_SBUS_DEBUG
! 243: printf("espattach_sbus: burst 0x%x, sbus 0x%x\n",
! 244: burst, sbusburst);
! 245: #endif
! 246:
! 247: if (burst == -1)
! 248: /* take SBus burst sizes */
! 249: burst = sbusburst;
! 250:
! 251: /* Clamp at parent's burst sizes */
! 252: burst &= sbusburst;
! 253: lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
! 254: (burst & SBUS_BURST_16) ? 16 : 0;
! 255:
! 256: lsc->sc_channel = L64854_CHANNEL_SCSI;
! 257: lsc->sc_client = sc;
! 258:
! 259: lsi64854_attach(lsc);
! 260:
! 261: /*
! 262: * map SCSI core registers
! 263: */
! 264: if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
! 265: sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size,
! 266: 0, 0, &esc->sc_reg) != 0) {
! 267: printf("%s: cannot map scsi core registers\n",
! 268: self->dv_xname);
! 269: return;
! 270: }
! 271:
! 272: if (sa->sa_nintr == 0) {
! 273: printf("%s: no interrupt property\n", self->dv_xname);
! 274: return;
! 275: }
! 276:
! 277: esc->sc_pri = sa->sa_pri;
! 278:
! 279: printf("%s", self->dv_xname);
! 280: espattach(esc, &esp_sbus_glue);
! 281:
! 282: return;
! 283: }
! 284:
! 285: /*
! 286: * Find the DMA by poking around the dma device structures
! 287: *
! 288: * What happens here is that if the dma driver has not been
! 289: * configured, then this returns a NULL pointer. Then when the
! 290: * dma actually gets configured, it does the opposing test, and
! 291: * if the sc->sc_esp field in its softc is NULL, then tries to
! 292: * find the matching esp driver.
! 293: */
! 294: esc->sc_dma = (struct lsi64854_softc *)
! 295: getdevunit("dma", sc->sc_dev.dv_unit - esp_unit_offset);
! 296:
! 297: /*
! 298: * and a back pointer to us, for DMA
! 299: */
! 300: if (esc->sc_dma)
! 301: esc->sc_dma->sc_client = sc;
! 302: else {
! 303: printf("\n");
! 304: panic("espattach: no dma found");
! 305: }
! 306:
! 307: /*
! 308: * The `ESC' DMA chip must be reset before we can access
! 309: * the esp registers.
! 310: */
! 311: if (esc->sc_dma->sc_rev == DMAREV_ESC)
! 312: DMA_RESET(esc->sc_dma);
! 313:
! 314: /*
! 315: * Map my registers in, if they aren't already in virtual
! 316: * address space.
! 317: */
! 318: if (sa->sa_npromvaddrs) {
! 319: if (bus_space_map(sa->sa_bustag, sa->sa_promvaddrs[0],
! 320: sa->sa_size, BUS_SPACE_MAP_PROMADDRESS,
! 321: &esc->sc_reg) != 0) {
! 322: printf("%s @ sbus: cannot map registers\n",
! 323: self->dv_xname);
! 324: return;
! 325: }
! 326: } else {
! 327: if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
! 328: sa->sa_offset, sa->sa_size, 0, 0, &esc->sc_reg) != 0) {
! 329: printf("%s @ sbus: cannot map registers\n",
! 330: self->dv_xname);
! 331: return;
! 332: }
! 333: }
! 334:
! 335: if (sa->sa_nintr == 0) {
! 336: /*
! 337: * No interrupt properties: we quit; this might
! 338: * happen on e.g. a Sparc X terminal.
! 339: */
! 340: printf("\n%s: no interrupt property\n", self->dv_xname);
! 341: return;
! 342: }
! 343:
! 344: esc->sc_pri = sa->sa_pri;
! 345:
! 346: if (strcmp("ptscII", sa->sa_name) == 0) {
! 347: espattach(esc, &esp_sbus_glue1);
! 348: } else {
! 349: espattach(esc, &esp_sbus_glue);
! 350: }
! 351: }
! 352:
! 353: void
! 354: espattach_dma(struct device *parent, struct device *self, void *aux)
! 355: {
! 356: struct esp_softc *esc = (void *)self;
! 357: struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
! 358: struct sbus_attach_args *sa = aux;
! 359:
! 360: if (strcmp("ptscII", sa->sa_name) == 0) {
! 361: return;
! 362: }
! 363:
! 364: esc->sc_bustag = sa->sa_bustag;
! 365: esc->sc_dmatag = sa->sa_dmatag;
! 366:
! 367: sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
! 368: sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
! 369:
! 370: esc->sc_dma = (struct lsi64854_softc *)parent;
! 371: esc->sc_dma->sc_client = sc;
! 372:
! 373: /*
! 374: * Map my registers in, if they aren't already in virtual
! 375: * address space.
! 376: */
! 377: if (sa->sa_npromvaddrs) {
! 378: if (bus_space_map(sa->sa_bustag, sa->sa_promvaddrs[0],
! 379: sa->sa_size /* ??? */, BUS_SPACE_MAP_PROMADDRESS,
! 380: &esc->sc_reg) != 0) {
! 381: printf("%s @ dma: cannot map registers\n",
! 382: self->dv_xname);
! 383: return;
! 384: }
! 385: } else {
! 386: if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset,
! 387: sa->sa_size, 0, 0, &esc->sc_reg) != 0) {
! 388: printf("%s @ dma: cannot map registers\n",
! 389: self->dv_xname);
! 390: return;
! 391: }
! 392: }
! 393:
! 394: if (sa->sa_nintr == 0) {
! 395: /*
! 396: * No interrupt properties: we quit; this might
! 397: * happen on e.g. a Sparc X terminal.
! 398: */
! 399: printf("\n%s: no interrupt property\n", self->dv_xname);
! 400: return;
! 401: }
! 402:
! 403: esc->sc_pri = sa->sa_pri;
! 404:
! 405: espattach(esc, &esp_sbus_glue);
! 406: }
! 407:
! 408:
! 409: /*
! 410: * Attach this instance, and then all the sub-devices
! 411: */
! 412: void
! 413: espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
! 414: {
! 415: struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
! 416: void *icookie;
! 417: unsigned int uid = 0;
! 418:
! 419: /*
! 420: * Set up glue for MI code early; we use some of it here.
! 421: */
! 422: sc->sc_glue = gluep;
! 423:
! 424: /* gimme MHz */
! 425: sc->sc_freq /= 1000000;
! 426:
! 427: /*
! 428: * XXX More of this should be in ncr53c9x_attach(), but
! 429: * XXX should we really poke around the chip that much in
! 430: * XXX the MI code? Think about this more...
! 431: */
! 432:
! 433: /*
! 434: * It is necessary to try to load the 2nd config register here,
! 435: * to find out what rev the esp chip is, else the ncr53c9x_reset
! 436: * will not set up the defaults correctly.
! 437: */
! 438: sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
! 439: sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
! 440: sc->sc_cfg3 = NCRCFG3_CDB;
! 441: NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
! 442:
! 443: if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
! 444: (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
! 445: sc->sc_rev = NCR_VARIANT_ESP100;
! 446: } else {
! 447: sc->sc_cfg2 = NCRCFG2_SCSI2;
! 448: NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
! 449: sc->sc_cfg3 = 0;
! 450: NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
! 451: sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
! 452: NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
! 453: if (NCR_READ_REG(sc, NCR_CFG3) !=
! 454: (NCRCFG3_CDB | NCRCFG3_FCLK)) {
! 455: sc->sc_rev = NCR_VARIANT_ESP100A;
! 456: } else {
! 457: /* NCRCFG2_FE enables > 64K transfers */
! 458: sc->sc_cfg2 |= NCRCFG2_FE;
! 459: sc->sc_cfg3 = 0;
! 460: NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
! 461: sc->sc_rev = NCR_VARIANT_ESP200;
! 462:
! 463: /* XXX spec says it's valid after power up or chip reset */
! 464: uid = NCR_READ_REG(sc, NCR_UID);
! 465: if (((uid & 0xf8) >> 3) == 0x0a) /* XXX */
! 466: sc->sc_rev = NCR_VARIANT_FAS366;
! 467: }
! 468: }
! 469:
! 470: #ifdef ESP_SBUS_DEBUG
! 471: printf("espattach: revision %d, uid 0x%x\n", sc->sc_rev, uid);
! 472: #endif
! 473:
! 474: /*
! 475: * XXX minsync and maxxfer _should_ be set up in MI code,
! 476: * XXX but it appears to have some dependency on what sort
! 477: * XXX of DMA we're hooked up to, etc.
! 478: */
! 479:
! 480: /*
! 481: * This is the value used to start sync negotiations
! 482: * Note that the NCR register "SYNCTP" is programmed
! 483: * in "clocks per byte", and has a minimum value of 4.
! 484: * The SCSI period used in negotiation is one-fourth
! 485: * of the time (in nanoseconds) needed to transfer one byte.
! 486: * Since the chip's clock is given in MHz, we have the following
! 487: * formula: 4 * period = (1000 / freq) * 4
! 488: */
! 489: sc->sc_minsync = 1000 / sc->sc_freq;
! 490:
! 491: /*
! 492: * Alas, we must now modify the value a bit, because it's
! 493: * only valid when can switch on FASTCLK and FASTSCSI bits
! 494: * in config register 3...
! 495: */
! 496: switch (sc->sc_rev) {
! 497: case NCR_VARIANT_ESP100:
! 498: sc->sc_maxxfer = 64 * 1024;
! 499: sc->sc_minsync = 0; /* No synch on old chip? */
! 500: break;
! 501:
! 502: case NCR_VARIANT_ESP100A:
! 503: sc->sc_maxxfer = 64 * 1024;
! 504: /* Min clocks/byte is 5 */
! 505: sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
! 506: break;
! 507:
! 508: case NCR_VARIANT_ESP200:
! 509: case NCR_VARIANT_FAS366:
! 510: sc->sc_maxxfer = 16 * 1024 * 1024;
! 511: /* XXX - do actually set FAST* bits */
! 512: break;
! 513: }
! 514:
! 515: /* Establish interrupt channel */
! 516: icookie = bus_intr_establish(esc->sc_bustag, esc->sc_pri, IPL_BIO, 0,
! 517: ncr53c9x_intr, sc, sc->sc_dev.dv_xname);
! 518:
! 519: /* Turn on target selection using the `dma' method */
! 520: if (sc->sc_rev != NCR_VARIANT_FAS366)
! 521: sc->sc_features |= NCR_F_DMASELECT;
! 522:
! 523: /* Do the common parts of attachment. */
! 524: ncr53c9x_attach(sc, &esp_switch, &esp_dev);
! 525: }
! 526:
! 527: /*
! 528: * Glue functions.
! 529: */
! 530:
! 531: #ifdef ESP_SBUS_DEBUG
! 532: int esp_sbus_debug = 0;
! 533:
! 534: static struct {
! 535: char *r_name;
! 536: int r_flag;
! 537: } esp__read_regnames [] = {
! 538: { "TCL", 0}, /* 0/00 */
! 539: { "TCM", 0}, /* 1/04 */
! 540: { "FIFO", 0}, /* 2/08 */
! 541: { "CMD", 0}, /* 3/0c */
! 542: { "STAT", 0}, /* 4/10 */
! 543: { "INTR", 0}, /* 5/14 */
! 544: { "STEP", 0}, /* 6/18 */
! 545: { "FFLAGS", 1}, /* 7/1c */
! 546: { "CFG1", 1}, /* 8/20 */
! 547: { "STAT2", 0}, /* 9/24 */
! 548: { "CFG4", 1}, /* a/28 */
! 549: { "CFG2", 1}, /* b/2c */
! 550: { "CFG3", 1}, /* c/30 */
! 551: { "-none", 1}, /* d/34 */
! 552: { "TCH", 1}, /* e/38 */
! 553: { "TCX", 1}, /* f/3c */
! 554: };
! 555:
! 556: static struct {
! 557: char *r_name;
! 558: int r_flag;
! 559: } esp__write_regnames[] = {
! 560: { "TCL", 1}, /* 0/00 */
! 561: { "TCM", 1}, /* 1/04 */
! 562: { "FIFO", 0}, /* 2/08 */
! 563: { "CMD", 0}, /* 3/0c */
! 564: { "SELID", 1}, /* 4/10 */
! 565: { "TIMEOUT", 1}, /* 5/14 */
! 566: { "SYNCTP", 1}, /* 6/18 */
! 567: { "SYNCOFF", 1}, /* 7/1c */
! 568: { "CFG1", 1}, /* 8/20 */
! 569: { "CCF", 1}, /* 9/24 */
! 570: { "TEST", 1}, /* a/28 */
! 571: { "CFG2", 1}, /* b/2c */
! 572: { "CFG3", 1}, /* c/30 */
! 573: { "-none", 1}, /* d/34 */
! 574: { "TCH", 1}, /* e/38 */
! 575: { "TCX", 1}, /* f/3c */
! 576: };
! 577: #endif
! 578:
! 579: u_char
! 580: esp_read_reg(struct ncr53c9x_softc *sc, int reg)
! 581: {
! 582: struct esp_softc *esc = (struct esp_softc *)sc;
! 583: u_char v;
! 584:
! 585: v = bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg * 4);
! 586: #ifdef ESP_SBUS_DEBUG
! 587: if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
! 588: printf("RD:%x <%s> %x\n", reg * 4,
! 589: ((unsigned)reg < 0x10) ? esp__read_regnames[reg].r_name : "<***>", v);
! 590: #endif
! 591: return v;
! 592: }
! 593:
! 594: void
! 595: esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v)
! 596: {
! 597: struct esp_softc *esc = (struct esp_softc *)sc;
! 598:
! 599: #ifdef ESP_SBUS_DEBUG
! 600: if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
! 601: printf("WR:%x <%s> %x\n", reg * 4,
! 602: ((unsigned)reg < 0x10) ? esp__write_regnames[reg].r_name : "<***>", v);
! 603: #endif
! 604: bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg * 4, v);
! 605: }
! 606:
! 607: u_char
! 608: esp_rdreg1(struct ncr53c9x_softc *sc, int reg)
! 609: {
! 610: struct esp_softc *esc = (struct esp_softc *)sc;
! 611:
! 612: return (bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg));
! 613: }
! 614:
! 615: void
! 616: esp_wrreg1(struct ncr53c9x_softc *sc, int reg, u_char v)
! 617: {
! 618: struct esp_softc *esc = (struct esp_softc *)sc;
! 619:
! 620: bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg, v);
! 621: }
! 622:
! 623: int
! 624: esp_dma_isintr(struct ncr53c9x_softc *sc)
! 625: {
! 626: struct esp_softc *esc = (struct esp_softc *)sc;
! 627:
! 628: return (DMA_ISINTR(esc->sc_dma));
! 629: }
! 630:
! 631: void
! 632: esp_dma_reset(struct ncr53c9x_softc *sc)
! 633: {
! 634: struct esp_softc *esc = (struct esp_softc *)sc;
! 635:
! 636: DMA_RESET(esc->sc_dma);
! 637: }
! 638:
! 639: int
! 640: esp_dma_intr(struct ncr53c9x_softc *sc)
! 641: {
! 642: struct esp_softc *esc = (struct esp_softc *)sc;
! 643:
! 644: return (DMA_INTR(esc->sc_dma));
! 645: }
! 646:
! 647: int
! 648: esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len,
! 649: int datain, size_t *dmasize)
! 650: {
! 651: struct esp_softc *esc = (struct esp_softc *)sc;
! 652:
! 653: return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
! 654: }
! 655:
! 656: void
! 657: esp_dma_go(struct ncr53c9x_softc *sc)
! 658: {
! 659: struct esp_softc *esc = (struct esp_softc *)sc;
! 660:
! 661: DMA_GO(esc->sc_dma);
! 662: }
! 663:
! 664: void
! 665: esp_dma_stop(struct ncr53c9x_softc *sc)
! 666: {
! 667: struct esp_softc *esc = (struct esp_softc *)sc;
! 668: u_int32_t csr;
! 669:
! 670: csr = L64854_GCSR(esc->sc_dma);
! 671: csr &= ~D_EN_DMA;
! 672: L64854_SCSR(esc->sc_dma, csr);
! 673: }
! 674:
! 675: int
! 676: esp_dma_isactive(struct ncr53c9x_softc *sc)
! 677: {
! 678: struct esp_softc *esc = (struct esp_softc *)sc;
! 679:
! 680: return (DMA_ISACTIVE(esc->sc_dma));
! 681: }
! 682:
! 683: #if defined(DDB) && defined(notyet)
! 684: #include <machine/db_machdep.h>
! 685: #include <ddb/db_output.h>
! 686:
! 687: void db_esp(db_expr_t, int, db_expr_t, char *);
! 688:
! 689: void
! 690: db_esp(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 691: {
! 692: struct ncr53c9x_softc *sc;
! 693: struct ncr53c9x_ecb *ecb;
! 694: struct ncr53c9x_linfo *li;
! 695: int u, t, i;
! 696:
! 697: for (u=0; u<10; u++) {
! 698: sc = (struct ncr53c9x_softc *)
! 699: getdevunit("esp", u);
! 700: if (!sc) continue;
! 701:
! 702: db_printf("esp%d: nexus %p phase %x prev %x dp %p dleft %lx ify %x\n",
! 703: u, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase,
! 704: sc->sc_dp, sc->sc_dleft, sc->sc_msgify);
! 705: db_printf("\tmsgout %x msgpriq %x msgin %x:%x:%x:%x:%x\n",
! 706: sc->sc_msgout, sc->sc_msgpriq, sc->sc_imess[0],
! 707: sc->sc_imess[1], sc->sc_imess[2], sc->sc_imess[3],
! 708: sc->sc_imess[0]);
! 709: db_printf("ready: ");
! 710: TAILQ_FOREACH(ecb, &sc->ready_list, chain) {
! 711: db_printf("ecb %p ", ecb);
! 712: if (ecb == TAILQ_NEXT(ecb, chain)) {
! 713: db_printf("\nWARNING: tailq loop on ecb %p", ecb);
! 714: break;
! 715: }
! 716: }
! 717: db_printf("\n");
! 718:
! 719: for (t=0; t<NCR_NTARG; t++) {
! 720: LIST_FOREACH(li, &sc->sc_tinfo[t].luns, link) {
! 721: db_printf("t%d lun %d untagged %p busy %d used %x\n",
! 722: t, (int)li->lun, li->untagged, li->busy,
! 723: li->used);
! 724: for (i=0; i<256; i++)
! 725: if ((ecb = li->queued[i])) {
! 726: db_printf("ecb %p tag %x\n", ecb, i);
! 727: }
! 728: }
! 729: }
! 730: }
! 731: }
! 732: #endif
! 733:
CVSweb