#include
#include
#include
#include
#include "send_scsi_cmd.h"
extern WORD Send_SCSI_CMD( const STRPTR devicename,
const ULONG devunit,
const ULONG opendevflags,
struct sizedbuffer * cmdbuffer,
struct sizedbuffer * databuffer,
struct sizedbuffer * sensebuffer,
const UBYTE LUN,
const UBYTE scsiflags)
{
struct IOStdReq * req;
struct MsgPort * myport;
WORD retval = -1;
// Controllo di alcuni parametri di chiamata.
if(!cmdbuffer || !databuffer || !sensebuffer)
return -1;
if((cmdbuffer->len != 6) && (cmdbuffer->len != 10) && (cmdbuffer->len != 12) &&
(cmdbuffer->len != 16))
return -1;
if((scsiflags & SCSIF_AUTOSENSE) && sensebuffer->len < 18)
return -1;
if(sensebuffer->len > 254)
sensebuffer->len = 254; // Tronca i sense buffer troppo lunghi.
if(LUN > 7)
return -1;
/* Il controllo qui sopra presuppone un utilizzo della LUN in stile SCSI-2, che
implica tra l'altro l'uso di un bus parallelo (SPI). */
if(myport=CreateMsgPort()) // Creazione message port per l'IO
{
if(req=CreateStdIO(myport)) // Creazione dell'IORequest (esteso)
{
UBYTE deverr;
struct SCSICmd cmdstruct; // La struttura apposita.
if(deverr=OpenDevice(devicename, devunit, (struct IORequest *)req, opendevflags))
{
retval = (WORD)(req->io_Error<<8); // Per qualche motivo la periferica non è disponibile.
}
else {
/* Assegnazione dei vari campi */
cmdstruct.scsi_Data = databuffer->buf;
cmdstruct.scsi_Length = databuffer->len;
cmdstruct.scsi_Command = cmdbuffer->buf;
cmdstruct.scsi_CmdLength= cmdbuffer->len;
cmdstruct.scsi_SenseData= sensebuffer->buf;
cmdstruct.scsi_SenseLength= sensebuffer->len;
cmdstruct.scsi_Flags = scsiflags;
/* Azzeramento dei valori in uscita */
cmdstruct.scsi_Status = cmdstruct.scsi_Actual = 0;
cmdstruct.scsi_CmdActual= cmdstruct.scsi_SenseActual = 0;
if(LUN)
{
SET_LUN_ON_COMMAND(cmdstruct.scsi_Command, LUN);
}
/* Configurazione dell'IOStdReq . */
req->io_Length = sizeof(struct SCSICmd);
req->io_Data = (APTR) &cmdstruct;
req->io_Command = HD_SCSICMD;
req->io_Flags = req->io_Actual = req->io_Offset = 0;
/* Esecuzione del comando!! */
retval = DoIO((struct IORequest *)req);
/* I valori in uscita: gli Actual .*/
cmdbuffer->actual = cmdstruct.scsi_CmdActual;
sensebuffer->actual = cmdstruct.scsi_SenseActual;
databuffer->actual = cmdstruct.scsi_Actual;
retval = retval<<8 | cmdstruct.scsi_Status;
CloseDevice((struct IORequest *)req); // Chiude il device.
}
DeleteStdIO(req); // Dealloca la struttura per l'IO
}
else retval = -1;
DeleteMsgPort(myport);
}
return retval;
}