Ausam/sys/dmr/ta.c
#
/*
* copyright 1975 ace systems inc.
*/
/*
* ta-11 cassette driver
*/
#include "../param.h"
#include "../conf.h"
#include "../buf.h"
#include "../user.h"
int taopenl[2];
int tabc,tabcz; char *taba,tabaz; int tactv; int taerr; taerrcnt;
/* symbolic equates for ta-11 */
#define taddr 0177500
struct {
int tacs; /* ta-11 control and status register */
int tadb; }; /* ta-11 data buffer register */
#define taperr (1<<15) /* 14->9,3->1, indicate type
valid only when ready is set */
#define blkchk (1<<14) /* crc error for read and sfb
sets error for read */
#define xot (1<<13) /* eot or bot on selected tape
sets error for all but rewind */
#define wlock (1<<12) /* selected tape is write protected
write or wfg must be set */
#define fgap (1<<11) /* tape mark encounted during read,sfb,srf,sff
sets error only on read, sfb */
#define timerr (1<<10) /* missed character
sets error only on read, write */
#define offline ((1<<9)|(1<<15)) /* selected cassette unavailable */
#define treq (1<<7) /* data available in tadb during read
data wanted in tadb during write */
#define ready (1<<5) /* unit ready to accept commands */
#define ilbs (1<<4) /* initate last byte sequence */
#define wfg ((1<<6)|(0<<1)|1) /* write file gap */
#define write ((1<<6)|(1<<1)|1) /* write */
#define read ((1<<6)|(2<<1)|1) /* read */
#define srf ((1<<6)|(3<<1)|1) /* space reverse file */
#define srb ((1<<6)|(4<<1)|1) /* space reverse block */
#define sff ((1<<6)|(5<<1)|1) /* space forward file */
#define sfb ((1<<6)|(6<<1)|1) /* space forward block */
#define rewind ((1<<6)|(7<<1)|1) /* rewind */
taopen(dev,flag)
{
register lr;
if( (lr=dev.d_minor)>1 ) u.u_error=ENXIO;
else { taddr->tacs =| lr<<8 ;
if( taopenl[lr] || ((taddr->tacs&offline)==offline) )
u.u_error=ENXIO;
else
taopenl[lr]=1;
}
}
taclose(dev,flag)
{
register lr;
lr = dev.d_minor<<8;
if (flag) tastart(lr,wfg);
tastart(lr,rewind);
taopenl[lr>>8]=0;
}
tastart( lr , cmd )
{
register struct buf *bp;
if(u.u_count>512) { u.u_error=ENXIO; return; }
while(tactv) sleep(&tactv,1);
taddr->tacs =| lr ;
if( (!(taddr->tacs&ready))||((taddr->tacs&offline)==offline))
{ u.u_error = ENXIO; return; }
switch(cmd) {
case read: bp = getblk(NODEV);
tabaz=taba=bp->b_addr;
tabcz=tabc= u.u_count;
break;
case write: bp = getblk(NODEV);
tabaz=taba=bp->b_addr;
tabcz=tabc= u.u_count;
iomove(bp,0,u.u_count,B_WRITE);
case wfg:
case rewind:
break;
}
tactv = cmd; taerr = 0; taerrcnt = 5;
taddr->tacs= lr | cmd;
while(tactv) sleep(&tactv,1); /* wait for i/o to complete */
if((taerr==2)&&(cmd==read)) return;
switch(cmd) {
case read: if(tabc==u.u_count) return;
iomove(bp,0,u.u_count-tabc,B_READ);
case write: brelse(bp);
case wfg: break;
case rewind: return;
}
if(taerr) u.u_error = ENXIO;
}
taintr()
{
if(!(tactv)) return;
if(taddr->tacs&treq)
{ if (!tabc--) { taddr->tacs =| ilbs; tabc=0; }
else if (tactv==read)
*taba++ =taddr->tadb;
else taddr->tadb= *taba++;
return; }
if(taddr->tacs&taperr) {
if(!taerr) {
/*************
deverror(bp,taddr->tacs);
*************/
taerr = 1;
if((taerrcnt--)>0) switch(tactv) {
case read: if(taddr->tacs&(xot|fgap)) {
taerr++; goto rti;
}
case write: if(taddr->tacs&timerr) {
taddr->tacs = (taddr->tacs & 0177740)|srb;
return;
}
}
}
}
else if(taerr) {
taddr->tacs = (taddr->tacs & 0177740) | tactv;
taerr = 0; taerrcnt = 5;
taba = tabaz; tabc = tabcz;
return;
}
rti: tactv = 0;
wakeup(&tactv);
}
/*
* i/o interface for cassette.
* essentially provided so users can read/write caps-11 format
* tapes.
*/
taread(dev)
{
tastart(dev.d_minor<<8,read);
}
tawrite(dev)
{
tastart(dev.d_minor<<8 , (u.u_count==1) ? wfg : write);
}