Beispiel #1
0
int
ch_getelemstatus(struct ch_softc *sc, int first, int count, caddr_t data,
    size_t datalen, int voltag)
{
	struct scsi_read_element_status *cmd;
	struct scsi_xfer *xs;
	int error;

	/*
	 * Build SCSI command.
	 */
	xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN);
	if (xs == NULL)
		return (ENOMEM);
	xs->cmdlen = sizeof(*cmd);
	xs->data = data;
	xs->datalen = datalen;
	xs->retries = CHRETRIES;
	xs->timeout = 100000;

	cmd = (struct scsi_read_element_status *)xs->cmd;
	cmd->opcode = READ_ELEMENT_STATUS;
	_lto2b(first, cmd->sea);
	_lto2b(count, cmd->count);
	_lto3b(datalen, cmd->len);
	if (voltag)
		cmd->byte2 |= READ_ELEMENT_STATUS_VOLTAG;

	error = scsi_xs_sync(xs);
	scsi_xs_put(xs);

	return (error);
}
Beispiel #2
0
static int
ch_getelemstatus(struct ch_softc *sc, int first, int count, void *data,
    size_t datalen, int scsiflags, int flags)
{
	struct scsi_read_element_status cmd;

	/*
	 * Build SCSI command.
	 */
	memset(&cmd, 0, sizeof(cmd));
	cmd.opcode = READ_ELEMENT_STATUS;
	cmd.byte2 = ELEMENT_TYPE_ALL;
	if (flags & CESR_VOLTAGS)
		cmd.byte2 |= READ_ELEMENT_STATUS_VOLTAG;
	_lto2b(first, cmd.sea);
	_lto2b(count, cmd.count);
	_lto3b(datalen, cmd.len);

	/*
	 * Send command to changer.
	 */
	return (scsipi_command(sc->sc_periph, (void *)&cmd, sizeof(cmd),
	    (void *)data, datalen,
	    CHRETRIES, CHTIMEOUT, NULL, scsiflags | XS_CTL_DATA_IN));
}
Beispiel #3
0
static int
ch_position(struct ch_softc *sc, struct changer_position_request *cp)
{
	struct scsi_position_to_element cmd;
	u_int16_t dst;

	/*
	 * Check arguments.
	 */
	if (cp->cp_type > CHET_DT)
		return (EINVAL);
	if (cp->cp_unit > (sc->sc_counts[cp->cp_type] - 1))
		return (ENODEV);

	/*
	 * Calculate the destination element.
	 */
	dst = sc->sc_firsts[cp->cp_type] + cp->cp_unit;

	/*
	 * Build the SCSI command.
	 */
	memset(&cmd, 0, sizeof(cmd));
	cmd.opcode = POSITION_TO_ELEMENT;
	_lto2b(sc->sc_picker, cmd.tea);
	_lto2b(dst, cmd.dst);
	if (cp->cp_flags & CP_INVERT)
		cmd.flags |= POSITION_TO_ELEMENT_INVERT;

	/*
	 * Send command to changer.
	 */
	return (scsipi_command(sc->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
	    CHRETRIES, CHTIMEOUT, NULL, 0));
}
Beispiel #4
0
static int
ch_exchange(struct ch_softc *sc, struct changer_exchange_request *ce)
{
	struct scsi_exchange_medium cmd;
	u_int16_t src, dst1, dst2;

	/*
	 * Check arguments.
	 */
	if ((ce->ce_srctype > CHET_DT) || (ce->ce_fdsttype > CHET_DT) ||
	    (ce->ce_sdsttype > CHET_DT))
		return (EINVAL);
	if ((ce->ce_srcunit > (sc->sc_counts[ce->ce_srctype] - 1)) ||
	    (ce->ce_fdstunit > (sc->sc_counts[ce->ce_fdsttype] - 1)) ||
	    (ce->ce_sdstunit > (sc->sc_counts[ce->ce_sdsttype] - 1)))
		return (ENODEV);

	/*
	 * Check the request against the changer's capabilities.
	 */
	if (((sc->sc_exchangemask[ce->ce_srctype] &
	     (1 << ce->ce_fdsttype)) == 0) ||
	    ((sc->sc_exchangemask[ce->ce_fdsttype] &
	     (1 << ce->ce_sdsttype)) == 0))
		return (ENODEV);

	/*
	 * Calculate the source and destination elements.
	 */
	src = sc->sc_firsts[ce->ce_srctype] + ce->ce_srcunit;
	dst1 = sc->sc_firsts[ce->ce_fdsttype] + ce->ce_fdstunit;
	dst2 = sc->sc_firsts[ce->ce_sdsttype] + ce->ce_sdstunit;

	/*
	 * Build the SCSI command.
	 */
	memset(&cmd, 0, sizeof(cmd));
	cmd.opcode = EXCHANGE_MEDIUM;
	_lto2b(sc->sc_picker, cmd.tea);
	_lto2b(src, cmd.src);
	_lto2b(dst1, cmd.fdst);
	_lto2b(dst2, cmd.sdst);
	if (ce->ce_flags & CE_INVERT1)
		cmd.flags |= EXCHANGE_MEDIUM_INV1;
	if (ce->ce_flags & CE_INVERT2)
		cmd.flags |= EXCHANGE_MEDIUM_INV2;

	/*
	 * Send command to changer.
	 */
	return (scsipi_command(sc->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
	    CHRETRIES, CHTIMEOUT, NULL, 0));
}
Beispiel #5
0
int
ch_move(struct ch_softc *sc, struct changer_move *cm)
{
	struct scsi_move_medium *cmd;
	struct scsi_xfer *xs;
	int error;
	u_int16_t fromelem, toelem;

	/*
	 * Check arguments.
	 */
	if ((cm->cm_fromtype > CHET_DT) || (cm->cm_totype > CHET_DT))
		return (EINVAL);
	if ((cm->cm_fromunit > (sc->sc_counts[cm->cm_fromtype] - 1)) ||
	    (cm->cm_tounit > (sc->sc_counts[cm->cm_totype] - 1)))
		return (ENODEV);

	/*
	 * Check the request against the changer's capabilities.
	 */
	if ((sc->sc_movemask[cm->cm_fromtype] & (1 << cm->cm_totype)) == 0)
		return (EINVAL);

	/*
	 * Calculate the source and destination elements.
	 */
	fromelem = sc->sc_firsts[cm->cm_fromtype] + cm->cm_fromunit;
	toelem = sc->sc_firsts[cm->cm_totype] + cm->cm_tounit;

	/*
	 * Build the SCSI command.
	 */
	xs = scsi_xs_get(sc->sc_link, 0);
	if (xs == NULL)
		return (ENOMEM);
	xs->cmdlen = sizeof(*cmd);
	xs->retries = CHRETRIES;
	xs->timeout = 100000;

	cmd = (struct scsi_move_medium *)xs->cmd;
	cmd->opcode = MOVE_MEDIUM;
	_lto2b(sc->sc_picker, cmd->tea);
	_lto2b(fromelem, cmd->src);
	_lto2b(toelem, cmd->dst);
	if (cm->cm_flags & CM_INVERT)
		cmd->flags |= MOVE_MEDIUM_INVERT;

	error = scsi_xs_sync(xs);
	scsi_xs_put(xs);

	return (error);
}
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
scsi_command_t * 
SCSI_rw_command (int rw, uint blkno, uint bcount)
{
  scsi_command_t *c = (scsi_command_t *) &sc;
  memset(c,0,sizeof(scsi_command_t));

  /*  if (((blkno & 0x1fffff) == blkno) && ((nblks & 0xff) == nblks)) { */
     /* transfer can be described in small RW SCSI command, so do it */
    /*
      struct scsi_rw *cmd_small = (struct scsi_rw *) &(c->command); 

      cmd_small->opcode = (rw == B_READ) ? READ_COMMAND : WRITE_COMMAND;
      _lto3b (blkno, cmd_small->addr);
      cmd_small->length = nblks & 0xff;
      c->length = sizeof (struct scsi_rw);
   } 
   else */
  {
    struct scsi_rw_10 *cmd_big = (struct scsi_rw_10 *) &(c->command); 
     cmd_big->opcode = (rw == B_READ) ? READ_10 : WRITE_10;
     _lto4b (blkno, cmd_big->addr);
     _lto2b (bcount, cmd_big->length);
     c->length = sizeof (struct scsi_rw_10);
  }
   c->datalen = bcount*SECT_SIZE;
   return ((scsi_command_t *) c);
}
Beispiel #7
0
static int
ch_voltag_convert_out(const struct changer_voltag *cv,
    struct changer_volume_tag *sv)
{
	int i;

