
/*
 *  READPAGE.C
 *
 */

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/scsidisk.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

typedef unsigned char ubyte;

typedef struct MsgPort	MsgPort;
typedef struct IOStdReq IOStdReq;
typedef struct SCSICmd	SCSICmd;

typedef struct SCSIReq {
    IOStdReq sr_Req;
    SCSICmd  sr_Cmd;
} SCSIReq;

MsgPort *IoSink;
SCSIReq Ios;

char *ErrorAry[] = {
    "No Sense",
    "Recovered Error",
    "Not Ready",
    "Medium Error",
    "Hardware Error",
    "Illegal Request",
    "Unit Attention",
    "Data Protect",
    "Blank Check",
    "Vendor Specific",
    "Copy Aborted",
    "Aborted Command",
    "Equal (search_data)",
    "Volume Overflow",
    "MisCompare",
    "Reserved"
};

void myexit(void);

main(ac, av)
char *av[];
{
    atexit(myexit);

    IoSink = CreatePort(NULL, 0);

    if (SCSIOpen("scsi.device", 4) < 0) {
	puts("Unable to open scsi.device");
	exit(20);
    }
    if (ac == 1) {
	short i;
	for (i = 0; i < 0x40; ++i)
	    ReadPage(i);
    } else {
	ReadPage(strtol(av[1], NULL, 0));
    }
    return(0);
}

ReadPage(pageNo)
short pageNo;
{
    __aligned char modeSenseCmd[] = { 0x1A, 0x00, pageNo, 0x00, 0xFF, 0x00 };
    unsigned char buf[512];
    int error;
    long len;

    if (error = DoSCSI(modeSenseCmd, buf, sizeof(buf), SCSIF_READ, &len)) {
	char *errorStr = (error > 0 && error < 16) ? ErrorAry[error] : "?";
	printf("error code %2d (0x%02x) %s\n", error, error, errorStr);
    } else {
	short i;

	for (i = 0; i < len; ++i) {
	    if (i && (i & 7) == 0)
		puts("");
	    printf(" %02x", buf[i]);
	}
	puts("");
    }
    return(error);
}

void
myexit(void)
{
    SCSIClose();
    if (IoSink)
	DeletePort(IoSink);
}


int
SCSIOpen(devName, unitNo)
char *devName;
long unitNo;
{
    int error;

    Ios.sr_Req.io_Message.mn_ReplyPort = IoSink;
    if (error = OpenDevice(devName, unitNo, &Ios.sr_Req, 0))
	error = -1;
    return(error);
}

int
SCSIClose()
{
    if (Ios.sr_Req.io_Device)
	CloseDevice(&Ios);
}

int
DoSCSI(cmd, buf, bytes, flags, len)
char *cmd;
char *buf;
long bytes;
ubyte flags;
long *len;
{
    static ubyte senseCmd[] = { 0x03, 0x00, 0x00, 0x00, 20, 0 };
    SCSIReq *ios = &Ios;
    char senseBuf[20];
    int error;

    ios->sr_Cmd.scsi_Command   = cmd;
    ios->sr_Cmd.scsi_CmdLength = 6;
    ios->sr_Cmd.scsi_Data   = buf;
    ios->sr_Cmd.scsi_Length = bytes;
    ios->sr_Cmd.scsi_Flags  = flags;

    ios->sr_Req.io_Command = 28;
    ios->sr_Req.io_Data    = &ios->sr_Cmd;
    ios->sr_Req.io_Length  = sizeof(ios->sr_Cmd);

    error = DoIO(&ios->sr_Req);
    if (len)
	*len = ios->sr_Cmd.scsi_Actual;

    switch(error) {
    case 0:
	break;
    case HFERR_BadStatus:
	ios->sr_Cmd.scsi_Command   = senseCmd;
	ios->sr_Cmd.scsi_CmdLength = 6;
	ios->sr_Cmd.scsi_Data	= (UWORD *)senseBuf;
	ios->sr_Cmd.scsi_Length = sizeof(senseBuf);
	ios->sr_Cmd.scsi_Flags	= SCSIF_READ;

	if (DoIO(&ios->sr_Req)) {
	    error = -256;
	    break;
	}
	if (ios->sr_Cmd.scsi_Actual < 4) {
	    error = -257;
	    break;
	}
	error = senseBuf[2];
	break;
    default:
	error = -error;
	break;
    }
    return(error);
}

