📄 aspi.c
字号:
if ( (i=GetDeviceTyp( TARGET )) < 0 ) {
( void ) fprintf(stderr,
"aspiinit: Can't determine type of device \"%s\"\n", tapeid);
( void ) fprintf(stderr,"aspiinit: GetDeviceTyp() returned errno %d\n", i);
exit(EX_SYSTEM);
} else if ( i != 1 ) {
( void ) fprintf(stderr,"aspiinit: device \"%s\" is not a streamer !\n",
tapeid);
( void ) fprintf(stderr,"the typ returned by GetDeviceTyp was %d\n",i);
exit(EX_SYSTEM);
}
/*
* Now get the max. and min. recordsize for the streamer
*/
if ( (i=SCSIReadBlockLimits(TARGET, &lim, 0)) != E$NoErr ) {
( void ) fprintf(stderr,"aspiinit: Can't read blocklimits. errno %d\n", i);
exit(EX_SYSTEM);
}
/*
* *** FIXME ***
* I don't really know how to handle this. What I do is, check if we have
* fixed record size (lim.max == lim.min), if this is not true, I don't
* really know which record size I should take. For now I try 512 bytes,
* and if 512 is not in range I try lim.min. This is probably not the
* way to do it. Let me know if you know better.
* chris@alderan.sdata.de
*/
if ( lim.max == lim.min ) recsize = lim.max;
else if ( (lim.min <= 512) && (lim.max>=512) ) recsize = 512;
else recsize = lim.min;
l = recsize; logrec = 0;
while ( (l>>=1) ) ++logrec; /* logrec = log2(recsize) */
#endif /* CTCTRL */
}
/*
* This is the function that we call for all out aspi-requests.
* The function simply takes our requestblock and hands it to
* aspi() (the real aspi request function) and then it polls
* and waits for the request to finish.
*/
int aspireq(srb)
void *srb;
{
int cnt;
struct _srbinquiry *s;
s = ( struct _srbinquiry *) srb;
aspi(s);
cnt = 10;
while ( cnt-- ) while ( ! s->h.status ) ; /* POLL ! */
if ( s->h.status == 1 ) return E$NoErr;
return E$AspiErr;
}
/*
* The following two commandos are supported directly by the ASPI module
* and do not require the construction of a SCSI-CCB.
*/
int HostAdapterInquiry(inq)
aspiinquiry *inq;
{
struct _srbinquiry *srb;
int i;
/* allocate a SCSI Request Block (SRB) in the lower 1 MB */
if ( (srb=calloc(sizeof(struct _srbinquiry), 1)) == ( char *) 0 )
return(E$NoMem);
srb->h.cmd = 0; /* Host Adapter Inquiry */
srb->h.adapter = inq->adapter_num;
/* issue the request */
if ( (i=aspireq(srb)) ) { /* if error status */
free(srb);
return(i);
}
inq->adapters = srb->adapters; /* number of hostadapters */
inq->target_id = srb->target_id;
for(i=0; i<16; ++i) inq->manager_id[i] = srb->manager_id[i];
inq->manager_id[16] = '\0';
for(i=0; i<16; ++i) inq->adapter_id[i] = srb->adapter_id[i];
inq->adapter_id[16] = '\0';
free(srb);
return(E$NoErr);
}
/*
* GetDeviceTyp: The returned typ corresponds to the typ of an
* SCSI-Inquiry command.
*/
int GetDeviceTyp(adapter, target_id, lun)
int adapter;
int target_id;
int lun;
{
struct _srbgettyp *srb;
int i;
/* allocate a SCSI Request Block (SRB) */
if ( (srb=calloc(sizeof( struct _srbgettyp), 1)) == 0 ) return(E$NoMem);
srb->h.cmd = 1;
srb->h.adapter = adapter;
srb->target_id = target_id;
srb->lun = lun;
/* Issue the request */
if ( (i=aspireq(srb)) ) {
switch ( srb->h.status ) {
case 0x82:
i = E$NoDevice;
break;
case 0x80:
i = E$AspiInval;
break;
case 0x81:
i = E$NoAdapter;
break;
case 0x02:
i = E$Abort;
break;
}
} else i = srb->typ;
( void ) free(srb);
return(i);
}
/*
* The ScsiIoError function is used to generate an unique errorcode
* from the three different errorcode sources.
* The errorcode sources are:
* - The exit status of the aspi request
* - The host adapter status
* - The scsi target status
* - The sense data structure
*
* Ahhmm ..... actually this makes FOUR different sources not three :-)
* The function is local to this module and called by all the SCSI-IO
* functions upon exit.
*/
static int ScsiIoError(aspi_status, adapter_status, target_status, sense)
int aspi_status;
int adapter_status;
int target_status;
unsigned char *sense;
{
int i;
switch ( aspi_status ) { /* check the aspi status */
case 0x82:
i = E$NoDevice;
break;
case 0x80:
i = E$AspiInval;
break;
case 0x81:
i = E$NoAdapter;
break;
case 0x02:
i = E$Abort;
break;
case 0x04:
/*
* Ok, this means scsi-io-error, so we see if
* we can find more details about the error.
*/
i = E$IOErr;
if ( adapter_status ) {
switch ( adapter_status ) {
case 0x11:
i = E$SelTimeout;
break;
case 0x12:
i = E$DataOverrun;
break;
case 0x13:
i = E$BusFree;
break;
case 0x14:
i = E$BusFail;
break;
}
} else switch ( target_status ) {
/*
* If the adapter didn't show any errors
* we going to check the target to see if
* the target was the source of the error.
*/
case 0x08:
i = E$TargetBusy;
break;
case 0x18:
i = E$Reservation;
break;
case 0x02:
/*
* Allright, the target has send
* sense data to the sense-data allocation
* area at the end of the srb.
*/
if ( sense != ( unsigned char *) 0 ) switch ( sense[2] & 0x0f ) {
case 0x00: /* This means "no sense", but we check for End of Medium */
if ( sense[2] & 0x40 ) i = E$EndOfMedium;
break;
case 0x01:
i = E$NoErr;/* this would be pretty stupid to report, but anyway */
break;
case 0x02:
i = E$NotReady;
break;
case 0x03:
i = E$Medium;
break;
case 0x04:
i = E$Hardware;
break;
case 0x05:
i = E$IllegalReq;
break;
case 0x06:
i = E$UnitAttention;
break;
case 0x07:
i = E$DataProtect;
break;
case 0x08:
i = E$BlankCheck;
break;
case 0x0b:
i = E$TargetAbort;
break;
case 0x0d:
i = E$VolOverflow;
break;
}
break;
}
break;
}
return(i);
}
int SCSIInquiry(adapter, target_id, lun, inq, sense)
int adapter;
int target_id;
int lun;
scsiinquiry far *inq;
unsigned char *sense;
{
struct _srbio *srb;
int i,j;
/* allocate a SCSI Request Block (SRB) */
if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
srb->h.cmd = 2;
srb->h.adapter = adapter;
srb->h.flags = (1<<3);
srb->target_id = target_id;
srb->lun = lun;
srb->buf_seg = FP_SEG(inq);
srb->buf_off = FP_OFF(inq);
srb->alloc_len = sizeof( scsiinquiry );
srb->sense_len = 14;
srb->cdb_len = 6;
srb->ccb.inq.cmd = 0x12;
srb->ccb.inq.lun = lun;
srb->ccb.inq.len = sizeof( scsiinquiry );
if ( (i=aspireq(srb)) ) {
i = ScsiIoError(srb->h.status, srb->adapter_status,
srb->target_status, srb->ccb.inq.sense);
}
if ( sense ) for(j=0; j<14; ++j) sense[j] = srb->ccb.inq.sense[j];
( void ) free(srb);
return(i);
}
int SCSIResetDevice(adapter, target_id, lun)
int adapter;
int target_id;
int lun;
{
struct _srbreset *srb;
int i;
/* allocate a SCSI Request Block (SRB) */
if ( (srb=calloc(sizeof(struct _srbreset), 1)) == 0 ) return(E$NoMem);
srb->h.cmd = 4;
srb->h.adapter = 0;
srb->target_id = target_id;
srb->lun = lun;
if ( (i=aspireq(srb)) )
i = ScsiIoError(srb->h.status, srb->adapter_status,
srb->target_status, ( unsigned char far * ) 0);
( void ) free (srb);
return(i);
}
/*
* The following commands are "Sequencial-Access Device" specific.
*/
int SCSIErase(adapter, target_id, lun, immediate, lng, sense)
int adapter;
int target_id;
int lun;
int immediate;
int lng;
unsigned char *sense;
{
struct _srbio *srb;
int i;
/* allocate a SCSI Request Block (SRB) */
if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
srb->h.cmd = 2;
srb->h.adapter = adapter;
srb->target_id = target_id;
srb->lun = lun;
srb->sense_len = 14;
srb->cdb_len = 6;
srb->ccb.c6.cmd = 0x19;
srb->ccb.c6.flag0 = lng;
srb->ccb.c6.flag1 = immediate;
srb->ccb.c6.lun = lun;
if ( (i=aspireq(srb)) ) {
if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.c6.sense[i];
i = ScsiIoError(srb->h.status, srb->adapter_status,
srb->target_status, srb->ccb.c6.sense);
}
( void ) free(srb);
return(i);
}
int SCSILoad(adapter, target_id, lun, immediate, load, retention, eot, sense)
int adapter;
int target_id;
int lun;
int immediate;
int load;
int retention;
int eot;
unsigned char *sense;
{
struct _srbio *srb;
int i;
/* allocate a SCSI Request Block (SRB) */
if ( (srb=calloc(sizeof(struct _srbio), 1)) == 0 ) return(E$NoMem);
srb->h.cmd = 2;
srb->h.adapter = adapter;
srb->target_id = target_id;
srb->lun = lun;
srb->sense_len = 14;
srb->cdb_len = 6;
srb->ccb.ld.cmd = 0x1b;
srb->ccb.ld.immediate = immediate;
srb->ccb.ld.lun = lun;
srb->ccb.ld.load = load;
srb->ccb.ld.retention = retention;
srb->ccb.ld.eot = eot;
if ( (i=aspireq(srb)) ) {
if ( sense ) for(i=0; i<14; ++i) sense[i] = srb->ccb.ld.sense[i];
i = ScsiIoError(srb->h.status, srb->adapter_status,
srb->target_status, srb->ccb.ld.sense);
}
( void ) free(srb);
return(i);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -