home *** CD-ROM | disk | FTP | other *** search
- #include "modern.h"
- #ifdef MSDOS
- #include <stdio.h>
- #include "pctimer.h"
- #include "define.h"
- #include <string.h>
-
- #define NILTIME 0
- #define MINTIME 6 /* ~0.3s */
- #define TRESET (unsigned short)SEC2TICK(3)
- #define MIDTIME (unsigned short)SEC2TICK(10)
- #define MAXTIME (unsigned short)SEC2TICK(300)
- #define HALTCPU
-
- #define MAXLEX 8
- #define UNKNOWN 255
-
- void far (*ASPI_ptr)(void far *) = (void far (*)())0xffff0000L;
- extern int ASPI_entry(void far (* far *)());
-
- #define HA_INQ 0 /* host adapter inquiry */
- #define GET_TYPE 1 /* get device type */
- #define EXEC_SIO 2 /* execute SCSI I/O command */
- #define ABORT_SRB 3 /* abort SCSI I/O command */
- #define RESET_DEV 4 /* reset SCSI device */
- #define SET_HAP 5 /* set host adapter parameters */
- #define GET_DI 6 /* get disk drive information */
-
- #define TAPE 1 /* SCSI device type */
-
- #ifndef byte
- # define byte unsigned char
- #endif
- #define SRBHEAD byte command, status, adapter, flags, reserved[4]
- #define MAX_CDB 6 /* Group 0 commands only */
- #define MAX_SENCE 14 /* ??? */
-
- struct _srbinquiry {
- SRBHEAD, ha_total, ha_type, mgr_id[16], ha_id[16], hap[16];
- };
- struct _srbgettype {
- SRBHEAD, target, lun, devtype;
- };
- struct _srbabort {
- SRBHEAD, pointer[4];
- };
- struct _srbio {
- SRBHEAD, target, lun,
- datalength[4], sencelength, databuffer[4], srblink[4], cdblength,
- adapter_status, target_status, post_routine[4],
- workspace[34], area[MAX_CDB + MAX_SENCE];
- };
- struct _srbreset {
- SRBHEAD, target, lun, dummy[14],
- adapter_status, target_status, post_routine[4], workspace[34];
- };
- struct _cdbtape {
- byte opcode, unit, counter[3], control;
- };
-
- /* SCSI tape opcodes */
- #define S0P_TEST 0 /* test unit ready */
- #define S0P_REWIND 1
- #define S0P_LIMITS 5 /* read block limits */
- #define S0P_READ 8
- #define S0P_WRITE 10
- #define S0P_WFM 16 /* write file mark */
- #define S0P_SPACE 17
- #define S0P_INQ 18
- #define S0P_MODE 21 /* mode select */
- #define S0P_ERASE 25
- #define S0P_MSENCE 26 /* mode sence */
-
- /* Transfer direction bits */
- #define T_INHERIT 000 /* Command-dependent*/
- #define T_READ 010 /* Read from target */
- #define T_WRITE 020 /* Write to target */
- #define T_NONE 030 /* No data transfer */
-
- #define ASPI_EMPTY 0
- #define ASPI_QUEUED 0
- #define ASPI_SUCCESS 1
- #define ASPI_SENCE 2
- #define ASPI_ABORTED 2
- #define ASPI_BUSY 8
- #define ASPI_INVALID 0x80 /* illegal request */
- #define ASPI_NoHA 0x81 /* invalid host adapter */
- #define ASPI_ABSENT 0x82 /* device not installed */
- #define SCSI_SENCE 0x20
- #define SCSI_SENCEOK 0x20
- #define SCSI_RECOVER 0x21
- #define SCSI_BUSY 0x22
- #define SCSI_INVALID 0x25 /* illegal request */
- #define SCSI_ATTN 0x26 /* unit attention */
- #define SCSI_BLANK 0x28
- #define SCSI_ILI 0x35 /* incorrect length indicator */
- #define SCSI_EOM 0x36 /* end-of-medium */
- #define SCSI_FM 0x37 /* hit file mark */
-
- int aspierrno;
- struct { byte code; char *text; } aspierrlist[] = {
- { 0x00, "SCSI request in progress" },
- { 0x01, "SCSI request completed without error"},
- { 0x02, "SCSI request aborted by host" },
- { 0x04, "SCSI request completed with error" },
- { 0x08, "Specified Target/LUN is busy" },
- { 0x11, "Selection timeout" },
- { 0x12, "Data over-run/under-run" },
- { 0x13, "Unexpected Bus Free" },
- { 0x14, "Target bus phase sequence failure" },
- { 0x18, "Reservation conflict" },
-
- { 0x20, "No sence" }, /* My codes */
- { 0x21, "Recovered error" },
- { 0x22, "Not ready" },
- { 0x23, "Medium error" },
- { 0x24, "Hardware error" },
- { 0x25, "Illegal request" },
- { 0x26, "Unit attention" },
- { 0x27, "Data protect" },
- { 0x28, "Blank check" },
- { 0x29, "Vendor unique" },
- { 0x2A, "Copy aborted" },
- { 0x2b, "Aborted command" },
- { 0x2C, "Equal" },
- { 0x2d, "Volume overflow" },
- { 0x2E, "Miscompare" },
- { 0x2f, "Reserved sence key"},
-
- { 0x35, "Incorrect length" },
- { 0x36, "End of medium" },
- { 0x37, "File mark reached" },
-
- { 0x80, "Invalid SCSI request" }, /* ASPI codes again */
- { 0x81, "Invalid Host Adapter Number"},
- { 0x82, "SCSI device not installed" },
- };
-
- char *aspierrmsg(int n)
- {
- static char h[16] = "0123456789ABCDEF";
- static char vendor[] = "Vendor unique, class ? code ?h";
- static char other[] = "Error ??h";
- register i;
-
- for (i=0; i<sizeof(aspierrlist)/sizeof(aspierrlist[0]); i++) {
- if (aspierrlist[i].code == n) return aspierrlist[i].text;
- }
- if (n >= 0x70 && n <= 0xff) {
- vendor[21] = n >= 0xf0 ? '0' : h[(n >> 4) & 7];
- vendor[28] = h[n & 15];
- return vendor;
- }
- other[6] = h[(n >> 4) & 15];
- other[7] = h[ n & 15];
- return other;
- }
-
- int aspicall(struct _srbio *s, unsigned timeout)
- {
- unsigned long t0;
- struct _srbabort sa;
- register unsigned char *p;
-
- *(long *)(s->reserved) = 0L; /* clear reserved field */
- (*ASPI_ptr)((void far *)s);
- if (s->status != ASPI_QUEUED || timeout == 0) goto test;
- for (t0 = pctimer();;) {
- if (s->status != ASPI_QUEUED) goto test;
- if (pctimer() - t0 > timeout) break;
- HALTCPU;
- }
- /* Timeout expired - abort the request */
- sa.command = ABORT_SRB;
- sa.adapter = s->adapter;
- sa.flags = 0;
- *(long *)sa.reserved = 0L;
- *(void far * far *)sa.pointer = (void far *)s;
- (void)(*ASPI_ptr)((void far *)&sa);
- /* Wait till IO aborted */
- for (t0=pctimer(); 1 >= pctimer()-t0;) HALTCPU;
- if (s->status == ASPI_QUEUED) s->status = ASPI_ABORTED;
- test:
- if (s->status & 0x80) return s->status;
- if (s->adapter_status != ASPI_EMPTY) return s->adapter_status;
- if (s->target_status != ASPI_EMPTY) {
- /* Is sence area information available? */
- if (s->target_status != ASPI_SENCE) return s->target_status;
- if (s->command == EXEC_SIO) {
- p = s->area + s->cdblength;
- /* Take out vendor-unique classes (remap class 0 to 15) */
- if ((*p & 0x70) == 0x00) return *p | 0xf0;
- if ((*p & 0x70) != 0x70) return *p | 0x80;
- /* Take out vendor-unique codes */
- if ((*p & 0x0f) != 0x00) return *p & 0x7f;
- /* Is incorrect length indicator set? */
- if (p[2] & 0x20) return SCSI_ILI;
- /* Is nontrivial sence key available? */
- if (p[2] & 0x0E) return (p[2] & 15) | SCSI_SENCE;
- /* Check for file mark and end-of-medium conditions */
- if (p[2] & 0x80) return SCSI_FM;
- if (p[2] & 0x40) return SCSI_EOM;
- /* Nothing looks like an error */
- return (p[2] & 15) | SCSI_SENCE;
- }
- }
- return s->status;
- }
-
- #define END_OF_MEDIUM 0x80
- #define FIXED_MODE 1
- #define NO_RESET 2
- #define NO_REWIND 4
- #define ERASE 8
- #define FM_ON_CLOSE 0x10
- #define OPEN_FLAGS 0x1E
-
- static struct {
- unsigned long iosize;
- unsigned long maxblock; unsigned short minblock;
- byte adapter, target, lun, density, flags;
- } id = { -1L, 0, 0, 4, 0, 0, 0 };
- static long residue;
- static byte lastcmd = 0;
- static byte ok_to_close = FALSE;
- static unsigned to_skip = 0;
-
- int aspisio(int cmd, void *buffer, long length, long cmdlen,
- unsigned aspiflags, unsigned cdbflags, unsigned tout)
- {
- register k;
- register byte *p;
- struct _srbio s;
-
- s.command = EXEC_SIO;
- s.adapter = id.adapter;
- s.flags = aspiflags;
- *(long *)(s.reserved) = 0L;
- s.target = id.target;
- s.lun = id.lun;
- *(long *)(s.datalength) = length;
- s.sencelength = MAX_SENCE;
- *(void far * far *)(s.databuffer) = (void far *)buffer;
- *(long *)(s.srblink) = 0L;
- s.cdblength = 6; /* Group 0 commands only */
- *(long *)(s.post_routine) = 0xffff0000L;
-
- ((struct _cdbtape *)(s.area))->opcode = lastcmd = cmd;
- ((struct _cdbtape *)(s.area))->unit = (id.lun << 5) | cdbflags;
- ((struct _cdbtape *)(s.area))->counter[0] = (byte)(cmdlen >> 16);
- ((struct _cdbtape *)(s.area))->counter[1] = (byte)(cmdlen >> 8);
- ((struct _cdbtape *)(s.area))->counter[2] = (byte) cmdlen;
- ((struct _cdbtape *)(s.area))->control = 0;
-
- /* Clear sence area */ *(p = s.area + s.cdblength) = 0;
-
- k = aspicall(&s, tout);
- if (k & SCSI_SENCE && k < 0x70) {
- /* Check sence data area */
- if (p[2] & 0x40) id.flags |= END_OF_MEDIUM;
- else id.flags &= ~END_OF_MEDIUM;
- residue = (p[6] | ((unsigned)p[5] << 8)) |
- ((long)(p[4] | ((unsigned)p[3] << 8)) << 16);
- }
- return k;
- }
-
- int aspiexec(int cmd, unsigned cdbflags, unsigned tout)
- {
- return aspisio(cmd, NULL, 0L, 0L, T_NONE, cdbflags, tout);
- }
-
- int aspitrans(int wr, void *buffer, unsigned length)
- {
- register k;
- unsigned fixed, counter;
-
- if (id.iosize != 0L) {/* fixed mode */
- if (length % id.iosize) return (aspierrno=SCSI_ILI, -1);
- counter = (unsigned)(length / id.iosize);
- fixed = 1;
- } else {
- if (length < id.minblock || length > id.maxblock)
- return (aspierrno=SCSI_ILI, -1);
- counter = length;
- fixed = 0;
- }
- if (wr) {
- wr = S0P_WRITE; k = T_WRITE;
- } else {
- wr = S0P_READ; k = T_READ;
- }
- k = aspisio(wr, buffer, (long)length, (long)counter, k, fixed, MAXTIME);
- if (k == ASPI_SUCCESS) return length;
- if (k != SCSI_SENCEOK && k != SCSI_RECOVER && k != SCSI_BLANK &&
- k != SCSI_EOM && k != SCSI_FM) return (aspierrno=k, -1);
- if (!residue) return length;
- aspierrno = k;
- if (fixed) {
- if (residue > 0x10000L/id.minblock) return -1;
- residue *= id.minblock;
- }
- return (unsigned long)residue > length ? -1 : length - (int)residue;
- }
-
- long aspiinvoke(int cmd, long counter, int flag)
- {
- register k;
-
- k = aspisio(cmd, NULL, 0L, counter, T_NONE, flag, MAXTIME);
- if (k == ASPI_SUCCESS) return 0L;
- if (k != SCSI_SENCEOK && k != SCSI_RECOVER && k != SCSI_BLANK &&
- k != SCSI_EOM && k != SCSI_FM) return (aspierrno=k, -0x80000000L);
- if (residue) aspierrno = k;
- return residue;
- }
-
- int aspirewind(void)
- {
- register k;
-
- if ((k=aspiexec(S0P_REWIND,0,MAXTIME)) != ASPI_SUCCESS) {
- if ((k != SCSI_SENCEOK && k != SCSI_EOM && k != SCSI_FM) ||
- !(id.flags & END_OF_MEDIUM)) return (aspierrno=k);
- }
- return ASPI_SUCCESS;
- }
-
- int aspierase(int lbit)
- {
- register k;
-
- k = aspiexec(S0P_ERASE, lbit, MAXTIME);
- if (k!=ASPI_SUCCESS && k!=SCSI_SENCEOK && k!=SCSI_EOM)
- return (aspierrno=k);
- return ASPI_SUCCESS;
- }
-
- int aspireset(void)
- {
- struct _srbreset s;
- unsigned long t0;
- register i;
-
- s.command = RESET_DEV;
- s.adapter = id.adapter;
- s.flags = 0;
- s.target = id.target;
- s.lun = id.lun;
- for (i=0; i<sizeof(s.dummy); i++) s.dummy[i] = 0;
- *(long *)(s.post_routine) = 0xffff0000L;
- *(long *)(s.reserved) = 0L; /* clear reserved field */
- (*ASPI_ptr)((void far *)&s);
- for (t0 = pctimer(); s.status == ASPI_QUEUED;) {
- if (pctimer() - t0 > TRESET) break;
- HALTCPU;
- }
- if (!(s.status & 0x80)) {
- if (s.adapter_status != ASPI_EMPTY) return s.adapter_status;
- if (s.target_status != ASPI_EMPTY) return s.target_status;
- }
- return s.status;
- }
-
- int aspiread(char *buffer, unsigned length)
- {
- register k;
-
- if (!cblock) {
- if (length > id.maxblock) length = (unsigned)id.maxblock;
- else if (length < id.minblock) length = (unsigned)id.minblock;
- }
- if ((k = aspitrans(0, buffer, length)) == -1) {
- (void)fprintf(stderr, "Tar: ASPI read error: %s\n",
- aspierrmsg(aspierrno));
- }
- return k;
- }
-
- int aspiwrite(char *buffer, unsigned length)
- {
- register k;
-
- if (id.flags & END_OF_MEDIUM && lastcmd == S0P_WRITE) {
- aspierrno = SCSI_EOM; k = 0;
- } else {
- k = aspitrans(1, buffer, length);
- }
- if (k != length) {
- (void)fprintf(stderr, "Tar: ASPI write error: %s\n",
- aspierrmsg(aspierrno));
- }
- return k;
- }
-
- int aspiback(/* number of 512-byte blocks */ int n)
- {
- if (aspiinvoke(S0P_SPACE, -1, 0) != 0L) {
- (void)fprintf(stderr, "Tar: ASPI seek error: %s\n",
- aspierrmsg(aspierrno));
- return 0;
- }
- return n;
- }
-
- static int GetType(void)
- {
- struct _srbgettype s;
-
- s.command = GET_TYPE;
- s.adapter = id.adapter;
- s.target = id.target;
- s.lun = id.lun;
- s.flags = 0;
- *(long *)(s.reserved) = 0L;
- (*ASPI_ptr)((void far *)&s);
- if (s.status == ASPI_SUCCESS) return s.devtype;
- aspierrno = s.status;
- return -1;
- }
-
- static int HAInquiry(struct _srbinquiry *s, int adapter)
- {
- s->command = HA_INQ;
- s->adapter = adapter;
- s->flags = 0;
- *(long *)(s->reserved) = 0L;
- (*ASPI_ptr)((void far *)s);
- return s->status;
- }
-
- int aspicount(int devno)
- {
- register k;
- struct _srbinquiry s;
- register ha_max;
-
- /* Initialise device description */
- id.maxblock = 0x800000L;
- id.minblock = 1;
-
- /* Get number of host adapters */
- if ((k=HAInquiry(&s, 0)) != ASPI_SUCCESS) return k;
- ha_max = s.ha_total;
-
- /* Search for the tape device with given number */
- for (id.adapter = 0; id.adapter < ha_max; id.adapter ++)
- for (id.target = 0; id.target < 8; id.target ++)
- for (id.lun = 0; id.lun < 8; id.lun ++) {
- if ((k = GetType()) == -1) {
- if (aspierrno != ASPI_ABSENT) return aspierrno;
- } else if (k == TAPE) {
- if (devno-- == 0) goto found;
- }
- }
- /* There is no so many tape devices */ return ASPI_ABSENT;
- found:
- return ASPI_SUCCESS;
- }
-
- static int hex(register c)
- {
- if (c>='0' && c<='9') c -= '0';
- else if (c>='A' && c<='F') c -= 'A'-10;
- else if (c>='a' && c<='f') c -= 'a'-10;
- else c = ERROR;
- return c;
- }
-
- static int rstrlen(char *s, int size)
- {
- register i;
- for (i=0; s[i] && i<size; i++) {
- if (s[i] < ' ' || s[i] >= 127) return 0;
- }
- while (i>0 && (s[i-1]==' ' || s[i-1]=='\377')) --i;
- return i;
- }
-
- int aspiparse(char *s)
- {
- static char already[] = "tape format already defined";
- static struct { unsigned short nqic, code; } qiclist[] = {
- {11,4}, {120,15}, {150,16}, {320,17}, {525,17}, {1350,18}
- };
- char lex[MAXLEX+1], *errmsg;
- register i, k; register char *p;
-
- for (i=0; i<sizeof(lex) && *s!='.'; i++) {
- if (*s == '\0' || *s == ':' || *s == ';' || *s == ',') goto test_name;
- lex[i] = *s++;
- }
- return FALSE;
- test_name:
- lex[i] = '\0';
- if ((lex[0] & ~('z'^'Z')) != 'A' || strnicmp(lex,"ASPI",4)) return FALSE;
- if (lex[4]!='\0' && stricmp(lex+4,"MGR$") && stricmp(lex+4,"TAPE"))
- return FALSE;
-
- to_skip = 0;
- ok_to_close = FALSE;
- id.maxblock = 0x800000L;
- id.minblock = 1;
- id.adapter = UNKNOWN;
- id.target = UNKNOWN;
- id.lun = UNKNOWN;
- id.density = 0;
- id.flags = 0;
-
- if (*s) {
- while (*++s) {
- for (i=0; i<=MAXLEX; ++i, s++) {
- if (*s >= 'A' && *s <= 'Z') lex[i] = *s | ('z'^'Z');
- else if (*s >= 'a' && *s <= 'z') lex[i] = *s;
- else break;
- }
- if (i < 1 || i > MAXLEX) {
- errmsg = "device parameter error"; goto error;
- }
- lex[i] = '\0'; /* for diagnostic printing */
- if (!strncmp("fluent", lex, i)) {
- id.flags |= NO_RESET;
- } else if (!strncmp("norewind", lex, i)) {
- if (to_skip || id.flags & ERASE) goto mutual;
- id.flags |= NO_REWIND;
- } else if (!strncmp("erase", lex, i)) {
- if (to_skip || id.flags & NO_REWIND) goto mutual;
- id.flags |= ERASE;
- } else if (!strncmp("qic", lex, i)) {
- if (id.density) {
- errmsg = already; goto error;
- }
- if (*s == '-') {
- ++s;
- } else {
- if (*s == ':') ++s;
- if (*s == '=') ++s;
- }
- for (k=0, i=0; i<5 && *s>='0' && *s<='9'; ++s, i++)
- k = (*s - '0') + 10*k;
- if (i < 5)
- for (i=0; i<dimof(qiclist); i++)
- if (qiclist[i].nqic == k) {
- id.density = qiclist[i].code; break;
- }
- if (!id.density) {
- errmsg = "invalid QIC number"; goto error;
- }
- } else {
- if (*s == ':') ++s;
- if (*s == '=') ++s;
- if (strncmp("adapter", lex, i) == 0) {
- if (*s<'0' || *s>'7') {
- errmsg = "invalid adapter number"; goto error;
- }
- id.adapter = *s++ & 7;
- } else if (strncmp("target", lex, i) == 0) {
- if (*s<'0' || *s>'7') {
- errmsg = "invalid target number"; goto error;
- }
- id.target = *s++ & 7;
- } else if (strncmp("lun", lex, i) == 0) {
- if (*s<'0' || *s>'7') {
- errmsg = "invalid LUN number"; goto error;
- }
- id.lun = *s++ & 7;
- } else if (!strncmp("skip", lex, i)) {
- if (id.flags & (ERASE|NO_REWIND)) goto mutual;
- for (to_skip=0, i=0; i<5 && *s>='0' && *s<='9'; ++i, s++) {
- to_skip = (*s - '0') + 10*to_skip;
- }
- } else if (!strncmp("code", lex, i) ||
- !strncmp("density", lex, i)) {
- id.density = 0; p = s;
- if (*p == '0') ++p;
- if ((*p | ('z'^'Z')) == 'x') {
- for (i=0, s=p+1; i<2; ++s, i++) {
- if ((k = hex(*s)) == ERROR) break;
- id.density = k | (id.density << 4);
- }
- } else {
- while (hex(*p)!=ERROR) ++p;
- if ((*p | ('z'^'Z')) == 'h') {
- for (i=0; i<2; ++s, i++) {
- if ((k = hex(*s)) == ERROR) break;
- id.density = k | (id.density << 4);
- }
- if ((*s | ('z'^'Z')) == 'h') ++s;
- } else {/* decimal code */
- for (i=0; i<4 && *s>='0' && *s<='9'; ++i, s++) {
- id.density = (*s - '0') + 10*id.density;
- }
- }
- }
- if (!i || ~255 & id.density) {
- errmsg = "invalid density code"; goto error;
- }
- } else {
- (void)fprintf(stderr,"Tar: unknown parameter \'%s\'\n",lex);
- return ERROR;
- }
- }
- if (*s == '\0') break;
- if (*s != ',' && *s != ':' && *s != '.') {
- (void)fprintf(stderr,"Tar: invalid character after \'%s\'\n",lex);
- return ERROR;
- }
- }
- }
- if (ASPI_entry((void far *)&ASPI_ptr) != 0) {
- errmsg = "no ASPI manager found"; goto error;
- }
- if (setdrive ||
- (id.adapter==UNKNOWN && id.target==UNKNOWN && id.lun==UNKNOWN)) {
- if (id.adapter!=UNKNOWN || id.target!=UNKNOWN || id.lun!=UNKNOWN) {
- errmsg = "both device number and SCSI parameters specified";
- goto error;
- }
- if ((k=aspicount(ndrive)) != ASPI_SUCCESS) {
- errmsg = k!=ASPI_ABSENT ? aspierrmsg(k) :
- "there is no so many tape devices" ;
- goto error;
- }
- } else {
- if (id.target == UNKNOWN) {
- errmsg = "unknown target number"; goto error;
- }
- if (id.adapter == UNKNOWN) id.adapter = 0;
- if (id.lun == UNKNOWN) id.lun = 0;
- if ((k=GetType()) != TAPE) {
- errmsg = k == -1 ? aspierrmsg(k) : "not a tape device specified";
- goto error;
- }
- }
- if (v_flag) {
- struct _srbinquiry s;
- if (HAInquiry(&s, id.adapter) != ASPI_SUCCESS) goto reported;
-
- i = rstrlen((char*)s.mgr_id, 16);
- k = rstrlen((char*)s.ha_id, 16);
- if (!i && !k) goto reported;
-
- (void)fprintf(myout, "Tar: ");
- if (i) {
- (void)fprintf(myout, "ASPI manager: <%-.*s>", i, s.mgr_id);
- if (k) (void)fprintf(myout, ", ");
- }
- if (k) {
- (void)fprintf(myout, "SCSI adapter: <%-.*s>", k, s.ha_id);
- }
- (void)fprintf(myout, "\n");
- reported:;
- }
- if (a_flag && !(id.flags & NO_REWIND)) id.flags |= FM_ON_CLOSE;
- return TRUE;
- mutual:
- errmsg = "\'erase\', \'norewind\' and \'skip\' are mutaully exclusive";
- error:
- (void)fprintf(stderr, "Tar: %s\n", errmsg);
- return ERROR;
- }
-
- static void printape(void)
- {
- char b[96];
- int dlen, ilen=0, plen=0, rlen=0;
-
- /* Inquiry command does not interfere with 'Unit Attension' */
- if (aspisio(S0P_INQ, b, 96L, 96L, T_READ, 0, MINTIME) != ASPI_SUCCESS)
- return;
- if ((dlen = *(unsigned char *)(b+4) + 5) > 8) {
- ilen = rstrlen(b+8, 8);
- if (dlen > 16) {
- plen = rstrlen(b+16, 16);
- if (dlen > 32) rlen = rstrlen(b+32, 4);
- }
- }
- if (ilen || plen || rlen) {
- (void)fprintf(myout, "Tar: SCSI tape drive:");
- if (ilen) (void)fprintf(myout, "\t%-8.*s", ilen, b+8);
- if (plen) (void)fprintf(myout, "\t%-.*s", plen, b+16);
- if (rlen) (void)fprintf(myout, "\trev. %-.*s", rlen, b+32);
- (void)fprintf(myout, "\n");
- }
- }
-
- int aspisetmode(long bsize, int speed, int bm, int pf)
- {
- unsigned char b[12];
-
- b[1] = b[0] = 0;
- b[2] = (unsigned char)speed;
- if (bm) b[2] |= 16;
- b[3] = 8; /* block descriptor length */
-
- b[4] = id.density;
- b[7] = b[6] = b[5] = 0; /* whole tape */
- b[8] = 0; /* reserved */
- b[ 9] = (unsigned char)(255 & (bsize >> 16));
- b[10] = (unsigned char)(255 & (bsize >> 8));
- b[11] = (unsigned char)(255 & bsize);
- return aspisio(S0P_MODE, b, 12L, 12L, T_WRITE, (pf ? 16 : 0), MINTIME);
- }
-
- static int longrewind(void)
- /* Wait until previous operation completed and rewind */
- {
- register i, k;
- unsigned long t0;
-
- for (i=0, t0=pctimer();;) {
- if ((k=aspirewind()) == SCSI_ATTN) {
- if (++i < 7) continue;
- } else if (k == ASPI_BUSY || k == SCSI_BUSY) {
- if (pctimer() - t0 < MAXTIME) continue;
- }
- break;
- }
- return k;
- }
-
- int aspistart(void)
- {
- register k;
- unsigned long t0;
- unsigned char b[12];
- int gotBL = FALSE, gotMS = FALSE;
- extern void printbs(int);
-
- if (!(id.flags & (NO_RESET|NO_REWIND)) && id.density != 127) {
- (void)aspireset();
- /* Wait until POST and/or clear 'unit attension' condition */
- for (k=0, t0=pctimer();;) {
- switch (aspiexec(S0P_TEST, 0, MINTIME)) {
- case SCSI_ATTN: if (++k < 7) continue; break;
- case ASPI_BUSY:
- case SCSI_BUSY: if (pctimer() - t0 < MAXTIME) continue;
- }
- break;
- }
- }
- if (v_flag) printape();
- if (!(id.flags & NO_REWIND)) {
- if (longrewind() != ASPI_SUCCESS) goto error;
- if (id.flags & ERASE) {
- if (aspierase(1) != ASPI_SUCCESS) goto error;
- if (aspirewind() != ASPI_SUCCESS) goto error;
- }
- }
- id.iosize = 0L;
- /* Read block limits */
- k = aspisio(S0P_LIMITS, b, 6L, 0L, T_READ, 0, MINTIME);
- if (k == ASPI_SUCCESS || k == SCSI_SENCEOK || k == SCSI_EOM) {
- id.minblock = b[5] | ((unsigned)b[4] << 8);
- id.maxblock = b[3] | ((unsigned)b[2] << 8) | ((unsigned long)b[1]<<16);
- if (!id.maxblock) id.maxblock = 0x800000L;
- gotBL = TRUE;
- }
- k = aspisio(S0P_MSENCE, b, 12L, 12L, T_READ, 0, MINTIME);
- if ((k == ASPI_SUCCESS || k == SCSI_SENCEOK || k == SCSI_EOM) &&
- b[0] >= 12 && b[3] == 8) {
- id.iosize = ((unsigned long)b[9]<<16) | ((unsigned)b[10]<<8) | b[11];
- gotMS = TRUE;
- if (gotBL && id.iosize != 0L) {
- if (id.iosize < id.minblock || id.iosize > id.maxblock) {
- (void)fprintf(stderr,
- "Tar: SCSI blocksize %ld is out of hardware limits (%u-%ld)\n",
- id.iosize, id.minblock, id.maxblock);
- return ERROR;
- }
- if (!cblock && id.iosize%BLKSIZE == 0 &&
- id.iosize <= BLKSIZE*MAXBLOCK) {
- printbs(cblock = (int)(id.iosize / BLKSIZE));
- goto ok;
- }
- }
- }
- if (gotMS && id.iosize == 0L || !gotMS &&
- gotBL && id.minblock != id.maxblock) {
- id.flags &= ~FIXED_MODE;
- id.iosize = 0L;
- if (cblock) {
- if ((k = cblock * BLKSIZE) < id.minblock || k > id.maxblock) {
- (void)fprintf(stderr,
- "Tar: blocksize is out of hardware limits (%d - %ld)\n",
- id.minblock / BLKSIZE, id.maxblock / BLKSIZE);
- return ERROR;
- }
- } else if (c_flag) {
- printbs(cblock = id.maxblock < BLKSIZE*MAXBLOCK ?
- (int)(id.maxblock/BLKSIZE) : MAXBLOCK);
- }
- } else if (gotMS || gotBL) {
- id.flags |= FIXED_MODE;
- if (!gotMS) id.iosize = id.minblock;
- if ((id.iosize % BLKSIZE || id.iosize > BLKSIZE*MAXBLOCK) &&
- (!cblock || id.density==0 || id.density==127)) {
- (void)fprintf(stderr,
- "Tar: hardware blocksize %ld bytes is not suitable for tar\n",
- id.iosize);
- }
- if (cblock) {
- if (id.density!=0 && id.density!=127 &&
- (k = cblock*BLKSIZE) >= id.minblock && k <= id.maxblock) {
- id.iosize = k;
- } else if ((cblock*BLKSIZE) % id.iosize) {
- (void)fprintf(stderr,
- "Tar: blocksize must be multiple of %ld\n",
- id.iosize/BLKSIZE);
- }
- } else {
- printbs(cblock = (int)(id.iosize / BLKSIZE));
- }
- } else /* !gotMS && !gotBL */ {
- if (cblock) {
- id.iosize = id.maxblock = id.minblock = BLKSIZE*cblock;
- id.flags |= FIXED_MODE;
- } else {
- id.maxblock = BLKSIZE*MAXBLOCK;
- id.minblock = BLKSIZE;
- id.flags &= ~FIXED_MODE;
- id.iosize = 0L;
- }
- }
- ok:
- if (id.density!=0 && id.density != 127) {
- for (k=4; k--;) {
- if (aspisetmode(id.iosize, 0, k&2, k&1)
- != SCSI_INVALID) break;
- }
- }
- ok_to_close = TRUE;
- if (to_skip) {
- if (aspisio(S0P_SPACE, NULL, 0L, (long)to_skip, T_NONE, 1, MAXTIME)
- != ASPI_SUCCESS) goto error;
- }
- return 0;
- error:
- (void)fprintf(stderr, "Tar: %s\n", aspierrmsg(aspierrno));
- return ERROR;
- }
-
- void aspiend(void)
- {
- if (!ok_to_close) return;
- if (id.flags & FM_ON_CLOSE || lastcmd == S0P_WRITE) {
- if (aspiinvoke(S0P_WFM,
- ((id.flags & (FM_ON_CLOSE|NO_REWIND)) == FM_ON_CLOSE ? 1L : 0L),
- 0) != 0L) goto error;
- }
- if (id.flags & NO_REWIND) return;
- if (longrewind() == ASPI_SUCCESS) return;
- error:
- (void)fprintf(stderr, "Tar: %s\n", aspierrmsg(aspierrno));
- }
- #endif