예제 #1
0
static int execscsicmd (struct dev_info_spti *di, int unitnum, uae_u8 *data, int len, uae_u8 *inbuf, int inlen)
{
	SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
	DWORD status;
	int err, dolen;

	uae_sem_wait (&scgp_sem);
	memset (&swb, 0, sizeof (swb));
	swb.spt.Length = sizeof (SCSI_PASS_THROUGH);
	swb.spt.CdbLength = len;
	if (inbuf) {
		swb.spt.DataIn = SCSI_IOCTL_DATA_IN;
		swb.spt.DataTransferLength = inlen;
		swb.spt.DataBuffer = inbuf;
		memset (inbuf, 0, inlen);
	} else {
		swb.spt.DataIn = SCSI_IOCTL_DATA_OUT;
	}
	swb.spt.TimeOutValue = 80 * 60;
	swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf);
	swb.spt.SenseInfoLength = 32;
	memcpy (swb.spt.Cdb, data, len);
	status = doscsi (di, unitnum, &swb, &err);
	uae_sem_post (&scgp_sem);
	dolen = swb.spt.DataTransferLength;
	if (!status)
		return -1;
	return dolen;
}
예제 #2
0
파일: scsi.c 프로젝트: AustenConrad/plan-9
static int
scsiexec(Target* tp, int rw, uchar* cmd, int cbytes, void* data, int* dbytes)
{
	int s;

	/*
	 * issue the SCSI command.  lun must already be in cmd[1].
	 */
	s = doscsi(tp, rw, cmd, cbytes, data, dbytes);
	switch(s){

	case STcheck:
		memmove(lastcmd, cmd, cbytes);
		lastcmdsz = cbytes;
		/*FALLTHROUGH*/

	default:
		/*
		 * It's more complicated than this.  There are conditions which
		 * are 'ok' but for which the returned status code is not 'STok'.
		 * Also, not all conditions require a reqsense, there may be a
		 * need to do a reqsense here when necessary and making it
		 * available to the caller somehow.
		 *
		 * Later.
		 */
		break;
	}

	return s;
}
예제 #3
0
static int execscsicmd_direct (int unitnum, struct amigascsi *as)
{
	struct dev_info_spti *di = unitisopen (unitnum);
	if (!di)
		return -1;

	SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
	DWORD status;
	int sactual = 0, i;
	int io_error = 0, err, parm;
	uae_u8 *scsi_datap, *scsi_datap_org;
	uae_u32 scsi_cmd_len_orig = as->cmd_len;

	memset (&swb, 0, sizeof (swb));
	swb.spt.Length = sizeof (SCSI_PASS_THROUGH);
	swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf);

	if (as->len > DEVICE_SCSI_BUFSIZE)
		as->len = DEVICE_SCSI_BUFSIZE;

	uae_sem_wait (&scgp_sem);

	/* the Amiga does not tell us how long the timeout shall be, so make it _very_ long (specified in seconds) */
	swb.spt.TimeOutValue = 80 * 60;
	scsi_datap = scsi_datap_org = as->len ? as->data : 0;
	swb.spt.DataIn = (as->flags & 1) ? SCSI_IOCTL_DATA_IN : SCSI_IOCTL_DATA_OUT;
	for (i = 0; i < as->cmd_len; i++)
		swb.spt.Cdb[i] = as->cmd[i];
	if (as->sense_len > 32)
		as->sense_len = 32;
	swb.spt.SenseInfoLength  = (as->flags & 4) ? 4 : /* SCSIF_OLDAUTOSENSE */
		(as->flags & 2) ? as->sense_len : /* SCSIF_AUTOSENSE */ 32;
	if (dev_info[unitnum].isatapi)
		scsi_atapi_fixup_pre (swb.spt.Cdb, &as->cmd_len, &scsi_datap, &as->len, &parm);

	memcpy (di->scsibuf, scsi_datap, as->len);

	swb.spt.CdbLength = (UCHAR)as->cmd_len;
	swb.spt.DataTransferLength = as->len;
	swb.spt.DataBuffer = di->scsibuf;

	status = doscsi (di, unitnum, &swb, &err);

	memcpy (scsi_datap, di->scsibuf, as->len);

	as->cmdactual = status == 0 ? 0 : scsi_cmd_len_orig; /* fake scsi_CmdActual */
	as->status = swb.spt.ScsiStatus; /* scsi_Status */
	if (swb.spt.ScsiStatus) {
		io_error = 45; /* HFERR_BadStatus */
		/* copy sense? */
		for (sactual = 0; sactual < as->sense_len && sactual < swb.spt.SenseInfoLength; sactual++)
			as->sensedata[sactual] = swb.SenseBuf[sactual];
		as->actual = 0; /* scsi_Actual */
	} else {
		int i;
		for (i = 0; i < as->sense_len; i++)
			as->sensedata[i] = 0;
		sactual = 0;
		if (status == 0) {
			io_error = 20; /* io_Error, but not specified */
			as->actual = 0; /* scsi_Actual */
		} else {
			as->len = swb.spt.DataTransferLength;
			if (dev_info[unitnum].isatapi)
				scsi_atapi_fixup_post (swb.spt.Cdb, as->cmd_len, scsi_datap_org, scsi_datap, &as->len, parm);
			io_error = 0;
			as->actual = as->len; /* scsi_Actual */
		}
	}
	as->sactual = sactual;
	uae_sem_post (&scgp_sem);

	if (scsi_datap != scsi_datap_org)
		free (scsi_datap);

	return io_error;
}