struct umass_scsi_softc * umass_scsi_setup(struct umass_softc *sc) { struct umass_scsi_softc *scbus; scbus = malloc(sizeof(*scbus), M_DEVBUF, M_WAITOK | M_ZERO); sc->bus = (struct umassbus_softc *)scbus; scsi_iopool_init(&scbus->sc_iopool, scbus, umass_io_get, umass_io_put); /* Fill in the link. */ scbus->sc_link.adapter_buswidth = 2; scbus->sc_link.adapter = &umass_scsi_switch; scbus->sc_link.adapter_softc = sc; scbus->sc_link.openings = 1; scbus->sc_link.quirks |= SDEV_ONLYBIG | sc->sc_busquirks; scbus->sc_link.pool = &scbus->sc_iopool; return (scbus); }
void vdsk_attach(struct device *parent, struct device *self, void *aux) { struct vdsk_softc *sc = (struct vdsk_softc *)self; struct cbus_attach_args *ca = aux; struct scsibus_attach_args saa; struct ldc_conn *lc; uint64_t sysino[2]; int err, s; int timeout; sc->sc_bustag = ca->ca_bustag; sc->sc_dmatag = ca->ca_dmatag; if (cbus_intr_map(ca->ca_node, ca->ca_tx_ino, &sysino[0]) || cbus_intr_map(ca->ca_node, ca->ca_rx_ino, &sysino[1])) { printf(": can't map interrupt\n"); return; } printf(": ivec 0x%lx, 0x%lx", sysino[0], sysino[1]); /* * Un-configure queues before registering interrupt handlers, * such that we dont get any stale LDC packets or events. */ hv_ldc_tx_qconf(ca->ca_id, 0, 0); hv_ldc_rx_qconf(ca->ca_id, 0, 0); sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sysino[0], IPL_BIO, 0, vdsk_tx_intr, sc, sc->sc_dv.dv_xname); sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sysino[1], IPL_BIO, 0, vdsk_rx_intr, sc, sc->sc_dv.dv_xname); if (sc->sc_tx_ih == NULL || sc->sc_rx_ih == NULL) { printf(", can't establish interrupt\n"); return; } lc = &sc->sc_lc; lc->lc_id = ca->ca_id; lc->lc_sc = sc; lc->lc_reset = vdsk_ldc_reset; lc->lc_start = vdsk_ldc_start; lc->lc_rx_data = vdsk_rx_data; lc->lc_txq = ldc_queue_alloc(sc->sc_dmatag, VDSK_TX_ENTRIES); if (lc->lc_txq == NULL) { printf(", can't allocate tx queue\n"); return; } lc->lc_rxq = ldc_queue_alloc(sc->sc_dmatag, VDSK_RX_ENTRIES); if (lc->lc_rxq == NULL) { printf(", can't allocate rx queue\n"); goto free_txqueue; } sc->sc_lm = ldc_map_alloc(sc->sc_dmatag, 2048); if (sc->sc_lm == NULL) { printf(", can't allocate LDC mapping table\n"); goto free_rxqueue; } err = hv_ldc_set_map_table(lc->lc_id, sc->sc_lm->lm_map->dm_segs[0].ds_addr, sc->sc_lm->lm_nentries); if (err != H_EOK) { printf("hv_ldc_set_map_table %d\n", err); goto free_map; } sc->sc_vd = vdsk_dring_alloc(sc->sc_dmatag, 32); if (sc->sc_vd == NULL) { printf(", can't allocate dring\n"); goto free_map; } sc->sc_vsd = malloc(32 * sizeof(*sc->sc_vsd), M_DEVBUF, M_NOWAIT); if (sc->sc_vsd == NULL) { printf(", can't allocate software ring\n"); goto free_dring; } sc->sc_lm->lm_slot[0].entry = sc->sc_vd->vd_map->dm_segs[0].ds_addr; sc->sc_lm->lm_slot[0].entry &= LDC_MTE_RA_MASK; sc->sc_lm->lm_slot[0].entry |= LDC_MTE_CPR | LDC_MTE_CPW; sc->sc_lm->lm_slot[0].entry |= LDC_MTE_R | LDC_MTE_W; sc->sc_lm->lm_next = 1; sc->sc_lm->lm_count = 1; err = hv_ldc_tx_qconf(lc->lc_id, lc->lc_txq->lq_map->dm_segs[0].ds_addr, lc->lc_txq->lq_nentries); if (err != H_EOK) printf("hv_ldc_tx_qconf %d\n", err); err = hv_ldc_rx_qconf(lc->lc_id, lc->lc_rxq->lq_map->dm_segs[0].ds_addr, lc->lc_rxq->lq_nentries); if (err != H_EOK) printf("hv_ldc_rx_qconf %d\n", err); cbus_intr_setenabled(sysino[0], INTR_ENABLED); cbus_intr_setenabled(sysino[1], INTR_ENABLED); ldc_send_vers(lc); printf("\n"); /* * Interrupts aren't enabled during autoconf, so poll for VIO * peer-to-peer hanshake completion. */ s = splbio(); timeout = 1000; do { if (vdsk_rx_intr(sc) && sc->sc_vio_state == VIO_ESTABLISHED) break; delay(1000); } while(--timeout > 0); splx(s); if (sc->sc_vio_state != VIO_ESTABLISHED) return; scsi_iopool_init(&sc->sc_iopool, sc, vdsk_io_get, vdsk_io_put); sc->sc_switch.scsi_cmd = vdsk_scsi_cmd; sc->sc_switch.scsi_minphys = scsi_minphys; sc->sc_switch.dev_probe = vdsk_dev_probe; sc->sc_switch.dev_free = vdsk_dev_free; sc->sc_link.adapter = &sc->sc_switch; sc->sc_link.adapter_softc = self; sc->sc_link.adapter_buswidth = 2; sc->sc_link.luns = 1; /* XXX slices should be presented as luns? */ sc->sc_link.adapter_target = 2; sc->sc_link.openings = sc->sc_vd->vd_nentries - 1; sc->sc_link.pool = &sc->sc_iopool; bzero(&saa, sizeof(saa)); saa.saa_sc_link = &sc->sc_link; config_found(self, &saa, scsiprint); return; free_dring: vdsk_dring_free(sc->sc_dmatag, sc->sc_vd); free_map: hv_ldc_set_map_table(lc->lc_id, 0, 0); ldc_map_free(sc->sc_dmatag, sc->sc_lm); free_rxqueue: ldc_queue_free(sc->sc_dmatag, lc->lc_rxq); free_txqueue: ldc_queue_free(sc->sc_dmatag, lc->lc_txq); }
void oosiop_attach(struct oosiop_softc *sc) { struct scsibus_attach_args saa; bus_size_t scrsize; bus_dma_segment_t seg; struct oosiop_cb *cb; int err, i, nseg; /* * Allocate DMA-safe memory for the script and map it. */ scrsize = round_page(sizeof(oosiop_script)); err = bus_dmamem_alloc(sc->sc_dmat, scrsize, PAGE_SIZE, 0, &seg, 1, &nseg, BUS_DMA_NOWAIT | BUS_DMA_ZERO); if (err) { printf(": failed to allocate script memory, err=%d\n", err); return; } err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, scrsize, (caddr_t *)&sc->sc_scr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT); if (err) { printf(": failed to map script memory, err=%d\n", err); return; } err = bus_dmamap_create(sc->sc_dmat, scrsize, 1, scrsize, 0, BUS_DMA_NOWAIT, &sc->sc_scrdma); if (err) { printf(": failed to create script map, err=%d\n", err); return; } err = bus_dmamap_load_raw(sc->sc_dmat, sc->sc_scrdma, &seg, nseg, scrsize, BUS_DMA_NOWAIT | BUS_DMA_WRITE); if (err) { printf(": failed to load script map, err=%d\n", err); return; } sc->sc_scrbase = sc->sc_scrdma->dm_segs[0].ds_addr; /* Initialize command block array */ TAILQ_INIT(&sc->sc_free_cb); TAILQ_INIT(&sc->sc_cbq); if (oosiop_alloc_cb(sc, OOSIOP_NCB) != 0) return; /* Use first cb to reselection msgin buffer */ cb = TAILQ_FIRST(&sc->sc_free_cb); sc->sc_reselbuf = cb->xferdma->dm_segs[0].ds_addr + offsetof(struct oosiop_xfer, msgin[0]); for (i = 0; i < OOSIOP_NTGT; i++) { sc->sc_tgt[i].nexus = NULL; sc->sc_tgt[i].flags = 0; } /* Setup asynchronous clock divisor parameters */ if (sc->sc_freq <= 25000000) { sc->sc_ccf = 10; sc->sc_dcntl = OOSIOP_DCNTL_CF_1; } else if (sc->sc_freq <= 37500000) { sc->sc_ccf = 15; sc->sc_dcntl = OOSIOP_DCNTL_CF_1_5; } else if (sc->sc_freq <= 50000000) { sc->sc_ccf = 20; sc->sc_dcntl = OOSIOP_DCNTL_CF_2; } else { sc->sc_ccf = 30; sc->sc_dcntl = OOSIOP_DCNTL_CF_3; } if (sc->sc_chip == OOSIOP_700) sc->sc_minperiod = oosiop_period(sc, 4, sc->sc_ccf); else sc->sc_minperiod = oosiop_period(sc, 4, 10); if (sc->sc_minperiod < 25) sc->sc_minperiod = 25; /* limit to 10MB/s */ mtx_init(&sc->sc_cb_mtx, IPL_BIO); scsi_iopool_init(&sc->sc_iopool, sc, oosiop_cb_alloc, oosiop_cb_free); printf(": NCR53C700%s rev %d, %dMHz\n", sc->sc_chip == OOSIOP_700_66 ? "-66" : "", oosiop_read_1(sc, OOSIOP_CTEST7) >> 4, sc->sc_freq / 1000000); /* * Reset all */ oosiop_reset(sc, TRUE); oosiop_reset_bus(sc); /* * Start SCRIPTS processor */ oosiop_load_script(sc); sc->sc_active = 0; oosiop_write_4(sc, OOSIOP_DSP, sc->sc_scrbase + Ent_wait_reselect); /* * Fill in the sc_link. */ sc->sc_link.adapter = &oosiop_adapter; sc->sc_link.adapter_softc = sc; sc->sc_link.openings = 1; /* XXX */ sc->sc_link.adapter_buswidth = OOSIOP_NTGT; sc->sc_link.adapter_target = sc->sc_id; sc->sc_link.pool = &sc->sc_iopool; sc->sc_link.quirks = ADEV_NODOORLOCK; bzero(&saa, sizeof(saa)); saa.saa_sc_link = &sc->sc_link; /* * Now try to attach all the sub devices. */ config_found(&sc->sc_dev, &saa, scsiprint); }