Exemple #1
0
/*
 * 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;
}
Exemple #2
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);
}
Exemple #3
0
/*
 * 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);
}