	memset(sv, ' ', sizeof(struct changer_volume_tag));

	for (i = 0; i < sizeof(sv->volid); i++) {
		if (cv->cv_tag[i] == '\0')
			break;
		/*
		 * Limit the character set to what is suggested in
		 * the SCSI-2 spec.
		 */
		if ((cv->cv_tag[i] < '0' || cv->cv_tag[i] > '9') &&
		    (cv->cv_tag[i] < 'A' || cv->cv_tag[i] > 'Z') &&
		    (cv->cv_tag[i] != '_'))
			return (EINVAL);
		sv->volid[i] = cv->cv_tag[i];
	}

	_lto2b(cv->cv_serial, sv->volseq);

	return (0);
}
Beispiel #8
0
int
emc_inquiry(struct emc_softc *sc, char *model, char *serial)
{
	u_int8_t *buffer;
	struct scsi_inquiry *cdb;
	struct scsi_xfer *xs;
	size_t length;
	int error;
	u_int8_t slen, mlen;

	length = MIN(sc->sc_path.p_link->inqdata.additional_length + 5, 255);
	if (length < 160) {
		printf("%s: FC (Legacy)\n");
		return (0);
	}

	buffer = dma_alloc(length, PR_WAITOK);

	xs = scsi_xs_get(sc->sc_path.p_link, scsi_autoconf);
	if (xs == NULL) {
		error = EBUSY;
		goto done;
	}

	cdb = (struct scsi_inquiry *)xs->cmd;
	cdb->opcode = INQUIRY;
	_lto2b(length, cdb->length);

	xs->cmdlen = sizeof(*cdb);
	xs->flags |= SCSI_DATA_IN;
	xs->data = buffer;
	xs->datalen = length;

	error = scsi_xs_sync(xs);
	scsi_xs_put(xs);

	if (error != 0)
		goto done;

	slen = buffer[160];
	if (slen == 0 || slen + 161 > length) {
		error = EIO;
		goto done;
	}

	mlen = buffer[99];
	if (mlen == 0 || slen + mlen + 161 > length) {
		error = EIO;
		goto done;
	}

	scsi_strvis(serial, buffer + 161, slen);
	scsi_strvis(model, buffer + 161 + slen, mlen);

	error = 0;
done:
	dma_free(buffer, length);
	return (error);
}
Beispiel #9
0
static int
ch_move(struct ch_softc *sc, struct changer_move_request *cm)
{
	struct scsi_move_medium cmd;
	u_int16_t fromelem, toelem;

	/*
	 * Check arguments.
	 */
	if ((cm->cm_fromtype > CHET_DT) || (cm->cm_totype > CHET_DT))
		return (EINVAL);
	if ((cm->cm_fromunit > (sc->sc_counts[cm->cm_fromtype] - 1)) ||
	    (cm->cm_tounit > (sc->sc_counts[cm->cm_totype] - 1)))
		return (ENODEV);

	/*
	 * Check the request against the changer's capabilities.
	 */
	if ((sc->sc_movemask[cm->cm_fromtype] & (1 << cm->cm_totype)) == 0)
		return (ENODEV);

	/*
	 * Calculate the source and destination elements.
	 */
	fromelem = sc->sc_firsts[cm->cm_fromtype] + cm->cm_fromunit;
	toelem = sc->sc_firsts[cm->cm_totype] + cm->cm_tounit;

	/*
	 * Build the SCSI command.
	 */
	memset(&cmd, 0, sizeof(cmd));
	cmd.opcode = MOVE_MEDIUM;
	_lto2b(sc->sc_picker, cmd.tea);
	_lto2b(fromelem, cmd.src);
	_lto2b(toelem, cmd.dst);
	if (cm->cm_flags & CM_INVERT)
		cmd.flags |= MOVE_MEDIUM_INVERT;

	/*
	 * Send command to changer.
	 */
	return (scsipi_command(sc->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0,
	    CHRETRIES, CHTIMEOUT, NULL, 0));
}
Beispiel #10
0
int
ch_position(struct ch_softc *sc, struct changer_position *cp)
{
	struct scsi_position_to_element *cmd;
	struct scsi_xfer *xs;
	int error;
	u_int16_t dst;

	/*
	 * Check arguments.
	 */
	if (cp->cp_type > CHET_DT)
		return (EINVAL);
	if (cp->cp_unit > (sc->sc_counts[cp->cp_type] - 1))
		return (ENODEV);

	/*
	 * Calculate the destination element.
	 */
	dst = sc->sc_firsts[cp->cp_type] + cp->cp_unit;

	/*
	 * Build the SCSI command.
	 */
	xs = scsi_xs_get(sc->sc_link, 0);
	if (xs == NULL)
		return (ENOMEM);
	xs->cmdlen = sizeof(*cmd);
	xs->retries = CHRETRIES;
	xs->timeout = 100000;

	cmd = (struct scsi_position_to_element *)xs->cmd;
	cmd->opcode = POSITION_TO_ELEMENT;
	_lto2b(sc->sc_picker, cmd->tea);
	_lto2b(dst, cmd->dst);
	if (cp->cp_flags & CP_INVERT)
		cmd->flags |= POSITION_TO_ELEMENT_INVERT;

	error = scsi_xs_sync(xs);
	scsi_xs_put(xs);

	return (error);
}
Beispiel #11
0
void
sd_cmd_rw10(struct scsi_xfer *xs, int read, u_int64_t secno, u_int nsecs)
{
	struct scsi_rw_big *cmd = (struct scsi_rw_big *)xs->cmd;

	cmd->opcode = read ? READ_BIG : WRITE_BIG;
	_lto4b(secno, cmd->addr);
	_lto2b(nsecs, cmd->length);

	xs->cmdlen = sizeof(*cmd);
}
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
scsi_command_t * 
SCSI_read_defect_data (uint datalen)
{
  scsi_command_t *c = (scsi_command_t *) &sc;

#ifdef USE_READ_DEFECT_DATA_10
  struct scsi_read_defect_data_10 *cmd = (struct scsi_read_defect_data_10 *) 
    &(c->command); 
  memset(c,0,sizeof(scsi_command_t));

#ifdef DIXTRAC_FREEBSD_CAM
  // CAM restricts I/O to 64K of I/O, rounded up to include the full set of pages
  // so limit max I/O size to 60 Kbytes
  datalen = min(datalen, (60*1024));
#else
  datalen = min(datalen, 0xFFFF);
#endif //DIXTRAC_FREEBSD_CAM

  c->length = 10;

  cmd->opcode = READ_DEFECT_DATA_10;
  cmd->format = SRDDH10_PLIST | SRDDH10_GLIST | SRDDH10_PHYSICAL_SECTOR_FORMAT;
  _lto2b(datalen,cmd->alloc_length);	/* alloclen */
#else
  struct scsi_read_defect_data_12 *cmd = (struct scsi_read_defect_data_12 *) 
    &(c->command); 
  memset(c,0,sizeof(scsi_command_t));

#ifdef DIXTRAC_FREEBSD_CAM
  // CAM restricts I/O to 64K of I/O, rounded up to include the full set of pages
  // so limit max I/O size to 60 Kbytes
  datalen = min(datalen, (60*1024));
#else
  datalen = min(datalen, 0x1FFFF);
#endif //DIXTRAC_FREEBSD_CAM

  c->length = 12;

  cmd->opcode = READ_DEFECT_DATA_12;
  cmd->format = SRDDH12_PLIST | SRDDH12_GLIST | SRDDH12_PHYSICAL_SECTOR_FORMAT;
  _lto4b(datalen, cmd->alloc_length);	/* alloclen */
#endif
  c->datalen = datalen;

  cmd->byte2 = 0;			/* LUN + reserved */
  cmd->reserved[0] = 0; cmd->reserved[1] = 0;
  cmd->reserved[1] = 0; cmd->reserved[3] = 0;

  cmd->control = 0;			/* unknown control bits */

  return ((scsi_command_t *) c);
}
Beispiel #13
0
/*
 * Get scsi driver to send a "start playing" command
 */
