Пример #1
0
void
sd_cmd_rw12(struct scsi_xfer *xs, int read, u_int64_t secno, u_int nsecs)
{
	struct scsi_rw_12 *cmd = (struct scsi_rw_12 *)xs->cmd;

	cmd->opcode = read ? READ_12 : WRITE_12;
	_lto4b(secno, cmd->addr);
	_lto4b(nsecs, cmd->length);

	xs->cmdlen = sizeof(*cmd);
}
Пример #2
0
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
scsi_command_t * 
SCSI_rw_command (int rw, uint blkno, uint bcount)
{
  scsi_command_t *c = (scsi_command_t *) ≻
  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);
}
Пример #3
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;
}
Пример #4
0
void
sd_cmd_rw16(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks)
{
    struct scsi_rw_16 *cmd = (struct scsi_rw_16 *)xs->cmd;

    cmd->opcode = read ? READ_16 : WRITE_16;
    _lto8b(blkno, cmd->addr);
    _lto4b(nblks, cmd->length);

    xs->cmdlen = sizeof(*cmd);
}
Пример #5
0
void
vdsk_scsi_capacity(struct scsi_xfer *xs)
{
	struct vdsk_softc *sc = xs->sc_link->adapter_softc;
	struct scsi_read_cap_data rcd;
	uint64_t capacity;

	bzero(&rcd, sizeof(rcd));

	capacity = sc->sc_vdisk_size - 1;
	if (capacity > 0xffffffff)
		capacity = 0xffffffff;

	_lto4b(capacity, rcd.addr);
	_lto4b(sc->sc_vdisk_block_size, rcd.length);

	bcopy(&rcd, xs->data, MIN(sizeof(rcd), xs->datalen));

	vdsk_scsi_done(xs, XS_NOERROR);
}
Пример #6
0
void
sd_cmd_rw10(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks)
{
    struct scsi_rw_big *cmd = (struct scsi_rw_big *)xs->cmd;

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

    xs->cmdlen = sizeof(*cmd);
}
Пример #7
0
/*
 * sd_read_capacity:
 *
 *	Find out from the device what its capacity is.
 */
