void esp_shutdownhook(void *arg) { struct ncr53c9x_softc *sc = arg; NCRCMD(sc, NCRCMD_RSTSCSI); }
int esp_activate(struct device *self, int act) { struct ncr53c9x_softc *sc = self; int rv = 0; switch (act) { case DVACT_POWERDOWN: rv = config_activate_children(self, act); NCRCMD(sc, NCRCMD_RSTSCSI); break; default: rv = config_activate_children(self, act); break; } return (rv); }
static int espattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep) { struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; unsigned int uid = 0; int error, i; NCR_LOCK_INIT(sc); /* Attach the DMA engine. */ error = lsi64854_attach(esc->sc_dma); if (error != 0) { device_printf(esc->sc_dev, "lsi64854_attach failed\n"); goto fail_lock; } sc->sc_id = OF_getscsinitid(esc->sc_dev); #ifdef ESP_SBUS_DEBUG device_printf(esc->sc_dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id, sc->sc_freq); #endif /* * The `ESC' DMA chip must be reset before we can access * the ESP registers. */ if (esc->sc_dma->sc_rev == DMAREV_ESC) DMA_RESET(esc->sc_dma); /* * Set up glue for MI code early; we use some of it here. */ sc->sc_glue = gluep; /* gimme MHz */ sc->sc_freq /= 1000000; /* * XXX More of this should be in ncr53c9x_attach(), but * XXX should we really poke around the chip that much in * XXX the MI code? Think about this more... */ /* * Read the part-unique ID code of the SCSI chip. The contained * value is only valid if all of the following conditions are met: * - After power-up or chip reset. * - Before any value is written to this register. * - The NCRCFG2_FE bit is set. * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued. */ NCRCMD(sc, NCRCMD_RSTCHIP); NCRCMD(sc, NCRCMD_NOP); sc->sc_cfg2 = NCRCFG2_FE; NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA); uid = NCR_READ_REG(sc, NCR_UID); /* * It is necessary to try to load the 2nd config register here, * to find out what rev the esp chip is, else the ncr53c9x_reset * will not set up the defaults correctly. */ sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1); sc->sc_cfg2 = 0; NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE; NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) != (NCRCFG2_SCSI2 | NCRCFG2_RPE)) { sc->sc_rev = NCR_VARIANT_ESP100; } else { sc->sc_cfg2 = NCRCFG2_SCSI2; NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); sc->sc_cfg3 = 0; NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK); NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); if (NCR_READ_REG(sc, NCR_CFG3) != (NCRCFG3_CDB | NCRCFG3_FCLK)) { sc->sc_rev = NCR_VARIANT_ESP100A; } else { /* NCRCFG2_FE enables > 64K transfers. */ sc->sc_cfg2 |= NCRCFG2_FE; sc->sc_cfg3 = 0; NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); if (sc->sc_freq <= 25) sc->sc_rev = NCR_VARIANT_ESP200; else { switch ((uid & 0xf8) >> 3) { case 0x00: sc->sc_rev = NCR_VARIANT_FAS100A; break; case 0x02: if ((uid & 0x07) == 0x02) sc->sc_rev = NCR_VARIANT_FAS216; else sc->sc_rev = NCR_VARIANT_FAS236; break; case 0x0a: sc->sc_rev = NCR_VARIANT_FAS366; break; default: /* * We could just treat unknown chips * as ESP200 but then we would most * likely drive them out of specs. */ device_printf(esc->sc_dev, "Unknown chip\n"); goto fail_lsi; } } } } #ifdef ESP_SBUS_DEBUG printf("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid); #endif /* * XXX minsync and maxxfer _should_ be set up in MI code, * XXX but it appears to have some dependency on what sort * XXX of DMA we're hooked up to, etc. */ /* * This is the value used to start sync negotiations * Note that the NCR register "SYNCTP" is programmed * in "clocks per byte", and has a minimum value of 4. * The SCSI period used in negotiation is one-fourth * of the time (in nanoseconds) needed to transfer one byte. * Since the chip's clock is given in MHz, we have the following * formula: 4 * period = (1000 / freq) * 4 */ sc->sc_minsync = 1000 / sc->sc_freq; sc->sc_maxoffset = 15; sc->sc_extended_geom = 1; /* * Alas, we must now modify the value a bit, because it's * only valid when can switch on FASTCLK and FASTSCSI bits * in config register 3... */ switch (sc->sc_rev) { case NCR_VARIANT_ESP100: sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; sc->sc_maxxfer = 64 * 1024; sc->sc_minsync = 0; /* No synch on old chip? */ break; case NCR_VARIANT_ESP100A: sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; sc->sc_maxxfer = 64 * 1024; /* Min clocks/byte is 5 */ sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5); break; case NCR_VARIANT_ESP200: sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; sc->sc_maxxfer = 16 * 1024 * 1024; /* Min clocks/byte is 5 */ sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5); break; case NCR_VARIANT_FAS100A: case NCR_VARIANT_FAS216: case NCR_VARIANT_FAS236: /* * The onboard SCSI chips in Sun Ultra 1 are actually * documented to be NCR53C9X which use NCRCFG3_FCLK and * NCRCFG3_FSCSI. BSD/OS however probes these chips as * FAS100A and uses NCRF9XCFG3_FCLK and NCRF9XCFG3_FSCSI * instead which seems to be correct as otherwise sync * negotiation just doesn't work. Using NCRF9XCFG3_FCLK * and NCRF9XCFG3_FSCSI with these chips in fact also * yields Fast-SCSI speed. */ sc->sc_features = NCR_F_FASTSCSI; sc->sc_cfg3 = NCRF9XCFG3_FCLK; sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI; sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT; sc->sc_maxxfer = 16 * 1024 * 1024; break; case NCR_VARIANT_FAS366: sc->sc_maxwidth = MSG_EXT_WDTR_BUS_16_BIT; sc->sc_maxxfer = 16 * 1024 * 1024; break; } /* Establish interrupt channel. */ i = 0; if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ, &i, RF_SHAREABLE|RF_ACTIVE)) == NULL) { device_printf(esc->sc_dev, "cannot allocate interrupt\n"); goto fail_lsi; } if (bus_setup_intr(esc->sc_dev, esc->sc_irqres, INTR_MPSAFE | INTR_TYPE_CAM, NULL, ncr53c9x_intr, sc, &esc->sc_irq)) { device_printf(esc->sc_dev, "cannot set up interrupt\n"); error = ENXIO; goto fail_ires; } /* Turn on target selection using the `DMA' method. */ if (sc->sc_rev != NCR_VARIANT_FAS366) sc->sc_features |= NCR_F_DMASELECT; /* Do the common parts of attachment. */ sc->sc_dev = esc->sc_dev; error = ncr53c9x_attach(sc); if (error != 0) { device_printf(esc->sc_dev, "ncr53c9x_attach failed\n"); goto fail_intr; } return (0); fail_intr: bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq); fail_ires: bus_release_resource(esc->sc_dev, SYS_RES_IRQ, rman_get_rid(esc->sc_irqres), esc->sc_irqres); fail_lsi: lsi64854_detach(esc->sc_dma); fail_lock: NCR_LOCK_DESTROY(sc); return (error); }