int
cd_play(struct cd_softc *cd, int blkno, int nblks)
{
	struct scsi_play scsi_cmd;

	bzero(&scsi_cmd, sizeof(scsi_cmd));
	scsi_cmd.opcode = PLAY;
	_lto4b(blkno, scsi_cmd.blk_addr);
	_lto2b(nblks, scsi_cmd.xfer_len);
	return (scsi_scsi_cmd(cd->sc_link,
	    (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
	    0, 0, SCSI_RETRIES, 200000, NULL, 0));
}
Beispiel #14
0
int
safte_match(struct device *parent, void *match, void *aux)
{
	struct scsi_attach_args		*sa = aux;
	struct scsi_inquiry_data	*inq = sa->sa_inqbuf;
	struct scsi_inquiry_data	inqbuf;
	struct scsi_inquiry		cmd;
	struct safte_inq		*si = (struct safte_inq *)&inqbuf.extra;
	int				length, flags;

	if (inq == NULL)
		return (0);

	/* match on dell enclosures */
	if ((inq->device & SID_TYPE) == T_PROCESSOR &&
	    SCSISPC(inq->version) == 3)
		return (2);

	if ((inq->device & SID_TYPE) != T_PROCESSOR ||
	    SCSISPC(inq->version) != 2 ||
	    (inq->response_format & SID_ANSII) != 2)
		return (0);

	length = inq->additional_length + SAFTE_EXTRA_OFFSET;
	if (length < SAFTE_INQ_LEN)
		return (0);
	if (length > sizeof(inqbuf))
		length = sizeof(inqbuf);

	memset(&cmd, 0, sizeof(cmd));
	cmd.opcode = INQUIRY;
	_lto2b(length, cmd.length);

	memset(&inqbuf, 0, sizeof(inqbuf));
	memset(&inqbuf.extra, ' ', sizeof(inqbuf.extra));

	flags = SCSI_DATA_IN;
	if (cold)
		flags |= SCSI_AUTOCONF;

	if (scsi_scsi_cmd(sa->sa_sc_link, (struct scsi_generic *)&cmd,
	    sizeof(cmd), (u_char *)&inqbuf, length, 2, 10000, NULL,
	    flags) != 0)
		return (0);

	if (memcmp(si->ident, SAFTE_IDENT, sizeof(si->ident)) == 0)
		return (2);

	return (0);
}
Beispiel #15
0
int
emc_inquiry(struct emc_softc *sc, char *model, char *serial)
{
	u_int8_t buffer[255];
	struct scsi_inquiry *cdb;
	struct scsi_xfer *xs;
	size_t length;
	int error;
	u_int8_t slen, mlen;

	length = MIN(sc->sc_path.p_link->inqdata.additional_length + 5,
	    sizeof(buffer));
	if (length < 160) {
		printf("%s: FC (Legacy)\n");
		return (0);
	}

	xs = scsi_xs_get(sc->sc_path.p_link, scsi_autoconf);
	if (xs == NULL)
		return (EBUSY);

        cdb = (struct scsi_inquiry *)xs->cmd;
        cdb->opcode = INQUIRY;
        _lto2b(length, cdb->length);

        xs->cmdlen = sizeof(*cdb);
        xs->flags |= SCSI_DATA_IN;
        xs->data = buffer;
        xs->datalen = length;

        error = scsi_xs_sync(xs);
        scsi_xs_put(xs);

	if (error != 0)
		return (error);

	slen = buffer[160];
	if (slen == 0 || slen + 161 > length)
		return (EIO);

	mlen = buffer[99];
	if (mlen == 0 || slen + mlen + 161 > length)
		return (EIO);

	scsi_strvis(serial, buffer + 161, slen);
	scsi_strvis(model, buffer + 161 + slen, mlen);

	return (0);
}
Beispiel #16
0
/*
 * Read subchannel
 */
int
cd_read_subchannel(struct cd_softc *cd, int mode, int format, int track,
    struct cd_sub_channel_info *data, int len)
{
	struct scsi_read_subchannel scsi_cmd;

	bzero(&scsi_cmd, sizeof(scsi_cmd));
	scsi_cmd.opcode = READ_SUBCHANNEL;
	if (mode == CD_MSF_FORMAT)
		scsi_cmd.byte2 |= CD_MSF;
	scsi_cmd.byte3 = SRS_SUBQ;
	scsi_cmd.subchan_format = format;
	scsi_cmd.track = track;
	_lto2b(len, scsi_cmd.data_len);
	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
	    sizeof(struct scsi_read_subchannel), (u_char *)data, len,
	    SCSI_RETRIES, 5000, NULL, SCSI_DATA_IN|SCSI_SILENT);
}
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
scsi_command_t * 
SCSI_recv_diag_command (uint datalength)
{
  scsi_command_t *c = (scsi_command_t *) &sc;
  struct scsi_generic *cmd = (struct scsi_generic *) &(c->command); 
  memset(c,0,sizeof(scsi_command_t));

  c->length = sizeof(struct scsi_send_diag);
  c->datalen = datalength;

  cmd->opcode = RECEIVE_DIAGNOSTIC;
  cmd->bytes[0] = 0x0; 

  /* allocation length */
  _lto2b(datalength,&cmd->bytes[2]);

  return ((scsi_command_t *) c);
}
Beispiel #18
0
int
scsi_read(struct scsi_private *priv, daddr32_t blk, size_t size, void *buf,
    size_t *rsize)
{
	union {
		struct scsi_rw rw;
		struct scsi_rw_big rw_big;
		struct scsi_rw_12 rw_12;
	} cmd;
	int nsecs;
	size_t cmdlen;
	int i, rc;

	nsecs = (size + DEV_BSIZE - 1) >> _DEV_BSHIFT;

	for (i = SCSI_RETRIES; i != 0; i--) {
		memset(&cmd, 0, sizeof cmd);

		/* XXX SDEV_ONLYBIG quirk */
		if ((blk & 0x1fffff) == blk && (nsecs & 0xff) == nsecs) {
			cmd.rw.opcode = READ_COMMAND;
			_lto3b(blk, cmd.rw.addr);
			cmd.rw.length = nsecs;
			cmdlen = sizeof cmd.rw;
		} else if ((nsecs & 0xffff) == nsecs) {
			cmd.rw_big.opcode = READ_BIG;
			_lto4b(blk, cmd.rw_big.addr);
			_lto2b(nsecs, cmd.rw_big.length);
			cmdlen = sizeof cmd.rw_big;
		} else {
			cmd.rw_12.opcode = READ_12;
			_lto4b(blk, cmd.rw_12.addr);
			_lto4b(nsecs, cmd.rw_12.length);
			cmdlen = sizeof cmd.rw_12;
		}

		rc = (*priv->scsicmd)(priv->scsicookie,
		    &cmd, sizeof cmd, buf, size, rsize);
		if (rc == 0)
			break;
	}

	return rc;
}
Beispiel #19
0
/*
 * Read table of contents
 */
