# /* * copyright 1975 ian inc. */ /* * cr11 card reader driver * ascii and binary version * for buffered card reader */ #include "../defines.h" #include "../param.h" #include "../conf.h" #include "../user.h" #include "../buf.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 spl4 /* 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 cbuffer (1<<11) #define online (1<<10) #define busy (1<<9) #define notready (1<<8) #define coldone (1<<7) #define ienable (1<<6) #define clear (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 */ }; struct { char crstat0,crstat1; /* chars of the status register */ char crbbin0,crbbin1; /* the two bytes of the binary buffer */ }; /* * card reader handler status */ #define closed 0 #define reading 1 #define cardread 2 #define endfile 3 #define valerr 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 */ /* 020 - B_PHYS for iomove */ char crmode; /* 0 - 029 1 - 026 2 - binary */ long crdcnt; /* double word card count */ int crvalerr; /* count of validity errors */ int crrdchk; /* count of read checks */ int *craddr; /* device register address */ 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 */ char buffer[2*ncols+1]; /* one card buffer */ }; struct cr11 cr0 { closed, /* initially cr11 closed */ 0, /* initial mode (o29) */ 0, /* initial card count */ 0, /* initial validity error count */ 0, /* initial read check count */ 0177160, /* device register craddr */ 0, /* initial characters to be passed back */ 0, /* initial ptr */ }; /* second card reader address:- 160030 */ struct cr11 *cr11[ncr11] { &cr0, }; /* to add another card reader - * 1. increment ncr11 by 1. * 2. add another element to the array "cr11" * and initialise the element to the address of * a cr11 structure (similar to "cr0"). * 3. add the cr11 struct complete with * its initialisation. if you cant work out * how to initialise it then you should not * be doing it...... */ /* * special character codes */ #define eoi 017 /* 6 7 8 9 punching */ #define csueoi 07417 /* 12 11 0 1 6 7 8 9 punching */ #define eof 015 /* 6 7 9 punching */ #define eor 007 /* 7 8 9 punching */ #define cnv 025 /* 5 7 9 punching */ #define cntrlf '\06' /* eof returns cntrlf */ #define cntrlr '\022' /* eor returns cntrlr */ /* * validity checking table */ int crvalid[8] { 0,1<<8,1<<7,1<<6,1<<5,1<<4,1<<3,1<<2 }; 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 */ craopen(dev,flag) { cropen(dev,flag,o29); } crbopen(dev,flag) { cropen(dev,flag,binary); } cropen(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; cr->crchars = 0; crstart(cr); } crclose(dev,flag) { register struct cr11 *cr; cr = cr11[dev.d_minor]; cr->craddr->crstatus = 0; cr->crstate = closed; } crint(dev) { register struct cr11 *cr; register int *devreg; register int status; cr = cr11[dev.d_minor]; devreg = cr->craddr; status = devreg->crstatus; if(status & (error|cardone|online)) { devreg->crstatus = ienable; /* clear interrupt*/ if(status & motion) { cr->crrdchk++; } else if((status&(cardone|cbuffer)) == (cardone|cbuffer)) { devreg->crstatus = 0; cr->crstate = cardread; wakeup(cr); } else if(status & online) crstart(cr); } } crread(dev) { register struct cr11 *cr; register int *devreg; register char *pch; char qch; cr = cr11[dev.d_minor]; if(cr->crchars == 0){ if(cr->crstate == endfile) crstart(cr); loop: splcr(); while(cr->crstate!=cardread) sleep(cr,cripri); spl0(); /* a card has been read */ cr->crdcnt++; pch = cr->buffer; devreg = cr->craddr; do { if(cr->crmode == binary) { *pch++ = devreg->crbbin0; *pch++ = devreg->crbbin1; } else { /* ascii conversion - 1st validity check */ if(crvalid[devreg->crbcode&07]!=(devreg->crbbin&0774)) { switch(devreg->crbbin) { case eoi: case csueoi: cr->crstate = endfile; cr->crmode = o29; return; /*<-----------------------------------------*/ case eof: *pch++ = cntrlf; break; case cnv: if(pch == cr->buffer) { crrdcol(devreg); cr->crmode=devreg->crbbin==0; crstart(cr); goto loop; /*<------------------------------*/ } /* if not conversion default*/ default: crerror(dev,cr); goto loop; /*<-------------------------------*/ } /* switch */ } else { /* valid - translate */ qch = crtab[devreg->crbcode]; /* check o26 or o29 specials */ if (qch <= 0) if (qch == 0) { crerror(dev,cr); goto loop; /*<--------------------------------*/ } else { *pch++=(cr->crmode? crcd26:crcd29)[-qch]; } else *pch++ = qch; } /* fi */ } /* fi */ } while (pch < &cr->buffer[ncols*2] && crrdcol(devreg)); if (cr->crmode != binary) *pch++ = '\n'; cr->nextch = cr->buffer; cr->crchars = pch - cr->buffer; if (cr->crstate != endfile) crstart(cr); } crpass(cr); } crstart(xcr) struct cr11 *xcr; { register struct cr11 *cr; register int *devreg; cr = xcr; cr->crstate = reading; /* flush the buffer in card reader */ devreg = cr->craddr; devreg->crstatus = clear; devreg->crstatus = ienable|read; /* card in motion */ } crerror(dev,xcr) struct cr11 *xcr; { register struct cr11 *cr; register int *devreg; register dummy; cr = xcr; devreg = cr->craddr; cr->crstate = valerr; cr->crvalerr++; #ifndef UPRINTS printf("cr%d validity - reread last card\n", dev.d_minor); #else uprints("Invalid punch - reread last card\n"); #endif UPRINTS dummy = devreg->crbbin; /* clear coldone */ devreg->crstatus = ienable|clear; } crpass(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(count2 = count1 & 0177776) { #ifdef MAPPED_BUFFERS cr->crstate =| 020; /* B_PHYS */ #endif MAPPED_BUFFERS iomove(cr,0,count2,B_READ); /* uses cr->nextch */ #ifdef MAPPED_BUFFERS cr->crstate =& ~020; /* off again */ #endif MAPPED_BUFFERS cr->crchars =- count2; cr->nextch =+ count2; } if(count1 & 1) { passc(*cr->nextch++); cr->crchars--; } } crrdcol(xdevreg) { register int *devreg; int x,y; devreg = xdevreg; devreg->crstatus = read; /* shift */ /* wait a microsecond or 5 */ x = y; /* waste the required time */ if(devreg->crstatus&cbuffer) return(1); else return(0); } crsgtty(dev, av) int *av; { register struct cr11 *cr; register *v; cr = cr11[dev.d_minor]; if( v=av ){ /* gtty */ *v++ = cr->crstate &0377; *v++ = cr->crmode &0377; *v++ = cr->craddr->crstatus; /**/ return(1); } /* stty */ v = u.u_arg; v++; /* lets skip this bit ... */ cr->crmode = *v++; /**/ return(0); } #ifdef POWER_FAIL crpowf() { register i; register struct cr11 *cr; for( i = 0 ; i < ncr11 ; i++ ) { cr = cr11[i]; if( cr->crstate == reading || cr->crstate == cardread) { crerror(i, cr); } } } #endif POWER_FAIL