# /* * copyright 1975 ian inc. */ /* * cr11 card reader driver * ascii and binary version */ #include "../defines.h" #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" /* * to add another card reader see notes * below with struct cr11 */ #define cripri 20 /* sleeping priority */ #define ncols 80 /* no. of columns */ #define splcr spl6 /* hardware priority level */ /* * card reader status bits * see the dec peripherals handbook * for more information */ #define error (1<<15) #define cardone (1<<14) #define hopper (1<<13) #define motion (1<<12) #define timing (1<<11) #define online (1<<10) #define busy (1<<9) #define notready (1<<8) #define coldone (1<<7) #define ienable (1<<6) #define eject (1<<1) #define read (1<<0) /* * card reader device registers * the order of these fields is important */ struct { int crstatus; /* status register */ int crbbin; /* 12 bit binary buffer */ int crbcode; /* 8 bit encoded buffer */ }; /* * card reader handler status */ #define closed 0 #define reading 1 #define cardread 2 #define endfile 3 #define err 4 /* * card reader mode */ #define o29 0 #define o26 1 #define binary 2 /* * status info for card reader(s) */ #define ncr11 1 /* no. of cr11 */ struct cr11 { char crstate; /* current state of reader */ /* 0 - closed 1 - reading 2 - cardread 3 - endfile 4 - err 020 - B_PHYS don't use */ char crmode; /* 0 - 029 1 - 026 2 - binary */ long crdcnt; /* dble word card count */ int crerror; /* copy of status register on error */ int *addr; /* device register address */ int crcols; /* for reading the number of columns left in the buffer */ int crchars; /* for passing back the number of characters left to pass back */ /********************************************************************* * this next word must be the 8th in the structure * * for the purposes of iomove * *********************************************************************/ char *nextch; /* buffer position pointer */ int *nextcol; /* pointer to the last column read */ int buffer[ncols+1]; /* one card buffer */ }; struct cr11 cr0 { closed, /* initially cr11 closed */ 0, /* initial mode (o29) */ 0, /* initial card count */ 0, /* initial error status */ 0177160, /* device register addr */ 0, /* initial columns */ 0, /* initial characters to go back */ 0, /* initial character ptr */ 0, /* initial column pointer */ }; /* /* struct cr11 cr1 /* { /* 0, /* initial card count */ /* closed, /* initially cr11 closed */ /* 0, /* initial mode (o29) */ /* 0, /* initial error status */ /* 0160030, /* device register addr */ /* 0, /* initial columns */ /* 0, /* initial characters to go back */ /* 0, /* initial character ptr */ /* 0, /* initial column pointer */ /* }; */ struct cr11 *cr11[ncr11] { &cr0, /* &cr1 */ }; /* to add another card reader - * 1. increment ncr11 by 1. * 2. add initialisation for the next card reader * into the initialisation for cr11 structure. * if you can't follow the structure then * perhaps you shouldn't be modifying it. */ /* * special character codes */ #define eoi 01437 /* 6 7 8 9 punching */ #define eof 01427 /* 6 7 9 punching */ #define eor 00437 /* 7 8 9 punching */ #define cnv 02427 /* 5 7 9 punching */ #define cntrlf '\06' /* eof returns cntrlf */ #define cntrlr '\022' /* eor returns cntrlr */ /* * validity checking table */ char crvalid[8] { 0,1<<6,1<<5,1<<4,1<<3,1<<2,1<<1,1<<0 }; char crcd26[] { 0,'+','=','(',')','\'','^','#','>','?',';','<','[',']', '`','"','&',':','!','?','^','@','%' }; char crcd29[] { 0,'&','#','%','<','@',')',';','^','(','!','{','"','\\', '_','>','?',']','}','[','+','\'','=' }; /* * coded to ascii translation */ char crtab[256] { ' ','1','2','3','4','5','6','7', /* */ '8','`',':',-2 ,-5 ,-21,-22,-12, /* 8 */ '9', 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , cntrlr , /* 9 8 */ '0','/','s','t','u','v','w','x', /* 0 */ 'y','^',-13,',',-3 ,-14,-15,-16, /* 0 8 */ 'z', 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0 9 8 */ '-','j','k','l','m','n','o','p', /* 11 */ 'q','|',-17,'$','*',-6 ,-7 ,-8 , /* 11 8 */ 'r', 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 11 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 11 9 8 */ -18,'~','S','T','U','V','W','X', /* 11 0 */ 'Y', 0 , 0 , 0 , 0 , 0 ,'\t',0 , /* 11 0 8 */ 'Z', 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 11 0 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 11 0 9 8 */ -1 ,'a','b','c','d','e','f','g', /* 12 */ 'h', 0 ,-19,'.',-4 ,-9 ,-20,-10, /* 12 8 */ 'i', 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 9 8 */ -11,'A','B','C','D','E','F','G', /* 12 0 */ 'H', 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 0 8 */ 'I', 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 0 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 0 9 8 */ 0 ,'J','K','L','M','N','O','P', /* 12 11 */ 'Q', 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 11 8 */ 'R', 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 11 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 11 9 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 11 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 11 0 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 11 0 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 12 11 0 9 8 */ }; /* * and now for something completely different * the routines to handle all */ crdaopen(dev,flag) { crdopen(dev,flag,o29); } crdbopen(dev,flag) { crdopen(dev,flag,binary); } crdopen(dev,flag,mode) { register struct cr11 *cr; if((flag != 0) || (dev.d_minor > ncr11)) { u.u_error = ENXIO; return; } cr = cr11[dev.d_minor]; if(cr->crstate != closed) { u.u_error = EEXIST; return; } cr->crmode = mode; crdstart(cr); } crdclose(dev,flag) { register struct cr11 *cr; cr = cr11[dev.d_minor]; cr->addr->crstatus = 0; cr->crstate = closed; } crdint(dev) { register struct cr11 *cr; register int *devreg; register int status; cr = cr11[dev.d_minor]; devreg = cr->addr; status = devreg->crstatus; if(status & coldone) if(cr->crcols) { cr->crcols--; *++(cr->nextcol) = (cr->crmode == binary ? devreg->crbbin : (devreg->crbcode) | (devreg->crbbin<<6 & 077400)); } else { int dummy; dummy = devreg->crbbin; /* clear interrupt */ } if(status & (error|cardone|online)) { if(status & error) { devreg->crstatus = eject|ienable; cr->crerror = status; } if(status&cardone) { devreg->crstatus = 0; cr->crstate = cardread; wakeup(cr); } else if(status & online) crdstart(cr); } } crdread(dev) { register struct cr11 *cr; cr = cr11[dev.d_minor]; if(cr->crchars == 0) { if(cr->crstate == endfile) crdstart(cr); loop: { splcr(); while(cr->crstate!=cardread) sleep(cr,cripri); spl0(); cr->crdcnt++; if(cr->crerror & timing) { crderror(dev,cr,"timing"); goto loop; /* next time put in a bigger card */ } if(cr->crerror&motion && cr->crcols==ncols) { crdstart(cr); goto loop; } } cr->crcols = ncols - cr->crcols; if (cr->crmode == binary) { cr->crchars = cr->crcols*2; } else { if(crascii(dev,cr)) goto loop; /* must have been an invalid card or conv */ } cr->nextch = cr->buffer; } crdpass(cr); if ((cr->crstate != endfile) && (cr->crchars == 0)) crdstart(cr); } crdstart(xcr) struct cr11 *xcr; { register struct cr11 *cr; register int *devreg; register dummy; cr = xcr; cr->nextcol = cr->buffer - 1; cr->crstate = reading; cr->crerror = 0; cr->crcols = ncols; cr->crchars = 0; devreg = cr->addr; dummy = devreg->crbbin; /* must clear column done in esoteric errors */ devreg->crstatus = ienable|read; } crderror(dev,cr,errmsg) register struct cr11 *cr; char *errmsg; { register dummy; #ifdef UPRINTS uprints("reread last card\n"); #endif printf("cr%d %s - reread last card\n", dev.d_minor, errmsg); dummy = cr->addr->crbbin; /* clear any column done interrupt */ cr->crstate = err; cr->addr->crstatus = ienable; } int crascii(dev,xcr) struct cr11 *xcr; { register struct cr11 *cr; register int *pch; register char *qch; cr = xcr; pch = qch = cr->buffer; while(pch <= cr->nextcol) { /* at most one punching in columns 1-7 */ if (crvalid[*pch&07] != (*pch>>8)) { switch(*pch) { case eoi: cr->crstate = endfile; cr->crmode = o29; return(0);/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ case eof: *pch = cntrlf; break;/*<<<<<<<<<<<<<<<<<<<<<*/ case cnv: if(pch == cr->buffer) { cr->crmode = cr->buffer[1]==0; crdstart(cr); return(1);/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } default: crderror(dev,cr,"validity"); return(1);/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } /* switch */ } else { /* translate character */ *qch = crtab[*pch&0377]; /* check 026 029 and validity */ if (*qch <= 0) if (*qch == 0) { crderror(dev,cr,"validity"); return(1);/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } else { *qch = (cr->crmode?crcd26: crcd29)[-*qch]; } } pch++; qch++; } *qch++ = '\n'; cr->crchars = cr->crcols + 1; return(0); } crdpass(xcr) struct cr11 *xcr; { register struct cr11 *cr; register int count1,count2; cr = xcr; /* send back the min of cols on card and use count */ count1 = (cr->crchars < u.u_count ? cr->crchars : u.u_count); /* iomove an even number of characters */ if(count1 > 1) { count2 = count1 & 0177776; #ifdef MAPPED_BUFFERS cr->crstate =| B_PHYS; #endif MAPPED_BUFFERS iomove(cr,0,count2,B_READ); #ifdef MAPPED_BUFFERS cr->crstate =& ~B_PHYS; #endif MAPPED_BUFFERS cr->crchars =- count2; cr->nextch =+ count2; } /* passc the last character if odd */ if(count1 & 1) { passc(*(cr->nextch++)); cr->crchars--; } } crdsgtty(dev, av) int *av; { register struct cr11 *cr; register int *v; cr = cr11[dev.d_minor]; if( v=av ){ /* gtty */ *v++ = cr->crstate &0377; *v++ = cr->crmode &0377; *v++ = cr->addr->crstatus; return(1); } /* stty */ v = u.u_arg; v++; /* skip this bit ... */ cr->crmode = *v++; /* only allowed to set mode ... */ return(0); } #ifdef POWER_FAIL crdpowf() { register i; register struct cr11 *cr; for( i = 0 ; i < ncr11 ; i++ ) { cr = cr11[i]; if( cr->crstate == reading || cr->crstate == err) { crderror(i, cr, "power fail"); } } } #endif POWER_FAIL