int
cd_read_toc(struct cd_softc *cd, int mode, int start, void *data, int len,
    int control)
{
	struct scsi_read_toc scsi_cmd;

	bzero(&scsi_cmd, sizeof(scsi_cmd));
	bzero(data, len);

	scsi_cmd.opcode = READ_TOC;
	if (mode == CD_MSF_FORMAT)
		scsi_cmd.byte2 |= CD_MSF;
	scsi_cmd.from_track = start;
	_lto2b(len, scsi_cmd.data_len);
	scsi_cmd.control = control;

	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
	    sizeof(struct scsi_read_toc), (u_char *)data, len, SCSI_RETRIES,
	    5000, NULL, SCSI_DATA_IN | SCSI_IGNORE_ILLEGAL_REQUEST);
}
Beispiel #20
0
struct scsi_generic * build_scsi_rw_command (int rw, uint blkno, uint bcount, int *cmdlen)
{
   uint nblks = howmany (bcount, SECT_SIZE);
   if (((blkno & 0x1fffff) == blkno) && ((nblks & 0xff) == nblks)) {
	/* transfer can be described in small RW SCSI command, so do it */
      struct scsi_rw *cmd_small = (struct scsi_rw *) malloc (sizeof(struct scsi_rw));
      bzero (cmd_small, sizeof(struct scsi_rw));
      cmd_small->opcode = (rw == B_READ) ? READ_COMMAND : WRITE_COMMAND;
      _lto3b (blkno, cmd_small->addr);
      cmd_small->length = nblks & 0xff;
      *cmdlen = sizeof (struct scsi_rw);
      return ((struct scsi_generic *) cmd_small);
      
   } else {
      struct scsi_rw_big *cmd_big = (struct scsi_rw_big *) malloc (sizeof(struct scsi_rw_big));
      bzero (cmd_big, sizeof(struct scsi_rw_big));
      cmd_big->opcode = (rw == B_READ) ? READ_BIG : WRITE_BIG;
      _lto4b (blkno, cmd_big->addr);
      _lto2b (nblks, cmd_big->length);
      *cmdlen = sizeof (struct scsi_rw_big);
      return ((struct scsi_generic *) cmd_big);
   }
}
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
scsi_command_t * 
SCSI_send_diag_command (uint datalength)
{
  scsi_command_t *c = (scsi_command_t *) &sc;
  struct scsi_send_diag *cmd = (struct scsi_send_diag *) &(c->command); 
  memset(c,0,sizeof(scsi_command_t));
  c->length = sizeof(struct scsi_send_diag);
  c->datalen = datalength;

  cmd->opcode = SEND_DIAGNOSTIC;
  cmd->byte2 = SSD_PF;  /* page format conforms to SCSI-2 */
  if (scsi_version >= 2) {
    cmd->byte2 = SSD_PF;  /* page format conforms to SCSI-2 */
  }
  else {
    cmd->byte2 = 0;  /* page format conforms to SCSI v.1 */
  }
  _lto2b(datalength,cmd->paramlen);

/*    printf("Send Diag command: ");  */
/*    print_hexpage((char *) cmd,6);  */

  return ((scsi_command_t *) c);
}
Beispiel #22
0
SANE_Status
sane_start (SANE_Handle handle)
{
  char *mode_str;
  Ibm_Scanner *s = handle;
  SANE_Status status;
  struct ibm_window_data wbuf;
  struct measurements_units_page mup;

  DBG (11, ">> sane_start\n");

  /* First make sure we have a current parameter set.  Some of the
     parameters will be overwritten below, but that's OK.  */
  status = sane_get_parameters (s, 0);
  if (status != SANE_STATUS_GOOD)
    return status;

  status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "open of %s failed: %s\n",
           s->hw->sane.name, sane_strstatus (status));
      return (status);
    }
  
  mode_str = s->val[OPT_MODE].s;
  s->xres = s->val[OPT_X_RESOLUTION].w;
  s->yres = s->val[OPT_Y_RESOLUTION].w;
  s->ulx = s->val[OPT_TL_X].w;
  s->uly = s->val[OPT_TL_Y].w;
  s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
  s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
  s->brightness = s->val[OPT_BRIGHTNESS].w;
  s->contrast = s->val[OPT_CONTRAST].w;
  s->bpp = s->params.depth;
  if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0) 
    {
      s->image_composition = IBM_BINARY_MONOCHROME;
    }
  else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
    {
      s->image_composition = IBM_DITHERED_MONOCHROME;
    }
  else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0)
    {
      s->image_composition = IBM_GRAYSCALE;
    }

  memset (&wbuf, 0, sizeof (wbuf));