static uint64_t
sd_read_capacity(struct sd_softc *sd, int *blksize)
{
	union {
		struct scsipi_read_capacity_10 cmd;
		struct scsipi_read_capacity_16 cmd16;
	} cmd;
	union {
		struct scsipi_read_capacity_10_data data;
		struct scsipi_read_capacity_16_data data16;
	} data;
	uint64_t rv;

	memset(&cmd, 0, sizeof(cmd));
	cmd.cmd.opcode = READ_CAPACITY_10;

	/*
	 * If the command works, interpret the result as a 4 byte
	 * number of blocks
	 */
	rv = 0;
	memset(&data, 0, sizeof(data.data));
	if (scsi_command(sd, (void *)&cmd.cmd, sizeof(cmd.cmd),
	    (void *)&data, sizeof(data.data)) != 0)
		goto out;

	if (_4btol(data.data.addr) != 0xffffffff) {
		*blksize = _4btol(data.data.length);
		rv = _4btol(data.data.addr) + 1;
		goto out;
	}

	/*
	 * Device is larger than can be reflected by READ CAPACITY (10).
	 * Try READ CAPACITY (16).
	 */

	memset(&cmd, 0, sizeof(cmd));
	cmd.cmd16.opcode = READ_CAPACITY_16;
	cmd.cmd16.byte2 = SRC16_SERVICE_ACTION;
	_lto4b(sizeof(data.data16), cmd.cmd16.len);

	memset(&data, 0, sizeof(data.data16));
	if (scsi_command(sd, (void *)&cmd.cmd16, sizeof(cmd.cmd16),
	    (void *)&data, sizeof(data.data16)) != 0)
		goto out;

	*blksize = _4btol(data.data16.length);
	rv = _8btol(data.data16.addr) + 1;

 out:
	return rv;
}
Пример #8
0
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
scsi_command_t * 
SCSI_read_defect_data (uint datalen)
{
  scsi_command_t *c = (scsi_command_t *) ≻

#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);
}
Пример #9
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));
}
Пример #10
0
void
vdsk_scsi_capacity16(struct scsi_xfer *xs)
{
	struct vdsk_softc *sc = xs->sc_link->adapter_softc;
	struct scsi_read_cap_data_16 rcd;

	bzero(&rcd, sizeof(rcd));

	_lto8b(sc->sc_vdisk_size - 1, rcd.addr);
	_lto4b(sc->sc_vdisk_block_size, rcd.length);

	bcopy(&rcd, xs->data, MIN(sizeof(rcd), xs->datalen));

	vdsk_scsi_done(xs, XS_NOERROR);
}
Пример #11
0
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
scsi_command_t * 
SCSI_read_capacity(uint lbn,u_int8_t pmi)
{
  scsi_command_t *c = (scsi_command_t *) ≻
  struct scsi_read_capacity *cmd = (struct scsi_read_capacity *) 
                                   &(c->command); 
  memset(c,0,sizeof(scsi_command_t));
  c->length = sizeof (struct scsi_read_capacity);
  c->datalen = READCAP_LENGTH;
  cmd->opcode = READ_CAPACITY;
  cmd->byte2 = 0x0; /* LUN=0 */
  _lto4b (lbn,cmd->addr);
  /*  __lto3b(0,cmd->unused); */
  cmd->unused[2]=pmi;
  return ((scsi_command_t *) c);
}
Пример #12
0
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
int 
create_lba_to_phys_page(char *p,int addr) 
{
  memset(p,0,TRANS_ADDR_PAGE_LEN+4);
  p[0]=TRANS_ADDR_PAGE;
  p[1]=0;
  p[2]=0;
  p[3]=TRANS_ADDR_PAGE_LEN;
  
  p[4] = 0x0; /* supplied format */
  p[5] = 0x05; /* translate format */
  
  _lto4b(addr,(u_int8_t *) &p[6]);
  
  return(TRANS_ADDR_PAGE_LEN+4);
}
Пример #13
0
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
int 
create_phys_to_lba_page(char *p,int cyl,int head,int sector) 
{
  memset(p,0,TRANS_ADDR_PAGE_LEN+4);
  p[0]=TRANS_ADDR_PAGE;
  p[1]=0;
  p[2]=0;
  p[3]=TRANS_ADDR_PAGE_LEN;
  
  p[4] = 0x05; /* supplied format */
  p[5] = 0x0; /* translate format */
  
  _lto3b(cyl,(u_int8_t *) &p[6]);
  p[9] = (u_int8_t) head;
  _lto4b(sector,(u_int8_t *) &p[10]);
  return(TRANS_ADDR_PAGE_LEN+4);
}
Пример #14
0
int
sd_read_cap_16(struct sd_softc *sc, int flags)
{
	struct scsi_read_capacity_16 cdb;
	struct scsi_read_cap_data_16 *rdcap;
	struct scsi_xfer *xs;
	int rv = ENOMEM;

	CLR(flags, SCSI_IGNORE_ILLEGAL_REQUEST);

	rdcap = dma_alloc(sizeof(*rdcap), (ISSET(flags, SCSI_NOSLEEP) ?
	    PR_NOWAIT : PR_WAITOK) | PR_ZERO);
	if (rdcap == NULL)
		return (ENOMEM);

	xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_IN | SCSI_SILENT);
	if (xs == NULL)
		goto done;

	bzero(&cdb, sizeof(cdb));
	cdb.opcode = READ_CAPACITY_16;
	cdb.byte2 = SRC16_SERVICE_ACTION;
	_lto4b(sizeof(*rdcap), cdb.length);

	memcpy(xs->cmd, &cdb, sizeof(cdb));
	xs->cmdlen = sizeof(cdb);
	xs->data = (void *)rdcap;
	xs->datalen = sizeof(*rdcap);
	xs->timeout = 20000;

	rv = scsi_xs_sync(xs);
	scsi_xs_put(xs);

	if (rv == 0) {
		sc->params.disksize = _8btol(rdcap->addr) + 1;
		sc->params.secsize = _4btol(rdcap->length);
		if (ISSET(_2btol(rdcap->lowest_aligned), READ_CAP_16_TPE))
			SET(sc->flags, SDF_THIN);
		else
			CLR(sc->flags, SDF_THIN);
	}

 done:
	dma_free(rdcap, sizeof(*rdcap));
	return (rv);
}
Пример #15
0
/*---------------------------------------------------------------------------
 *
 *--------------------------------------------------------------------------*/
scsi_command_t * 
SCSI_seek_command (uint lbn)
{
  scsi_command_t *c = (scsi_command_t *) ≻
  struct scsi_seek_extended *cmd = 
            (struct scsi_seek_extended *) &(c->command); 
  memset (c, 0,sizeof(scsi_command_t));

  c->length = 10;
  c->datalen = 0;

  cmd->opcode = SEEK_EXTENDED;

  /* lbn */
  _lto4b(lbn,cmd->lbn);
  
  return ((scsi_command_t *) c);
}
Пример #16
0
static int
ld_twa_scsicmd(struct ld_twa_softc *sc,
	struct twa_request *tr, struct buf *bp)
{
	if (tr->tr_flags == TWA_CMD_DATA_IN) {
		tr->tr_command->command.cmd_pkt_9k.cdb[0] = WRITE_16;
	} else {
		tr->tr_command->command.cmd_pkt_9k.cdb[0] = READ_16;
	}
	tr->tr_command->command.cmd_pkt_9k.cdb[1] =
		(sc->sc_hwunit << 5);			/* lun for CDB */

