/* * Get the scsi driver to send a full inquiry to the * device and use the results to fill out the global * parameter structure. * * called from: * attach * open * ioctl (to reset original blksize) */ static int st_scsibus_mode_sense(struct st_softc *st, int flags) { u_int scsipi_sense_len; int error; struct scsipi_sense { struct scsi_mode_parameter_header_6 header; struct scsi_general_block_descriptor blk_desc; u_char sense_data[MAX_PAGE_0_SIZE]; } scsipi_sense; struct scsipi_periph *periph = st->sc_periph; scsipi_sense_len = sizeof(scsipi_sense.header) + sizeof(scsipi_sense.blk_desc) + st->page_0_size; /* * Set up a mode sense * We don't need the results. Just print them for our interest's sake, * if asked, or if we need it as a template for the mode select store * it away. */ error = scsipi_mode_sense(st->sc_periph, 0, SMS_PCTRL_CURRENT, &scsipi_sense.header, scsipi_sense_len, flags, ST_RETRIES, ST_CTL_TIME); if (error) return error; st->numblks = _3btol(scsipi_sense.blk_desc.nblocks); st->media_blksize = _3btol(scsipi_sense.blk_desc.blklen); st->media_density = scsipi_sense.blk_desc.density; if (scsipi_sense.header.dev_spec & SMH_DSP_WRITE_PROT) st->flags |= ST_READONLY; else st->flags &= ~ST_READONLY; SC_DEBUG(periph, SCSIPI_DB3, ("density code %d, %d-byte blocks, write-%s, ", st->media_density, st->media_blksize, st->flags & ST_READONLY ? "protected" : "enabled")); SC_DEBUG(periph, SCSIPI_DB3, ("%sbuffered\n", scsipi_sense.header.dev_spec & SMH_DSP_BUFF_MODE ? "" : "un")); if (st->page_0_size) memcpy(st->sense_data, scsipi_sense.sense_data, st->page_0_size); periph->periph_flags |= PERIPH_MEDIA_LOADED; return 0; }
static int st_scsibus_cmprss(struct st_softc *st, int flags, int onoff) { u_int scsi_dlen; int byte2, page; struct scsi_select { struct scsi_mode_parameter_header_6 header; struct scsi_general_block_descriptor blk_desc; u_char pdata[MAX(sizeof(struct scsi_tape_dev_conf_page), sizeof(struct scsi_tape_dev_compression_page))]; } scsi_pdata; struct scsi_tape_dev_conf_page *ptr; struct scsi_tape_dev_compression_page *cptr; struct scsipi_periph *periph = st->sc_periph; int error, ison; scsi_dlen = sizeof(scsi_pdata); /* * Do DATA COMPRESSION page first. */ page = SMS_PCTRL_CURRENT | 0xf; byte2 = 0; /* * Do the MODE SENSE command... */ again: memset(&scsi_pdata, 0, scsi_dlen); error = scsipi_mode_sense(periph, byte2, page, &scsi_pdata.header, scsi_dlen, flags | XS_CTL_DATA_ONSTACK, ST_RETRIES, ST_CTL_TIME); if (error) { if (byte2 != SMS_DBD) { byte2 = SMS_DBD; goto again; } /* * Try a different page? */ if (page == (SMS_PCTRL_CURRENT | 0xf)) { page = SMS_PCTRL_CURRENT | 0x10; byte2 = 0; goto again; } return (error); } if (scsi_pdata.header.blk_desc_len) ptr = (struct scsi_tape_dev_conf_page *) scsi_pdata.pdata; else ptr = (struct scsi_tape_dev_conf_page *) &scsi_pdata.blk_desc; if ((page & SMS_PAGE_MASK) == 0xf) { cptr = (struct scsi_tape_dev_compression_page *) ptr; ison = (cptr->dce_dcc & DCP_DCE) != 0; if (onoff) cptr->dce_dcc |= DCP_DCE; else cptr->dce_dcc &= ~DCP_DCE; cptr->pagecode &= ~0x80; } else { ison = (ptr->sel_comp_alg != 0); if (onoff) ptr->sel_comp_alg = 1; else ptr->sel_comp_alg = 0; ptr->pagecode &= ~0x80; ptr->byte2 = 0; ptr->active_partition = 0; ptr->wb_full_ratio = 0; ptr->rb_empty_ratio = 0; ptr->byte8 &= ~0x30; ptr->gap_size = 0; ptr->byte10 &= ~0xe7; ptr->ew_bufsize[0] = 0; ptr->ew_bufsize[1] = 0; ptr->ew_bufsize[2] = 0; ptr->reserved = 0; } /* * There might be a virtue in actually doing the MODE SELECTS, * but let's not clog the bus over it. */ if (onoff == ison) return (0); /* * Set up for a mode select */ scsi_pdata.header.data_length = 0; scsi_pdata.header.medium_type = 0; if ((st->flags & ST_DONTBUFFER) == 0) scsi_pdata.header.dev_spec = SMH_DSP_BUFF_MODE_ON; else scsi_pdata.header.dev_spec = 0; if (scsi_pdata.header.blk_desc_len) { scsi_pdata.blk_desc.density = 0; scsi_pdata.blk_desc.nblocks[0] = 0; scsi_pdata.blk_desc.nblocks[1] = 0; scsi_pdata.blk_desc.nblocks[2] = 0; } /* * Do the command */ error = scsipi_mode_select(periph, SMS_PF, &scsi_pdata.header, scsi_dlen, flags | XS_CTL_DATA_ONSTACK, ST_RETRIES, ST_CTL_TIME); if (error && (page & SMS_PAGE_MASK) == 0xf) { /* * Try DEVICE CONFIGURATION page. */ page = SMS_PCTRL_CURRENT | 0x10; goto again; } return (error); }
/* * Ask the device about itself and fill in the parameters in our * softc. */ static int ch_get_params(struct ch_softc *sc, int scsiflags) { struct scsi_mode_sense_data { struct scsi_mode_parameter_header_6 header; union { struct page_element_address_assignment ea; struct page_transport_geometry_parameters tg; struct page_device_capabilities cap; } pages; } sense_data; int error, from; u_int8_t *moves, *exchanges; /* * Grab info from the element address assignment page. */ memset(&sense_data, 0, sizeof(sense_data)); error = scsipi_mode_sense(sc->sc_periph, SMS_DBD, 0x1d, &sense_data.header, sizeof(sense_data), scsiflags, CHRETRIES, 6000); if (error) { aprint_error_dev(sc->sc_dev, "could not sense element address page\n"); return (error); } sc->sc_firsts[CHET_MT] = _2btol(sense_data.pages.ea.mtea); sc->sc_counts[CHET_MT] = _2btol(sense_data.pages.ea.nmte); sc->sc_firsts[CHET_ST] = _2btol(sense_data.pages.ea.fsea); sc->sc_counts[CHET_ST] = _2btol(sense_data.pages.ea.nse); sc->sc_firsts[CHET_IE] = _2btol(sense_data.pages.ea.fieea); sc->sc_counts[CHET_IE] = _2btol(sense_data.pages.ea.niee); sc->sc_firsts[CHET_DT] = _2btol(sense_data.pages.ea.fdtea); sc->sc_counts[CHET_DT] = _2btol(sense_data.pages.ea.ndte); /* XXX ask for transport geometry page XXX */ /* * Grab info from the capabilities page. */ memset(&sense_data, 0, sizeof(sense_data)); /* * XXX: Note: not all changers can deal with disabled block descriptors */ error = scsipi_mode_sense(sc->sc_periph, SMS_DBD, 0x1f, &sense_data.header, sizeof(sense_data), scsiflags, CHRETRIES, 6000); if (error) { aprint_error_dev(sc->sc_dev, "could not sense capabilities page\n"); return (error); } memset(sc->sc_movemask, 0, sizeof(sc->sc_movemask)); memset(sc->sc_exchangemask, 0, sizeof(sc->sc_exchangemask)); moves = &sense_data.pages.cap.move_from_mt; exchanges = &sense_data.pages.cap.exchange_with_mt; for (from = CHET_MT; from <= CHET_DT; ++from) { sc->sc_movemask[from] = moves[from]; sc->sc_exchangemask[from] = exchanges[from]; } #ifdef CH_AUTOMATIC_IELEM_POLICY /* * If we need to do an Init-Element-Status, * do that now that we know what's in the changer. */ if ((scsiflags & XS_CTL_IGNORE_MEDIA_CHANGE) == 0) { if ((sc->sc_periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) error = ch_ielem(sc); if (error == 0) sc->sc_periph->periph_flags |= PERIPH_MEDIA_LOADED; else sc->sc_periph->periph_flags &= ~PERIPH_MEDIA_LOADED; } #endif return (error); }