/* next line commented out by mf */
/*  _lto2b(sizeof(wbuf) - 8, wbuf.len); */
/* next line by mf */
  _lto2b(IBM_WINDOW_DATA_SIZE, wbuf.len); /* size=320 */
  _lto2b(s->xres, wbuf.x_res);
  _lto2b(s->yres, wbuf.y_res);
  _lto4b(s->ulx, wbuf.x_org);
  _lto4b(s->uly, wbuf.y_org);
  _lto4b(s->width, wbuf.width);
  _lto4b(s->length, wbuf.length);

  wbuf.image_comp = s->image_composition;
  /* if you throw the MRIF bit the brighness control reverses too */
  /* so I reverse the reversal in software for symmetry's sake */
  if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME) 
    {
      if (wbuf.image_comp == IBM_GRAYSCALE) 
	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x80; /* it was 0x90 */
      if (wbuf.image_comp == IBM_DITHERED_MONOCHROME) 
	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10;
      wbuf.brightness = 256 - (SANE_Byte) s->brightness;
/*
      if (is50)
        wbuf.contrast = (SANE_Byte) s->contrast;
      else
*/
      wbuf.contrast = 256 - (SANE_Byte) s->contrast;
    }
  else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */
    {
      wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00;
      wbuf.brightness = (SANE_Byte) s->brightness;
      wbuf.contrast = (SANE_Byte) s->contrast;
    }

  wbuf.threshold = 0;
  wbuf.bits_per_pixel = s->bpp;

  wbuf.halftone_code = 2;     /* diithering */
  wbuf.halftone_id = 0x0A;    /* 8x8 Bayer pattenr */
  wbuf.pad_type = 3;
  wbuf.bit_ordering[0] = 0;
  wbuf.bit_ordering[1] = 7;   /* modified by mf (it was 3) */

  DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
  DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
  DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
  DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
  DBG (5, "width=%d\n", _4btol(wbuf.width));
  DBG (5, "length=%d\n", _4btol(wbuf.length));
  DBG (5, "image_comp=%d\n", wbuf.image_comp);

  DBG (11, "sane_start: sending SET WINDOW\n");
  status = set_window (s->fd, &wbuf);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status));
      return (status);
    }

  DBG (11, "sane_start: sending GET WINDOW\n");
  memset (&wbuf, 0, sizeof (wbuf));
  status = get_window (s->fd, &wbuf);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status));
      return (status); 
    }
  DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
  DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
  DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
  DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
  DBG (5, "width=%d\n", _4btol(wbuf.width));
  DBG (5, "length=%d\n", _4btol(wbuf.length));
  DBG (5, "image_comp=%d\n", wbuf.image_comp);

  DBG (11, "sane_start: sending MODE SELECT\n");
  memset (&mup, 0, sizeof (mup));
  mup.page_code = MEASUREMENTS_PAGE;
  mup.parameter_length = 0x06;
  mup.bmu = INCHES;
  mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
  mup.mud[1] = (DEFAULT_MUD & 0xff);
/* next lines by mf */
  mup.adf_page_code = 0x26;
  mup.adf_parameter_length = 6;
  if (s->adf_state == ADF_ARMED)
    mup.adf_control = 1;
  else
    mup.adf_control = 0;
/* end lines by mf */
  
  status = mode_select (s->fd, (struct mode_pages *) &mup);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "attach: MODE_SELECT failed\n");
      return (SANE_STATUS_INVAL);
    }

  status = trigger_scan (s->fd);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "start of scan failed: %s\n", sane_strstatus (status));
      /* next line introduced not to freeze xscanimage */
      do_cancel(s);
      return status;
    }

  /* Wait for scanner to become ready to transmit data */
  status = ibm_wait_ready (s);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status));
      return (status);
    } 

  s->bytes_to_read = s->params.bytes_per_line * s->params.lines;

  DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
       "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
       s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
 
  s->scanning = SANE_TRUE;

  DBG (11, "<< sane_start\n"); 
  return (SANE_STATUS_GOOD); 
}
Beispiel #23
0
/*
 * cdstart looks to see if there is a buf waiting for the device
 * and that the device is not already busy. If both are true,
 * It deques the buf and creates a scsi command to perform the
 * transfer in the buf. The transfer request will call scsi_done
 * on completion, which will in turn call this routine again
 * so that the next queued transfer is performed.
 * The bufs are queued by the strategy routine (cdstrategy)
 *
 * This routine is also called after other non-queued requests
 * have been made of the scsi driver, to ensure that the queue
 * continues to be drained.
 *
 * must be called at the correct (highish) spl level
 * cdstart() is called at splbio from cdstrategy, cdrestart and scsi_done
 */
