home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1993 #2
/
Image.iso
/
os2
/
gtak212b.zip
/
SOURCE.ZIP
/
TAPE
/
scsiaspi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-05
|
8KB
|
395 lines
/*****************************************************************************
* $Id: scsiaspi.c,v 1.3 1992/10/04 22:15:38 ak Exp $
*****************************************************************************
* $Log: scsiaspi.c,v $
* Revision 1.3 1992/10/04 22:15:38 ak
* Updated DOS version, scsi_name() was missing. There seems to be some
* request for GTAK10x (DOS) with DAT.
*
* Revision 1.2 1992/09/02 19:05:35 ak
* Version 2.0
* - EMX version
* - AIX version
* - SCSI-2 commands
* - ADD Driver
* - blocksize support
*
* Revision 1.1.1.1 1992/01/06 20:27:32 ak
* Interface now based on ST01 and ASPI.
* AHA_DRVR no longer supported.
* Files reorganized.
*
* Revision 1.1 1992/01/06 20:27:30 ak
* Initial revision
*
*****************************************************************************/
static char *rcsid = "$Id: scsiaspi.c,v 1.3 1992/10/04 22:15:38 ak Exp $";
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#ifdef OS2
#error "ASPI interface not usable for OS/2"
#endif
#include <io.h>
#include <fcntl.h>
#include <dos.h>
#include "aspi.h"
#include "scsi.h"
static int trace;
static int handle;
static void (_far * api)(SRB _far *);
SenseMode senseMode = SenseKey;
static long blocksize = 512;
#define ASPI(srb) (*api)(srb)
static void
fatal(char *msg, ...)
{
va_list ap;
fprintf(stderr, "Fatal SCSI error: ");
va_start(ap, msg);
vfprintf(stderr, msg, ap);
va_end (ap);
fprintf(stderr, "\n");
exit (2);
}
static void
command(SRB *srb)
{
int i;
printf("SCSI op:");
for (i = 0; i < srb->u.cmd.cdb_len; ++i)
printf(" %02X", srb->u.cmd.cdb_st[i]);
printf("\n");
}
static void
status(SRB *srb)
{
int i;
printf("SCSI status:");
for (i = 0; i < srb->u.cmd.sense_len; ++i) {
if (i && (i % 16) == 0)
printf("\n ");
printf(" %02X", srb->u.cmd.cdb_st[srb->u.cmd.cdb_len + i]);
}
printf("\n");
}
void
scsi_init(void)
{
union REGS r;
struct SREGS sr;
char *cp;
#ifndef OS2
if (_osmajor >= 10)
fatal("Cannot use SCSI interface in OS/2 DOS mode\n");
#endif
if ((handle = open("SCSIMGR$", O_BINARY|O_RDWR)) < 0)
fatal("SCSI Manager not found\n");
r.x.ax = 0x4402; /* Ioctl Read */
sr.ds = FP_SEG((void _far *)&api);
r.x.dx = FP_OFF((void _far *)&api);
r.x.cx = 4;
r.x.bx = handle;
intdosx(&r, &r, &sr);
if (r.x.cflag)
fatal("SCSI Manager Ioctl failure\n");
if ((cp = getenv("TAPEMODE")) != NULL)
senseMode = atoi(cp);
}
void
scsi_file(int fd)
{
scsi_init();
}
void
scsi_name(char *name)
{
scsi_init();
}
void
scsi_term(void)
{
close(handle);
}
void
scsi_trace(int level)
{
trace = level;
}
void *
scsi_alloc(void)
{
void *p = malloc(sizeof(SRB));
if (p == NULL)
fatal("No memory for SCSI Request Block\n");
}
void
scsi_free(void *p)
{
free(p);
}
int
scsi_start(void *ctrl,
int target, int lun,
void *cdb, int cdb_len, int sense_len,
void far *data, long data_len,
int readflag)
{
SRB *srb = ctrl;
srb->cmd = SRB_Command;
srb->status = SRB_Busy;
srb->ha_num = 0;
srb->flags = data_len ? readflag ? SRB_Read : SRB_Write
: SRB_NoTransfer;
srb->u.cmd.target = target;
srb->u.cmd.lun = lun;
srb->u.cmd.data_len = data_len;
srb->u.cmd.sense_len = sense_len;
srb->u.cmd.data_ptr = data;
srb->u.cmd.link_ptr = 0;
srb->u.cmd.cdb_len = cdb_len;
memcpy(srb->u.cmd.cdb_st+0, cdb, cdb_len);
memset(srb->u.cmd.cdb_st+cdb_len, 0, sense_len);
if (trace)
command(srb);
ASPI(srb);
if (trace >= 2)
printf("SRB status: %02X\n", srb->status);
switch (srb->status) {
case SRB_Busy:
case SRB_Error:
return ComeAgain;
case SRB_Done:
return NoError;
default:
return DriverError + srb->status;
}
}
int
scsi_wait(void *ctrl, void *sense, int wait)
{
SRB *srb = ctrl;
int i, slen, ret;
unsigned char *sptr;
for (;;) {
if (trace >= 2)
printf("SRB status: %02X\n", srb->status);
switch (srb->status) {
case SRB_Busy:
if (wait) {
union REGS r;
/* DESQview - give up timeslice */
r.x.ax = 0x1000;
int86(0x15, &r, &r);
/* Windows 3+ - give up timeslice */
r.x.ax = 0x1680;
int86(0x2F, &r, &r);
continue;
}
return ComeAgain;
case SRB_Error:
break;
case SRB_Done:
return NoError;
default:
return DriverError + srb->status;
}
break;
}
if (srb->u.cmd.ha_status) {
if (trace)
printf("SCSI host adapter error: %02X\n",
srb->u.cmd.ha_status);
return HostError + srb->u.cmd.ha_status;
}
switch (srb->u.cmd.target_status) {
case GoodStatus:
return NoError;
case CheckStatus:
break;
default:
if (trace)
printf("SCSI completion status: %02X\n",
srb->u.cmd.target_status);
return StatusError + srb->u.cmd.target_status;
}
slen = srb->u.cmd.sense_len ? srb->u.cmd.sense_len : 14;
memcpy(sense, srb->u.cmd.cdb_st + srb->u.cmd.cdb_len, slen);
if (trace)
status(srb);
sptr = (unsigned char *)sense;
if ((sptr[0] & 0x7E) != 0x70)
return ExtendedError + (sptr[0] & 0x7F);
if (srb->u.cmd.sense_len <= 2)
return UnknownError;
return SenseKey + (sptr[2] & 0x0F);
}
int
scsi_cmd(int target, int lun,
void *cdb, int cdb_len, void *sense, int sense_len,
void far *data, long data_len,
int readflag)
{
SRB srb;
int ret;
ret = scsi_start(&srb,
target, lun,
cdb, cdb_len, sense_len,
data, data_len,
readflag);
while (ret == ComeAgain)
ret = scsi_wait(&srb, sense, 1);
return ret;
}
int
scsi_reset(int target, int lun, int bus)
{
SRB srb;
srb.cmd = SRB_Reset;
srb.status = SRB_Busy;
srb.ha_num = 0;
srb.flags = SRB_NoTransfer;
srb.u.res.target = target;
srb.u.res.lun = lun;
ASPI(&srb);
for (;;) {
switch (srb.status) {
case SRB_Busy:
continue;
case SRB_Done:
return NoError;
default:
return DriverError + srb.status;
}
}
}
long
scsi_get_blocksize(int target, int lun)
{
return blocksize;
}
long
scsi_set_blocksize(int target, int lun, long size)
{
long old = blocksize;
blocksize = size;
return old;
}
int
scsi_set_trace(int level)
{
int old = trace;
trace = level;
return old;
}
char *
scsi_error(int code)
{
static char text[80];
static ErrorTable driverTab[] = {
SRB_Aborted, "Command aborted",
SRB_BadAbort, "Could not abort",
SRB_InvalidCmd, "Invalid ASPI request",
SRB_InvalidHA, "Invalid host adapter",
SRB_BadDevice, "Device not installed",
-1
};
static ErrorTable hostTab[] = {
/* Adaptec 154x host adapter status */
SRB_NoError, "No error",
SRB_Timeout, "Selection timeout",
SRB_DataLength, "Data length error",
SRB_BusFree, "Unexpected bus free",
SRB_BusSequence, "Target bus sequence failure",
-1
};
if (code == 0)
return "No error";
if (code == ComeAgain)
return "Busy";
switch (ErrorClass(code)) {
case SenseKey:
return senseTab[code & 0x0F];
case ExtendedError:
switch (senseMode) {
case TDC3600:
sprintf(text, "Error code: %s",
find_error(tdc3600ercd, ErrorCode(code)));
break;
default:
sprintf(text, "Additional sense code: %02X",
ErrorCode(code));
}
break;
case StatusError:
sprintf(text, "Target status: %s",
find_error(targetStatusTab, ErrorCode(code)));
break;
case DriverError:
sprintf(text, "Driver error: %s",
find_error(driverTab, ErrorCode(code)));
break;
case SystemError:
sprintf(text, "System error: %u", ErrorCode(code));
break;
case HostError:
sprintf(text, "Host adapter error: %s",
find_error(hostTab, ErrorCode(code)));
break;
default:
sprintf(text, "Other error: %04X", code);
break;
}
return text;
}