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; }
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; }
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; }