void
cdstart(void *v)
{
	struct cd_softc *cd = v;
	struct scsi_link *sc_link = cd->sc_link;
	struct buf *bp = 0;
	struct buf *dp;
	struct scsi_rw_big cmd_big;
	struct scsi_rw cmd_small;
	struct scsi_generic *cmdp;
	int blkno, nblks, cmdlen, error;
	struct partition *p;

	splassert(IPL_BIO);

	SC_DEBUG(sc_link, SDEV_DB2, ("cdstart\n"));
	/*
	 * Check if the device has room for another command
	 */
	while (sc_link->openings > 0) {
		/*
		 * there is excess capacity, but a special waits
		 * It'll need the adapter as soon as we clear out of the
		 * way and let it run (user level wait).
		 */
		if (sc_link->flags & SDEV_WAITING) {
			sc_link->flags &= ~SDEV_WAITING;
			wakeup((caddr_t)sc_link);
			return;
		}

		/*
		 * See if there is a buf with work for us to do..
		 */
		dp = &cd->buf_queue;
		if ((bp = dp->b_actf) == NULL)	/* yes, an assign */
			return;
		dp->b_actf = bp->b_actf;

		/*
		 * If the device has become invalid, abort all the
		 * reads and writes until all files have been closed and
		 * re-opened
		 */
		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
			bp->b_error = EIO;
			bp->b_flags |= B_ERROR;
			bp->b_resid = bp->b_bcount;
			biodone(bp);
			continue;
		}

		/*
		 * We have a buf, now we should make a command
		 *
		 * First, translate the block to absolute and put it in terms
		 * of the logical blocksize of the device.
		 */
		blkno =
		    bp->b_blkno / (cd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
		p = &cd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
		blkno += DL_GETPOFFSET(p);
		nblks = howmany(bp->b_bcount, cd->sc_dk.dk_label->d_secsize);

		/*
		 *  Fill out the scsi command.  If the transfer will
		 *  fit in a "small" cdb, use it.
		 */
		if (!(sc_link->flags & SDEV_ATAPI) &&
		    !(sc_link->quirks & SDEV_ONLYBIG) && 
		    ((blkno & 0x1fffff) == blkno) &&
		    ((nblks & 0xff) == nblks)) {
			/*
			 * We can fit in a small cdb.
			 */
			bzero(&cmd_small, sizeof(cmd_small));
			cmd_small.opcode = (bp->b_flags & B_READ) ?
			    READ_COMMAND : WRITE_COMMAND;
			_lto3b(blkno, cmd_small.addr);
			cmd_small.length = nblks & 0xff;
			cmdlen = sizeof(cmd_small);
			cmdp = (struct scsi_generic *)&cmd_small;
		} else {
			/*
			 * Need a large cdb.
			 */
			bzero(&cmd_big, sizeof(cmd_big));
			cmd_big.opcode = (bp->b_flags & B_READ) ?
			    READ_BIG : WRITE_BIG;
			_lto4b(blkno, cmd_big.addr);
			_lto2b(nblks, cmd_big.length);
			cmdlen = sizeof(cmd_big);
			cmdp = (struct scsi_generic *)&cmd_big;
		}

		/* Instrumentation. */
		disk_busy(&cd->sc_dk);

		/*
		 * Call the routine that chats with the adapter.
		 * Note: we cannot sleep as we may be an interrupt
		 */
		error = scsi_scsi_cmd(sc_link, cmdp, cmdlen,
		    (u_char *) bp->b_data, bp->b_bcount, SCSI_RETRIES, 30000,
		    bp, SCSI_NOSLEEP | ((bp->b_flags & B_READ) ? SCSI_DATA_IN :
		    SCSI_DATA_OUT));
		switch (error) {
		case 0:
			timeout_del(&cd->sc_timeout);
			break;
		case EAGAIN:
			/*
			 * The device can't start another i/o. Try again later.
			 */
			dp->b_actf = bp;
			disk_unbusy(&cd->sc_dk, 0, 0);
			timeout_add(&cd->sc_timeout, 1);
			return;
		default:
			disk_unbusy(&cd->sc_dk, 0, 0);
			printf("%s: not queued, error %d\n",
			    cd->sc_dev.dv_xname, error);
			break;
		}
	}
}
Beispiel #24
0
/*
 * Get the scsi driver to send a full inquiry to the * device and use the
 * results to fill out the disk parameter structure.
 */
static int
sd_get_capacity(struct sd_softc *sd)
{
	struct disk_parms *dp = &sd->sc_params;
	uint64_t blocks;
	int error, blksize;

	dp->disksize = blocks = sd_read_capacity(sd, &blksize);
	if (blocks == 0) {
		struct scsipi_read_format_capacities cmd;
		struct {
			struct scsipi_capacity_list_header header;
			struct scsipi_capacity_descriptor desc;
		} __packed data;

		memset(&cmd, 0, sizeof(cmd));
		memset(&data, 0, sizeof(data));
		cmd.opcode = READ_FORMAT_CAPACITIES;
		_lto2b(sizeof(data), cmd.length);

		error = scsi_command(sd,
		    (void *)&cmd, sizeof(cmd), (void *)&data, sizeof(data));
		if (error == EFTYPE)
			/* Medium Format Corrupted, handle as not formatted */
			return SDGP_RESULT_UNFORMATTED;
		if (error || data.header.length == 0)
			return SDGP_RESULT_OFFLINE;

		switch (data.desc.byte5 & SCSIPI_CAP_DESC_CODE_MASK) {
		case SCSIPI_CAP_DESC_CODE_RESERVED:
		case SCSIPI_CAP_DESC_CODE_FORMATTED:
			break;

		case SCSIPI_CAP_DESC_CODE_UNFORMATTED:
			return SDGP_RESULT_UNFORMATTED;

		case SCSIPI_CAP_DESC_CODE_NONE:
			return SDGP_RESULT_OFFLINE;
		}

		dp->disksize = blocks = _4btol(data.desc.nblks);
		if (blocks == 0)
			return SDGP_RESULT_OFFLINE;		/* XXX? */

		blksize = _3btol(data.desc.blklen);

	} else if (!sd_validate_blksize(blksize)) {
		struct sd_mode_sense_data scsipi_sense;
		int bsize;

		memset(&scsipi_sense, 0, sizeof(scsipi_sense));
		error = scsi_mode_sense(sd, 0, 0, &scsipi_sense.header,
		    sizeof(struct scsi_mode_parameter_header_6) +
						sizeof(scsipi_sense.blk_desc));
		if (!error) {
			bsize = scsipi_sense.header.blk_desc_len;

			if (bsize >= 8)
				blksize = _3btol(scsipi_sense.blk_desc.blklen);
		}
	}

	if (!sd_validate_blksize(blksize))
		blksize = SD_DEFAULT_BLKSIZE;

	dp->blksize = blksize;
	dp->disksize512 = (blocks * dp->blksize) / DEV_BSIZE;
	return 0;
}
/*
 * trigger the scanner to start a scan operation
 * this includes sending the mode- and window-data, starting the scanner
 * and getting the image size info
 */