	_lto8b(htole64(bp->b_rawblkno),
		&tr->tr_command->command.cmd_pkt_9k.cdb[2]);
	_lto4b(htole32((bp->b_bcount / TWA_SECTOR_SIZE)),
		&tr->tr_command->command.cmd_pkt_9k.cdb[10]);
	
	tr->tr_command->command.cmd_pkt_9k.cdb[14] = 0;
	tr->tr_command->command.cmd_pkt_9k.cdb[15] = 0;

	return (0);
}
Пример #17
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);
   }
}
Пример #18
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); 
}
Пример #19
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;
}
Пример #20
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;
		}
	}
}
Пример #21
0
/*
 * This is pretty much a CD target for now
 */
static void
scsitest_request(struct scsipi_channel *chan,
	scsipi_adapter_req_t req, void *arg)
{
	struct scsipi_xfer *xs = arg;
	struct scsipi_generic *cmd = xs->cmd;
#ifdef USE_TOSI_ISO
	int error;
#endif

	if (req != ADAPTER_REQ_RUN_XFER)
		return;

	//show_scsipi_xs(xs);

	switch (cmd->opcode) {
	case SCSI_TEST_UNIT_READY:
		if (isofd == -1)
			sense_notready(xs);

		break;
	case INQUIRY: {
		struct scsipi_inquiry_data *inqbuf = (void *)xs->data;

		memset(inqbuf, 0, sizeof(*inqbuf));
		inqbuf->device = T_CDROM;
		inqbuf->dev_qual2 = SID_REMOVABLE;
		strcpy(inqbuf->vendor, "RUMPHOBO");
		strcpy(inqbuf->product, "It's a LIE");
		strcpy(inqbuf->revision, "0.00");
		break;
	}
	case READ_CD_CAPACITY: {
		struct scsipi_read_cd_cap_data *ret = (void *)xs->data;

		_lto4b(CDBLOCKSIZE, ret->length);
		_lto4b(mycdsize, ret->addr);

		break;
	}
	case READ_DISCINFO: {
		struct scsipi_read_discinfo_data *ret = (void *)xs->data;

		memset(ret, 0, sizeof(*ret));
		break;
	}
	case READ_TRACKINFO: {
		struct scsipi_read_trackinfo_data *ret = (void *)xs->data;

		_lto4b(mycdsize, ret->track_size);
		break;
	}
	case READ_TOC: {
		struct scsipi_toc_header *ret = (void *)xs->data;

		memset(ret, 0, sizeof(*ret));
		break;
	}
	case START_STOP: {
		struct scsipi_start_stop *param = (void *)cmd;

		if (param->how & SSS_LOEJ) {
#ifdef USE_TOSI_ISO
			rumpuser_close(isofd, &error);
#endif
			isofd = -1;
		}
		break;
	}
	case SCSI_SYNCHRONIZE_CACHE_10: {
		if (isofd == -1) {
			if ((xs->xs_control & XS_CTL_SILENT) == 0)
				atomic_inc_uint(&rump_scsitest_err
				    [RUMP_SCSITEST_NOISYSYNC]);
			
			sense_notready(xs);
		}

		break;
	}
	case GET_CONFIGURATION: {
		memset(xs->data, 0, sizeof(struct scsipi_get_conf_data));
		break;
	}
	case SCSI_READ_6_COMMAND: {
#ifdef USE_TOSI_ISO
		struct scsi_rw_6 *param = (void *)cmd;

		printf("reading %d bytes from %d\n",
		    param->length * CDBLOCKSIZE,
		    _3btol(param->addr) * CDBLOCKSIZE);
		rumpuser_pread(isofd, xs->data,
		     param->length * CDBLOCKSIZE,
		     _3btol(param->addr) * CDBLOCKSIZE,
		     &error);
#endif

		break;
	}
	case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
		/* hardcoded for now */
		break;
	default:
		printf("unhandled opcode 0x%x\n", cmd->opcode);
		break;
	}

	scsipi_done(xs);
}
Пример #22
0
int
dvd_auth(struct cd_softc *cd, union dvd_authinfo *a)
{
	struct scsi_generic cmd;
	u_int8_t buf[20];
	int error;

	bzero(cmd.bytes, sizeof(cmd.bytes));
	bzero(buf, sizeof(buf));

	switch (a->type) {
	case DVD_LU_SEND_AGID:
		cmd.opcode = GPCMD_REPORT_KEY;
		cmd.bytes[8] = 8;
		cmd.bytes[9] = 0 | (0 << 6);
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8,
		    SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN);
		if (error)
			return (error);
		a->lsa.agid = buf[7] >> 6;
		return (0);

	case DVD_LU_SEND_CHALLENGE:
		cmd.opcode = GPCMD_REPORT_KEY;
		cmd.bytes[8] = 16;
		cmd.bytes[9] = 1 | (a->lsc.agid << 6);
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 16,
		    SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN);
		if (error)
			return (error);
		dvd_copy_challenge(a->lsc.chal, &buf[4]);
		return (0);

	case DVD_LU_SEND_KEY1:
		cmd.opcode = GPCMD_REPORT_KEY;
		cmd.bytes[8] = 12;
		cmd.bytes[9] = 2 | (a->lsk.agid << 6);
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 12,
		    SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN);
		if (error)
			return (error);
		dvd_copy_key(a->lsk.key, &buf[4]);
		return (0);

	case DVD_LU_SEND_TITLE_KEY:
		cmd.opcode = GPCMD_REPORT_KEY;
		_lto4b(a->lstk.lba, &cmd.bytes[1]);
		cmd.bytes[8] = 12;
		cmd.bytes[9] = 4 | (a->lstk.agid << 6);
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 12,
		    SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN);
		if (error)
			return (error);
		a->lstk.cpm = (buf[4] >> 7) & 1;
		a->lstk.cp_sec = (buf[4] >> 6) & 1;
		a->lstk.cgms = (buf[4] >> 4) & 3;
		dvd_copy_key(a->lstk.title_key, &buf[5]);
		return (0);

	case DVD_LU_SEND_ASF:
		cmd.opcode = GPCMD_REPORT_KEY;
		cmd.bytes[8] = 8;
		cmd.bytes[9] = 5 | (a->lsasf.agid << 6);
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8,
		    SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN);
		if (error)
			return (error);
		a->lsasf.asf = buf[7] & 1;
		return (0);

	case DVD_HOST_SEND_CHALLENGE:
		cmd.opcode = GPCMD_SEND_KEY;
		cmd.bytes[8] = 16;
		cmd.bytes[9] = 1 | (a->hsc.agid << 6);
		buf[1] = 14;
		dvd_copy_challenge(&buf[4], a->hsc.chal);
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 16,
		    SCSI_RETRIES, 30000, NULL, SCSI_DATA_OUT);
		if (error)
			return (error);
		a->type = DVD_LU_SEND_KEY1;
		return (0);

	case DVD_HOST_SEND_KEY2:
		cmd.opcode = GPCMD_SEND_KEY;
		cmd.bytes[8] = 12;
		cmd.bytes[9] = 3 | (a->hsk.agid << 6);
		buf[1] = 10;
		dvd_copy_key(&buf[4], a->hsk.key);
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 12,
		    SCSI_RETRIES, 30000, NULL, SCSI_DATA_OUT);
		if (error) {
			a->type = DVD_AUTH_FAILURE;
			return (error);
		}
		a->type = DVD_AUTH_ESTABLISHED;
		return (0);

	case DVD_INVALIDATE_AGID:
		cmd.opcode = GPCMD_REPORT_KEY;
		cmd.bytes[9] = 0x3f | (a->lsa.agid << 6);
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 16,
		    SCSI_RETRIES, 30000, NULL, 0);
		if (error)
			return (error);
		return (0);

	case DVD_LU_SEND_RPC_STATE:
		cmd.opcode = GPCMD_REPORT_KEY;
		cmd.bytes[8] = 8;
		cmd.bytes[9] = 8 | (0 << 6);
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8,
		    SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN);
		if (error)
			return (error);
		a->lrpcs.type = (buf[4] >> 6) & 3;
		a->lrpcs.vra = (buf[4] >> 3) & 7;
		a->lrpcs.ucca = (buf[4]) & 7;
		a->lrpcs.region_mask = buf[5];
		a->lrpcs.rpc_scheme = buf[6];
		return (0);

	case DVD_HOST_SEND_RPC_STATE:
		cmd.opcode = GPCMD_SEND_KEY;
		cmd.bytes[8] = 8;
		cmd.bytes[9] = 6 | (0 << 6);
		buf[1] = 6;
		buf[4] = a->hrpcs.pdrc;
		error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8,
		    SCSI_RETRIES, 30000, NULL, SCSI_DATA_OUT);
		if (error)
			return (error);
		return (0);

	default:
		return (ENOTTY);
	}
}