home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #6
/
amigamamagazinepolishissue1998.iso
/
cdrom
/
cdt
/
source
/
cdt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-24
|
21KB
|
646 lines
/***************************************************************************/
/* */
/* CDT - a small shell utility to deal with a CD-ROM (based on SCSIutil ;) */
/* - written by Gunther Nikl in 11/1995 */
/* - can *only* be compiled with gcc ... */
/* */
/***************************************************************************/
/***************************************************************************/
/* */
/* includes */
/* */
/***************************************************************************/
#include <exec/types.h>
#ifndef CONST
#define CONST const
#endif
#ifndef INLINE
#define INLINE inline
#endif
#include <exec/io.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <devices/scsidisk.h>
/*
** structure definitions now!
*/
struct PortIO {
struct IOStdReq req;
struct MsgPort port;
};
/*
** sizeof(struct Globals) _MUST_ be a multiple of 4 !
*/
struct Globals {
/*** library stuff ***/
struct ExecBase *SysBase;
struct DosLibrary *DosBase;
/*** io stuff ***/
STRPTR ScsiName;
ULONG ScsiUnit;
struct PortIO *ScsiIO;
struct SCSICmd ScsiCmd;
UBYTE Pad[2],
*ScsiData,
*SenseBuf,
*TocBuf,
Command[12];
LONG HaveCmd,
Arg1,Arg2;
};
/*
** ptr to the `global' data space (will be on the stack :-)
*/
register struct Globals *gb asm("a4");
/*
** redirect global library bases to the `global' data space
*/
#define BASE_NAME gb->SysBase
#include <proto/exec.h>
#undef BASE_NAME
#define BASE_NAME gb->DosBase
#include <proto/dos.h>
#undef BASE_NAME
/*
** strcpy() && strlen()
*/
#include <string.h>
/*
** SCSI-2 stuff (taken from the ANSI draft, ct 11/1993 and SCSIutil)
*/
#include "cdt_scsi.h"
/***************************************************************************/
/* */
/* prototypes */
/* */
/***************************************************************************/
struct PortIO *OpenSCSI(STRPTR,ULONG);
LONG GetBuffers();
LONG GetArguments();
VOID Main();
LONG StartAudioPlay(LONG,LONG);
LONG PauseResumePlay(LONG);
VOID ShowInfo();
LONG DoScsiCmd(UBYTE *,LONG,UBYTE *,LONG,LONG);
VOID FreeBuffers();
VOID CloseSCSI(struct PortIO *);
VOID PrintF(STRPTR,...);
/***************************************************************************/
/* */
/* ReadArgs() peculiarities + other defines */
/* */
/***************************************************************************/
enum {
DEVICEARG=0,UNITARG,STARTTRACKARG,STARTINDEXARG,LASTTRACKARG,LASTINDEXARG,
LOADARG,EJECTARG,LOCKARG,UNLOCKARG,PLAYARG,STOPARG,PAUSEARG,RESUMEARG,
INFOARG,MAXARG
};
#define TEMPLATE "D=DEVICE,U=UNIT/K/N,STARTTRACK/N,STARTINDEX/N,LASTTRACK/N," \
"LASTINDEX/N,LOAD/S,EJECT/S,LOCK/S,UNLOCK/S,PLAY/S,STOP/S," \
"PAUSE/S,RESUME/S,INFO/S"
#define DEFDEVICE "scsi.device"
#define DEFUNIT 4
#define NEWLIST(l) ((l)->lh_Head = (struct Node *)&(l)->lh_Tail, \
/*(l)->lh_Tail = NULL,*/ \
(l)->lh_TailPred = (struct Node *)&(l)->lh_Head)
/***************************************************************************/
/* */
/* memory clear function (!!! caution: size _MUST_ be a multiple of 4!!!) */
/* */
/***************************************************************************/
STATIC INLINE VOID MEMZEROL(VOID *mem,ULONG size)
{ ULONG *p;
WORD s;
for(p=(ULONG *)mem,s=(size/sizeof(ULONG))-1; s>=0; *p++=NULL,s--);
}
/***************************************************************************/
/* */
/* implementation */
/* */
/***************************************************************************/
LONG Start()
{
struct Globals globals;
MEMZEROL(&globals,sizeof(struct Globals)); gb = &globals;
gb->SysBase = *(struct ExecBase **)4L;
Main();
return 0;
}
/***************************************************************************/
/* */
/* version string */
/* */
/***************************************************************************/
CONST UBYTE verstag[]="$VER: CDT 1.0 (8.11.95) © 1995 by G.Nikl";
/***************************************************************************/
/* */
/* open scsi device */
/* */
/***************************************************************************/
struct PortIO *OpenSCSI(STRPTR DeviceName,ULONG DeviceUnit)
{
struct PortIO *portio;
if ((portio=(struct PortIO *)AllocMem(sizeof(struct PortIO),MEMF_CLEAR|MEMF_PUBLIC)))
{
portio->port.mp_Node.ln_Type=NT_MSGPORT;
if ((BYTE)(portio->port.mp_SigBit=AllocSignal(-1))>=0)
{
portio->port.mp_SigTask=FindTask(NULL);
NEWLIST(&portio->port.mp_MsgList);
portio->req.io_Message.mn_Node.ln_Type=NT_MESSAGE;
portio->req.io_Message.mn_ReplyPort=&portio->port;
if (!(OpenDevice(DeviceName,DeviceUnit,(struct IORequest *)&portio->req,0)))
return portio;
FreeSignal(portio->port.mp_SigBit);
}
FreeMem(portio,sizeof(struct PortIO)); portio=NULL;
}
return portio;
}
/***************************************************************************/
/* */
/* allocate all buffers */
/* */
/***************************************************************************/
LONG GetBuffers()
{
LONG ret=0;
if ((gb->ScsiData=AllocMem(DATALEN,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
if ((gb->SenseBuf=AllocMem(SENSELEN,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
if ((gb->TocBuf=AllocMem(TOCLEN,MEMF_CHIP|MEMF_PUBLIC)) != NULL)
ret=1;
return ret;
}
/***************************************************************************/
/* */
/* read arguments */
/* */
/***************************************************************************/
LONG GetArguments()
{
struct FileSysStartupMsg *fssm;
struct DosList *dol;
struct RDArgs *rda;
STRPTR name,p;
ULONG unit;
LONG args[MAXARG],size,tmp,value,i,*ptr,ret=0;
MEMZEROL(&args[0],sizeof(args));
if ((rda=ReadArgs(TEMPLATE,&args[0],NULL)) != NULL)
{
i=MAXARG-LOADARG; ptr=&args[LOADARG];
do {} while(!(gb->HaveCmd=*ptr++) && --i);
if (args[UNLOCKARG] || args[LOCKARG])
{
gb->Command[0] = SCSI_CMD_PAMR;
gb->Command[4] = (args[LOCKARG] ? 1 : 0);
}
if (args[EJECTARG] || args[LOADARG])
{
gb->Command[0] = SCSI_CMD_SSU;
gb->Command[4] = (args[LOADARG] ? 1 : 0) + 2;
}
if (args[PAUSEARG] || args[RESUMEARG])
{
gb->Command[0] = SCSI_CMD_RQS;
gb->Command[4] = SENSELEN;
((UBYTE *)&gb->Arg1)[3] = (args[RESUMEARG] ? 1 : 0);
}
if (args[STOPARG])
{
gb->Command[0] = SCSI_CMD_SSU;
gb->Command[4] = 0;
}
if (!args[INFOARG] && args[PLAYARG])
{
gb->Command[0] = SCSI_CMD_PLAYAUDIOTRACKINDEX;
value = 1;
if (args[STARTTRACKARG])
{
tmp = *(LONG *)args[STARTTRACKARG];
if (tmp > 0 && tmp < 100)
value = tmp;
}
gb->Command[4] = value; gb->Arg1 = value;
value = 0;
if (args[STARTINDEXARG])
{
tmp = *(LONG *)args[STARTINDEXARG];
if (tmp >= 0 && tmp < 100)
value = tmp;
}
gb->Command[5] = value;
value = 99;
if (args[LASTTRACKARG])
{
tmp = *(LONG *)args[LASTTRACKARG];
if (tmp > 0 && tmp < 100 && tmp > gb->Arg1)
value = tmp;
}
gb->Command[7] = value; gb->Arg2 = value;
value = 0;
if (args[LASTINDEXARG])
{
tmp = *(LONG *)args[LASTINDEXARG];
if (tmp >= 0 && tmp < 100)
value = tmp;
}
gb->Command[8] = value;
}
if (args[INFOARG])
{
gb->Command[0] = SCSI_CMD_INQ;
gb->Command[4] = DATALEN;
}
unit = DEFUNIT;
if (args[UNITARG])
unit = *(ULONG *)args[UNITARG];
gb->ScsiUnit=unit;
name = DEFDEVICE;
if (args[DEVICEARG])
name = (STRPTR)args[DEVICEARG];
if ((size=((tmp=strlen(name))+1+3)&~3) < 256)
size = 256;
if ((gb->ScsiName=AllocVec(size,MEMF_ANY)) != NULL)
{
name=strcpy(gb->ScsiName,name);
if (name[tmp-1] == ':')
{
name[tmp-1] = '\0';
dol=FindDosEntry(LockDosList(LDF_READ|LDF_DEVICES),name,LDF_DEVICES);
name[0] = '\0';
if (dol != NULL)
{
fssm=(struct FileSysStartupMsg *)BADDR(dol->dol_misc.dol_handler.dol_Startup);
if (TypeOfMem(fssm))
{
if (TypeOfMem((p=BADDR(fssm->fssm_Device))))
{
strcpy(name,1+p); gb->ScsiUnit = fssm->fssm_Unit;
}
}
}
UnLockDosList(LDF_READ|LDF_DEVICES);
if (name[0] == '\0')
strcpy(name,DEFDEVICE);
}
ret = 1;
}
FreeArgs(rda);
}
else
PrintFault(IoErr(),NULL);
return ret;
}
/***************************************************************************/
/* */
/* main function */
/* */
/***************************************************************************/
#define CmdLen (gb->Command[0] != SCSI_CMD_PLAYAUDIOTRACKINDEX ? 6 : 10)
VOID Main()
{
LONG err;
if ((gb->DosBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) != NULL)
{
if (GetArguments())
{
if (GetBuffers())
{
if ((gb->ScsiIO=OpenSCSI(gb->ScsiName,gb->ScsiUnit)) != NULL)
{
if (gb->HaveCmd)
{
err = DoScsiCmd(gb->ScsiData,DATALEN,&gb->Command[0],CmdLen,(SCSIF_READ|SCSIF_AUTOSENSE));
if (err != 0 && gb->Command[0] == SCSI_CMD_PLAYAUDIOTRACKINDEX)
err = StartAudioPlay(gb->Arg1,gb->Arg2);
else
switch (gb->Command[0])
{
case SCSI_CMD_RQS:
err = PauseResumePlay(gb->Arg1);
break;
case SCSI_CMD_INQ:
ShowInfo();
default:
break;
}
if (err != 0 && gb->ScsiCmd.scsi_SenseActual >= OFFS_KEY)
PrintF("direct command failed! (Sense: 0x%02lx, Code: 0x%02lx, Qualifier: 0x%02lx)\n",
(LONG)gb->SenseBuf[OFFS_KEY]&0xf,(LONG)gb->SenseBuf[OFFS_CODE],(LONG)gb->SenseBuf[OFFS_QUAL]);
}
CloseSCSI(gb->ScsiIO);
}
else
PrintF("couldn't open `%s' unit `%ld'\n",gb->ScsiName,gb->ScsiUnit);
}
FreeBuffers();
FreeVec(gb->ScsiName);
}
CloseLibrary(&(gb->DosBase->dl_lib));
}
}
/***************************************************************************/
/* */
/* PlayAudioTrackIndex (0x48) failed so try it with another play command */
/* */
/***************************************************************************/
LONG StartAudioPlay(LONG First,LONG Last)
{
UBYTE *data,*toc;
LONG err,tmp,index;
data=&gb->Command[0];
*(LONG *)&data[0] = 0; *(LONG *)&data[4] = 0; *(LONG *)&data[8] = 0;
data[0] = SCSI_CMD_READTOC;
data[7] = ((TOCLEN >> 8) & 0xFF);
data[8] = ((TOCLEN >> 0) & 0xFF);
if ((err=DoScsiCmd(gb->TocBuf,TOCLEN,data,10,(SCSIF_READ|SCSIF_AUTOSENSE))) == 0)
{
toc=gb->TocBuf;
if ((tmp=toc[3]) < Last)
if ((Last=tmp) < First)
First = 1;
data[0] = SCSI_CMD_PLAYAUDIO12;
index = 8*First;
First = 1 + ((toc[index] << 24) | (toc[index+1] << 16) | (toc[index+2] << 8) | (toc[index+3]));
data[2] = ((First >> 24) & 0xFF);
data[3] = ((First >> 16) & 0xFF);
data[4] = ((First >> 8) & 0xFF);
data[5] = ((First >> 0) & 0xFF);
index = 8*Last+8;
Last = -2 + ((toc[index] << 24) | (toc[index+1] << 16) | (toc[index+2] << 8) | (toc[index+3]));
Last -= First;
data[6] = ((Last >> 24) & 0xFF);
data[7] = ((Last >> 16) & 0xFF);
data[8] = ((Last >> 8) & 0xFF);
data[9] = ((Last >> 0) & 0xFF);
err = DoScsiCmd(gb->ScsiData,DATALEN,data,12,(SCSIF_READ|SCSIF_AUTOSENSE));
}
return err;
}
/***************************************************************************/
/* */
/* Pause / Resume audio play (REQUEST SENSE was done before) */
/* */
/***************************************************************************/
LONG PauseResumePlay(LONG What)
{
UBYTE *data = gb->ScsiData;
LONG audio,err = 0;
if ((BYTE)(data[OFFS_KEY]&0xf) == 0)
{
audio = data[OFFS_QUAL];
if ((audio == 0x11 && What == 0) || (audio == 0x12 && What == 1))
{
data=&gb->Command[0];
*(LONG *)&data[0] = 0; *(LONG *)&data[4] = 0; *(LONG *)&data[8] = 0;
data[0] = SCSI_CMD_PAUSERESUME;
data[8] = What;
err = DoScsiCmd(gb->ScsiData,DATALEN,data,10,(SCSIF_READ|SCSIF_AUTOSENSE));
}
}
return err;
}
/***************************************************************************/
/* */
/* display inquiry information */
/* */
/***************************************************************************/
CONST UBYTE *CONST DeviceType[] = {
"Direct-access device (e.g., magnetic disk)",
"Sequential-access device (e.g., magnetic tape)",
"Printer device",
"Processor device",
"Write-once device (e.g., some optical disks)",
"CD-ROM device",
"Scanner device",
"Optical memory device (e.g., some optical disks)",
"Medium Changer device (e.g., jukeboxes)",
"Communications device",
"Defined by ASC IT8 (Graphic Arts Pre-Press Devices)",
"Defined by ASC IT8 (Graphic Arts Pre-Press Devices)",
"Reserved, unknown or no device type"
};
CONST UBYTE *CONST AnsiVersion[] = {
"The device might or might not comply to an ANSI-approved standard.",
"The device complies to ANSI X3.131-1986 (SCSI-1).",
"The device complies to ANSI X?.???-???? (SCSI-2).",
"Reserved",
};
CONST UBYTE *CONST ResponseFormat[] = {
"SCSI-1",
"CCS",
"SCSI-2",
"Reserved",
};
CONST UBYTE *CONST DataTransfer[] = {
"8-bit only",
"16-bit",
"32-bit",
"16 and 32-bit"
};
VOID ShowInfo()
{
UBYTE *data=gb->ScsiData;
STRPTR p1,p2;
ULONG index;
if ((index=data[0]&0x1f) > 0x0b)
index = 0x0c;
PrintF("Device type : %s\n",DeviceType[index]);
if ((index=data[2]&0x07) > 0x02)
index = 0x03;
PrintF("ANSI-approved version: %s\n",AnsiVersion[index]);
if ((index=data[3]&0x0f) > 0x02)
index = 0x03;
PrintF("Response data format : %s\n",ResponseFormat[index]);
PrintF("Vendor : %.8s\n",&data[8]);
PrintF("Product : %.16s\n",&data[16]);
PrintF("Revision : %.4s\n",&data[32]);
index = (data[7]&0x60)>>5;
PrintF("Transfer : %s\n",DataTransfer[index]);
p1 = "not removable"; p2 = p1 + 4;
PrintF("Medium : %s\n",(data[1]&0x80 ? p2 : p1));
p1 = "not supported"; p2 = p1 + 4;
PrintF("Relative addressing : %s\n",(data[7]&0x80 ? p2 : p1));
PrintF("Synchronous transfer : %s\n",(data[7]&0x10 ? p2 : p1));
PrintF("Linked command : %s\n",(data[7]&0x08 ? p2 : p1));
PrintF("Command queuing : %s\n",(data[7]&0x02 ? p2 : p1));
PrintF("Soft reset : %s\n",(data[7]&0x01 ? p2 : p1));
}
/***************************************************************************/
/* */
/* issue a scsi command */
/* */
/***************************************************************************/
LONG DoScsiCmd(UBYTE *data,LONG datasize,UBYTE *cmd,LONG cmdsize,LONG flags)
{
struct PortIO *portio;
struct SCSICmd *scmd;
portio = gb->ScsiIO;
portio->req.io_Command = HD_SCSICMD;
scmd = &gb->ScsiCmd;
portio->req.io_Data = (APTR)scmd;
portio->req.io_Length = sizeof(struct SCSICmd);
scmd->scsi_Data = (APTR)data;
scmd->scsi_Length = datasize;
scmd->scsi_SenseActual = 0;
scmd->scsi_SenseData = gb->SenseBuf;
scmd->scsi_SenseLength = SENSELEN;
scmd->scsi_Command = cmd;
scmd->scsi_CmdLength = cmdsize;
scmd->scsi_Flags = flags;
DoIO((struct IORequest *)&portio->req);
return portio->req.io_Error;
}
/***************************************************************************/
/* */
/* free all buffers */
/* */
/***************************************************************************/
VOID FreeBuffers()
{
APTR buf;
if ((buf=gb->TocBuf) != NULL)
FreeMem(buf,TOCLEN);
if ((buf=gb->SenseBuf) != NULL)
FreeMem(buf,SENSELEN);
if ((buf=gb->ScsiData) != NULL)
FreeMem(buf,DATALEN);
}
/***************************************************************************/
/* */
/* close scsi device */
/* */
/***************************************************************************/
VOID CloseSCSI(struct PortIO *portio)
{
CloseDevice((struct IORequest *)&portio->req);
FreeSignal(portio->port.mp_SigBit);
FreeMem(portio,sizeof(struct PortIO));
}
/***************************************************************************/
/* */
/* vararg printf() with VPrintf() from the dos.library (can't use Printf())*/
/* */
/***************************************************************************/
VOID PrintF(STRPTR format,...)
{
VPrintf(format,(APTR)(&format+1));
}
/***************************************************************************/
/* */
/* The End */
/* */
/***************************************************************************/