home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / standalone / vt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-03  |  5.3 KB  |  206 lines

  1. /*
  2.  * Virtual tape driver - copyright 1998 Warren Toomey    wkt@cs.adfa.oz.au
  3.  *
  4.  * $Revision: 1.9 $
  5.  * $Date: 1998/02/01 00:49:15 $
  6.  */
  7.  
  8. #include <sys/param.h>
  9. #include <sys/inode.h>
  10. #include "saio.h"
  11.  
  12. /* Command sent to tape server */
  13. struct vtcmd {
  14.     char hdr1;            /* Header, 31 followed by 42 (decimal) */
  15.     char hdr2;
  16.     char cmd;            /* Command, one of VTC_XXX below */
  17.                 /* Error comes back in top 4 bits */
  18.     char record;        /* Record we're accessing */
  19.     char blklo;            /* Block number, in lo/hi format */
  20.     char blkhi;
  21.     char sum0;            /* 16-bit checksum */
  22.     char sum1;
  23. };
  24.  
  25. /* Header bytes */
  26. #define VT_HDR1        31
  27. #define VT_HDR2        42
  28.  
  29. /* Commands available */
  30. #define VTC_QUICK    0    /* Quick read, no cksum sent */
  31. #define VTC_OPEN    1
  32. #define VTC_CLOSE    2
  33. #define VTC_READ    3    /* This file only uses READ and OPEN */
  34. #define VTC_WRITE    4
  35.  
  36. /* Errors returned */
  37. #define VTE_NOREC    1    /* No such record available */
  38. #define VTE_OPEN    2    /* Can't open requested block */
  39. #define VTE_CLOSE    3    /* Can't close requested block */
  40. #define VTE_READ    4    /* Can't read requested block */
  41. #define VTE_WRITE    5    /* Can't write requested block */
  42. #define VTE_NOCMD       6       /* No such command */
  43. #define VTE_EOF         7       /* End of file: no blocks left to read */
  44.  
  45. #define BLKSIZE         512
  46.  
  47. /* Static things */
  48. struct vtcmd vtcmd;        /* Command buffer */
  49. struct vtcmd vtreply;        /* Reply from server */
  50. char *vtbuf;            /* Pointer to input buffer */
  51. unsigned int hitim, lotim;    /* Variables for delay loop */
  52. char oddeven=0;            /* Toggle status printing character */
  53. char *oddstr= ".*";
  54.  
  55. char vtsendcmd();        /* Forward references */
  56. char vtgetc();
  57.  
  58.  
  59. /*** Standalone-dependent section */
  60.  
  61. /* vtopen() is used to inform the server which record we'll be using */
  62. vtopen(io)
  63. register struct iob *io;
  64. {
  65.     register i;
  66.  
  67.     vtcmd.record= io->i_boff; vtcmd.cmd= VTC_OPEN;
  68.     vtcmd.blklo=0; vtcmd.blkhi=0;
  69.  
  70.     vtsendcmd();        /* Send the command to the server */
  71. }
  72.  
  73.  
  74. /* vtstrategy() must be called as a READ. We send a command
  75.  * to the server, get a reply, and return the amount read
  76.  * (even on EOF, which may be zero) or -1 on error.
  77.  */
  78. vtstrategy(io, func)
  79. register struct iob *io;
  80. {
  81.     register error, i;
  82.  
  83.     vtbuf= io->i_ma;
  84.  
  85.     /* Assume record, blklo and blkhi are ok */
  86.     /* Assume i->i_cc is in multiples of BLKSIZE */
  87.     for (i=0; i<io->i_cc; i+=BLKSIZE, vtbuf+=BLKSIZE) {
  88.  
  89.     vtcmd.cmd= VTC_READ;
  90.  
  91.         error= vtsendcmd();        /* Send the command to the server */
  92.  
  93.                     /* Some programs rely on */
  94.                     /* the buffer being cleared to */
  95.                     /* indicate EOF, e.g cat */
  96.     if (error == VTE_EOF) { vtbuf[0]=0; return(i); }
  97.  
  98.     if (error != 0) {
  99.       printf("tape error %d", error);
  100.       return(-1);
  101.      }
  102.                     /* Increment block number for next time */
  103.     vtcmd.blklo++;
  104.     if (vtcmd.blklo==0) vtcmd.blkhi++;
  105.     }
  106.     return(io->i_cc);
  107. }
  108.  
  109. /*** Protocol-specific stuff ***/
  110.  
  111. char vtsendcmd()
  112. {
  113.     register i;
  114.     char error, cmd, sum0, sum1;
  115.  
  116.             /* Build the checksum */
  117.     vtcmd.hdr1= VT_HDR1; vtcmd.hdr2= VT_HDR2;
  118.     vtcmd.sum0= VT_HDR1 ^ vtcmd.cmd ^ vtcmd.blklo;
  119.     vtcmd.sum1= VT_HDR2 ^ vtcmd.record ^ vtcmd.blkhi;
  120.  
  121.             /* Send the command to the server */
  122.   sendcmd:
  123.     vtputc(vtcmd.hdr1);  vtputc(vtcmd.hdr2);
  124.     vtputc(vtcmd.cmd);   vtputc(vtcmd.record);
  125.     vtputc(vtcmd.blklo); vtputc(vtcmd.blkhi);
  126.     vtputc(vtcmd.sum0);  vtputc(vtcmd.sum1);
  127.  
  128.               /* Now get a valid reply from the server */
  129.   getreply:
  130.     vtreply.hdr1= vtgetc(); if (hitim==0) goto sendcmd;
  131.     if (vtreply.hdr1!=VT_HDR1) goto getreply;
  132.     vtreply.hdr2= vtgetc(); if (hitim==0) goto sendcmd;
  133.     if (vtreply.hdr2!=VT_HDR2) goto getreply;
  134.     vtreply.cmd= vtgetc(); if (hitim==0) goto sendcmd;
  135.     vtreply.record= vtgetc(); if (hitim==0) goto sendcmd;
  136.     vtreply.blklo= vtgetc(); if (hitim==0) goto sendcmd;
  137.     vtreply.blkhi= vtgetc(); if (hitim==0) goto sendcmd;
  138.  
  139.  
  140.             /* Calc. the cksum to date */
  141.     sum0= VT_HDR1 ^ vtreply.cmd ^ vtreply.blklo;
  142.     sum1= VT_HDR2 ^ vtreply.record ^ vtreply.blkhi;
  143.  
  144.             /* Retrieve the block if no errs and a READ cmd */
  145.     if (vtreply.cmd==VTC_READ) {
  146.       for (i=0; i<BLKSIZE; i++) {
  147.     vtbuf[i]= vtgetc(); if (hitim==0) goto sendcmd;
  148.     sum0 ^= vtbuf[i]; i++;
  149.     vtbuf[i]= vtgetc(); if (hitim==0) goto sendcmd;
  150.     sum1 ^= vtbuf[i];
  151.       }
  152.     }
  153.             /* Get the checksum */
  154.     vtreply.sum0= vtgetc(); if (hitim==0) goto sendcmd;
  155.     vtreply.sum1= vtgetc(); if (hitim==0) goto sendcmd;
  156.  
  157.             /* Try again on a bad checksum */
  158.     if ((sum0!=vtreply.sum0) || (sum1!=vtreply.sum1)) {
  159.     putchar('e'); goto sendcmd;
  160.     }
  161.  
  162.     putchar(oddstr[oddeven]); oddeven= 1-oddeven;
  163.  
  164.             /* Extract any error */
  165.     error= vtreply.cmd >> 4; return(error);
  166. }
  167.  
  168. /*** Harware-specific stuff ***/
  169.  
  170. struct  device  {
  171.         int     rcsr,rbuf;
  172.         int     tcsr,tbuf;
  173. };
  174.  
  175. static struct  device *KL1= {0176500};        /* We use KL11 unit 1 */
  176.  
  177. /* vtgetc() and vtputc(): A sort-of repeat of the getchar/putchar
  178.  * code in prf.c, but without any console stuff
  179.  */
  180.  
  181. /* Get a character, or timeout and return with hitim zero */
  182. char vtgetc()
  183. {   
  184.         register c;
  185.     
  186.         KL1->rcsr = 1; hitim=3; lotim=65535;
  187.   
  188.         while ((KL1->rcsr&0200)==0) {
  189.        lotim--;
  190.        if (lotim==0) hitim--;
  191.        if (hitim==0) { putchar('t'); return(0); }
  192.     }
  193.         c = KL1->rbuf; return(c);
  194. }
  195.  
  196.  
  197. vtputc(c)
  198. register c;
  199. {
  200.         register s;
  201.  
  202.         while((KL1->tcsr&0200) == 0) ;
  203.         s = KL1->tcsr;
  204.         KL1->tcsr = 0; KL1->tbuf = c; KL1->tcsr = s;
  205. }
  206.