static int
mustek_trigger_scanner(struct ss_softc *ss)
{
	struct mustek_mode_select_cmd mode_cmd;
	struct mustek_mode_select_data mode_data;
	struct mustek_set_window_cmd window_cmd;
	struct mustek_set_window_data window_data;
	struct mustek_start_scan_cmd start_scan_cmd;
	struct scsipi_periph *periph = ss->sc_periph;
	int pixel_tlx, pixel_tly, pixel_brx, pixel_bry, paperlength;
	int error;

	mustek_compute_sizes(ss);

	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_trigger_scanner\n"));

	/* set the window params and send the scsi command */
	memset(&window_cmd, 0, sizeof(window_cmd));
	window_cmd.opcode = MUSTEK_SET_WINDOW;
	window_cmd.length = sizeof(window_data);

	memset(&window_data, 0, sizeof(window_data));
	window_data.frame.header = MUSTEK_LINEART_BACKGROUND | MUSTEK_UNIT_SPEC;
#ifdef MUSTEK_INCH_SPEC
	/* the positional values are all 1 byte because 256 / 8 = 32" */
	pixel_tlx = ss->sio.scan_x_origin / 150;
	pixel_tly = ss->sio.scan_y_origin / 150;
	pixel_brx = pixel_tlx + ss->sio.scan_width / 150;
	pixel_bry = pixel_tly + ss->sio.scan_height / 150;
#else
	pixel_tlx = (ss->sio.scan_x_origin * ss->sio.scan_x_resolution) / 1200;
	pixel_tly = (ss->sio.scan_y_origin * ss->sio.scan_y_resolution) / 1200;
	pixel_brx = pixel_tlx +
	    (ss->sio.scan_width * ss->sio.scan_x_resolution) / 1200;
	pixel_bry = pixel_tly +
	    (ss->sio.scan_height * ss->sio.scan_y_resolution) / 1200;
#endif
	_lto2l(pixel_tlx, window_data.frame.tl_x);
	_lto2l(pixel_tly, window_data.frame.tl_y);
	_lto2l(pixel_brx, window_data.frame.br_x);
	_lto2l(pixel_bry, window_data.frame.br_y);

#if MUSTEK_WINDOWS >= 1
	window_data.window1 = window_data.frame;
	window_data.window1.header = MUSTEK_WINDOW_MASK | MUSTEK_UNIT_SPEC;
#endif

	/* send the set window command to the scanner */
	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_set_parms: set_window\n"));
	error = scsipi_command(periph, (void *)&window_cmd, sizeof(window_cmd),
	    (void *)&window_data, sizeof(window_data),
	    MUSTEK_RETRIES, 5000, NULL, XS_CTL_DATA_OUT);
	if (error)
		return error;

	/*
	 * do what it takes to actualize the mode
	 */
	memset(&mode_cmd, 0, sizeof(mode_cmd));
	mode_cmd.opcode = MUSTEK_MODE_SELECT;
	_lto2b(sizeof(mode_data), mode_cmd.length);

	memset(&mode_data, 0, sizeof(mode_data));
	mode_data.mode =
	    MUSTEK_MODE_MASK | MUSTEK_HT_PATTERN_BUILTIN | MUSTEK_UNIT_SPEC;
	if (ss->sio.scan_x_resolution <= 300)
		mode_data.resolution = ss->sio.scan_x_resolution / 3;
	else
		/*
		 * the resolution values is computed by modulo 100, but not
		 * for 600dpi, where the value is 100 (a bit tricky, but ...)
		 */
		mode_data.resolution =
		    ((ss->sio.scan_x_resolution - 1) % 100) + 1;

	mode_data.brightness = (ss->sio.scan_brightness - 64) / 3;
	mode_data.contrast = (ss->sio.scan_contrast - 16) / 7;
	mode_data.grain = 0;
	mode_data.velocity = ss->sio.scan_quality / 20 - 1;
#ifdef MUSTEK_INCH_SPEC
	paperlength = 14 * 8;	/* 14" */
#else
	paperlength = 14 * ss->sio.scan_y_resolution;	/* 14" */
#endif
	_lto2l(paperlength, mode_data.paperlength);

	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_trigger_scanner: mode_select\n"));
	/* send the command to the scanner */
	error = scsipi_command(periph, (void *)&mode_cmd, sizeof(mode_cmd),
	    (void *)&mode_data, sizeof(mode_data),
	    MUSTEK_RETRIES, 5000, NULL, XS_CTL_DATA_OUT);
	if (error)
		return error;

	/*
	 * now construct and send the start command
	 */
	memset(&start_scan_cmd, 0, sizeof(start_scan_cmd));
	start_scan_cmd.opcode = MUSTEK_START_STOP;
	start_scan_cmd.mode = MUSTEK_SCAN_START;
	if (ss->sio.scan_x_resolution <= 300)
		start_scan_cmd.mode |= MUSTEK_RES_STEP_1;
	else
		start_scan_cmd.mode |= MUSTEK_RES_STEP_10;
	switch (ss->sio.scan_image_mode) {
	case SIM_BINARY_MONOCHROME:
	case SIM_DITHERED_MONOCHROME:
		start_scan_cmd.mode |= MUSTEK_BIT_MODE | MUSTEK_GRAY_FILTER;
		break;
	case SIM_GRAYSCALE:
		start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_GRAY_FILTER;
		break;
	case SIM_RED:
		start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_RED_FILTER;
		break;
	case SIM_GREEN:
		start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_GREEN_FILTER;
		break;
	case SIM_BLUE:
		start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_BLUE_FILTER;
		break;
	}

	/* send the command to the scanner */
	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_trigger_scanner: start_scan\n"));
	error = scsipi_command(periph,
	    (void *)&start_scan_cmd, sizeof(start_scan_cmd), NULL, 0,
	    MUSTEK_RETRIES, 5000, NULL, 0);
	if (error)
		return error;

	/*
	 * now check if scanner ready this time with update of size info
	 * we wait here so that if the user issues a read directly afterwards,
	 * the scanner will respond directly (otherwise we had to sleep with
	 * a buffer locked in memory)
	 */
	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_trigger_scanner: get_status\n"));
	error = mustek_get_status(ss, 60, 1);
	if (error)
		return error;

	return 0;
}
Beispiel #26
0
/*
 * Read some data.
 */
int
sdstrategy(void *f, int rw, daddr_t dblk, size_t size, void *p, size_t *rsize)
{
	struct sd_softc *sd;
	struct disklabel *lp;
	struct partition *pp;
	struct scsipi_generic *cmdp;
	struct scsipi_rw_16 cmd16;
	struct scsipi_rw_10 cmd_big;
	struct scsi_rw_6 cmd_small;
	daddr_t blkno;
	int cmdlen, nsect, i;
	uint8_t *buf;

	if (size == 0)
		return 0;
    
	if (rw != F_READ)
		return EOPNOTSUPP;

	buf = p;
	sd = f;
	lp = &sd->sc_label;
	pp = &lp->d_partitions[sd->sc_part];

	if (!(sd->sc_flags & FLAGS_MEDIA_LOADED))
		return EIO;

	nsect = howmany(size, lp->d_secsize);
	blkno = dblk + pp->p_offset;

	for (i = 0; i < nsect; i++, blkno++) {
		int error;

		/*
		 * Fill out the scsi command.  Use the smallest CDB possible
		 * (6-byte, 10-byte, or 16-byte).
		 */
		if ((blkno & 0x1fffff) == blkno) {
			/* 6-byte CDB */
			memset(&cmd_small, 0, sizeof(cmd_small));
			cmd_small.opcode = SCSI_READ_6_COMMAND;
			_lto3b(blkno, cmd_small.addr);
			cmd_small.length = 1;
			cmdlen = sizeof(cmd_small);
			cmdp = (struct scsipi_generic *)&cmd_small;
		} else if ((blkno & 0xffffffff) == blkno) {
			/* 10-byte CDB */
			memset(&cmd_big, 0, sizeof(cmd_big));
			cmd_small.opcode = READ_10;
			_lto4b(blkno, cmd_big.addr);
			_lto2b(1, cmd_big.length);
			cmdlen = sizeof(cmd_big);
			cmdp = (struct scsipi_generic *)&cmd_big;
		} else {
			/* 16-byte CDB */
			memset(&cmd16, 0, sizeof(cmd16));
			cmd_small.opcode = READ_16;
			_lto8b(blkno, cmd16.addr);
			_lto4b(1, cmd16.length);
			cmdlen = sizeof(cmd16);
			cmdp = (struct scsipi_generic *)&cmd16;
		}

		error = scsi_command(sd, cmdp, cmdlen, buf, lp->d_secsize);
		if (error)
			return error;

		buf += lp->d_secsize;
	}

	*rsize = size;
	return 0;
}
Beispiel #27
0
static int
ch_setvoltag(struct ch_softc *sc, struct changer_set_voltag_request *csvr)
{
	struct scsi_send_volume_tag cmd;
	struct changer_volume_tag voltag;
	void *data = NULL;
	size_t datalen = 0;
	int error;
	u_int16_t dst;

	/*
	 * Check arguments.
	 */
	if (csvr->csvr_type > CHET_DT)
		return (EINVAL);
	if (csvr->csvr_unit > (sc->sc_counts[csvr->csvr_type] - 1))
		return (ENODEV);

	dst = sc->sc_firsts[csvr->csvr_type] + csvr->csvr_unit;

	/*
	 * Build the SCSI command.
	 */
	memset(&cmd, 0, sizeof(cmd));
	cmd.opcode = SEND_VOLUME_TAG;
	_lto2b(dst, cmd.eaddr);

#define	ALTERNATE	(csvr->csvr_flags & CSVR_ALTERNATE)

	switch (csvr->csvr_flags & CSVR_MODE_MASK) {
	case CSVR_MODE_SET:
		cmd.sac = ALTERNATE ? SAC_ASSERT_ALT : SAC_ASSERT_PRIMARY;
		break;

	case CSVR_MODE_REPLACE:
		cmd.sac = ALTERNATE ? SAC_REPLACE_ALT : SAC_REPLACE_PRIMARY;
		break;

	case CSVR_MODE_CLEAR:
		cmd.sac = ALTERNATE ? SAC_UNDEFINED_ALT : SAC_UNDEFINED_PRIMARY;
		break;

	default:
		return (EINVAL);
	}

#undef ALTERNATE

	if (cmd.sac < SAC_UNDEFINED_PRIMARY) {
		error = ch_voltag_convert_out(&csvr->csvr_voltag, &voltag);
		if (error)
			return (error);
		data = &voltag;
		datalen = sizeof(voltag);
		_lto2b(datalen, cmd.length);
	}

	/*
	 * Send command to changer.
	 */
	return (scsipi_command(sc->sc_periph, (void *)&cmd, sizeof(cmd),
	    (void *)data, datalen, CHRETRIES, CHTIMEOUT, NULL,
	    datalen ? XS_CTL_DATA_OUT : 0));
}
Beispiel #28
0
int
ch_exchange(struct ch_softc *sc, struct changer_exchange *ce)
{
	struct scsi_exchange_medium *cmd;
	struct scsi_xfer *xs;
	int error;
	u_int16_t src, dst1, dst2;

	/*
	 * Check arguments.
	 */
	if ((ce->ce_srctype > CHET_DT) || (ce->ce_fdsttype > CHET_DT) ||
	    (ce->ce_sdsttype > CHET_DT))
		return (EINVAL);
	if ((ce->ce_srcunit > (sc->sc_counts[ce->ce_srctype] - 1)) ||
	    (ce->ce_fdstunit > (sc->sc_counts[ce->ce_fdsttype] - 1)) ||
	    (ce->ce_sdstunit > (sc->sc_counts[ce->ce_sdsttype] - 1)))
		return (ENODEV);

	/*
	 * Check the request against the changer's capabilities.
	 */
	if (((sc->sc_exchangemask[ce->ce_srctype] &
	    (1 << ce->ce_fdsttype)) == 0) ||
	    ((sc->sc_exchangemask[ce->ce_fdsttype] &
	    (1 << ce->ce_sdsttype)) == 0))
		return (EINVAL);

	/*
	 * Calculate the source and destination elements.
	 */
	src = sc->sc_firsts[ce->ce_srctype] + ce->ce_srcunit;
	dst1 = sc->sc_firsts[ce->ce_fdsttype] + ce->ce_fdstunit;
	dst2 = sc->sc_firsts[ce->ce_sdsttype] + ce->ce_sdstunit;

	/*
	 * Build the SCSI command.
	 */
	xs = scsi_xs_get(sc->sc_link, 0);
	if (xs == NULL)
		return (ENOMEM);
	xs->cmdlen = sizeof(*cmd);
	xs->retries = CHRETRIES;
	xs->timeout = 100000;

	cmd = (struct scsi_exchange_medium *)xs->cmd;
	cmd->opcode = EXCHANGE_MEDIUM;
	_lto2b(sc->sc_picker, cmd->tea);
	_lto2b(src, cmd->src);
	_lto2b(dst1, cmd->fdst);
	_lto2b(dst2, cmd->sdst);
	if (ce->ce_flags & CE_INVERT1)
		cmd->flags |= EXCHANGE_MEDIUM_INV1;
	if (ce->ce_flags & CE_INVERT2)
		cmd->flags |= EXCHANGE_MEDIUM_INV2;

	error = scsi_xs_sync(xs);
	scsi_xs_put(xs);

	return (error);
}