|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "io.h" ! 7: #include "../port/error.h" ! 8: ! 9: /* Centronix parallel (printer) port */ ! 10: ! 11: /* base addresses */ ! 12: static int lptbase[] = { ! 13: 0x3bc, /* lpt1 */ ! 14: 0x378, /* lpt2 (sic) */ ! 15: 0x278 /* lpt3 (sic) */ ! 16: }; ! 17: #define NDEV (sizeof lptbase/sizeof lptbase[0]) ! 18: ! 19: /* offsets, and bits in the registers */ ! 20: enum ! 21: { ! 22: /* data latch register */ ! 23: Qdlr= 0x0, ! 24: /* printer status register */ ! 25: Qpsr= 0x1, ! 26: Fnotbusy= 0x80, ! 27: Fack= 0x40, ! 28: Fpe= 0x20, ! 29: Fselect= 0x10, ! 30: Fnoerror= 0x08, ! 31: /* printer control register */ ! 32: Qpcr= 0x2, ! 33: Fie= 0x10, ! 34: Fselectin= 0x08, ! 35: Finitbar= 0x04, ! 36: Faf= 0x02, ! 37: Fstrobe= 0x01, ! 38: /* fake `data register' */ ! 39: Qdata= 0x3, ! 40: }; ! 41: ! 42: static int lptready(void*); ! 43: static void outch(int, int); ! 44: static void lptintr(Ureg*, void*); ! 45: ! 46: static Rendez lptrendez; ! 47: ! 48: Dirtab lptdir[]={ ! 49: "dlr", {Qdlr}, 1, 0666, ! 50: "psr", {Qpsr}, 5, 0444, ! 51: "pcr", {Qpcr}, 0, 0222, ! 52: "data", {Qdata}, 0, 0222, ! 53: }; ! 54: #define NLPT (sizeof lptdir/sizeof lptdir[0]) ! 55: ! 56: static int ! 57: lptgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) ! 58: { ! 59: Qid qid; ! 60: char name[NAMELEN]; ! 61: ! 62: if(tab==0 || i>=ntab) ! 63: return -1; ! 64: tab += i; ! 65: qid = tab->qid; ! 66: if(qid.path < Qdata) ! 67: qid.path += lptbase[c->dev]; ! 68: qid.vers = c->dev; ! 69: sprint(name, "lpt%d%s", c->dev+1, tab->name); ! 70: devdir(c, qid, name, tab->length, eve, tab->perm, dp); ! 71: return 1; ! 72: } ! 73: ! 74: void ! 75: lptreset(void) ! 76: { ! 77: } ! 78: ! 79: void ! 80: lptinit(void) ! 81: {} ! 82: ! 83: Chan* ! 84: lptattach(char *spec) ! 85: { ! 86: Chan *c; ! 87: int i = (spec && *spec) ? strtol(spec, 0, 0) : 1; ! 88: static int set; ! 89: ! 90: if(!set){ ! 91: set = 1; ! 92: setvec(Parallelvec, lptintr, 0); ! 93: } ! 94: if(i < 1 || i > NDEV) ! 95: error(Ebadarg); ! 96: c = devattach('L', spec); ! 97: c->dev = i-1; ! 98: return c; ! 99: } ! 100: ! 101: Chan* ! 102: lptclone(Chan *c, Chan *nc) ! 103: { ! 104: return devclone(c, nc); ! 105: } ! 106: ! 107: int ! 108: lptwalk(Chan *c, char *name) ! 109: { ! 110: return devwalk(c, name, lptdir, NLPT, lptgen); ! 111: } ! 112: ! 113: void ! 114: lptstat(Chan *c, char *dp) ! 115: { ! 116: devstat(c, dp, lptdir, NLPT, lptgen); ! 117: } ! 118: ! 119: Chan* ! 120: lptopen(Chan *c, int omode) ! 121: { ! 122: return devopen(c, omode, lptdir, NLPT, lptgen); ! 123: } ! 124: ! 125: void ! 126: lptcreate(Chan *c, char *name, int omode, ulong perm) ! 127: { ! 128: USED(c, name, omode, perm); ! 129: error(Eperm); ! 130: } ! 131: ! 132: void ! 133: lptclose(Chan *c) ! 134: { ! 135: USED(c); ! 136: } ! 137: ! 138: void ! 139: lptremove(Chan *c) ! 140: { ! 141: USED(c); ! 142: error(Eperm); ! 143: } ! 144: ! 145: void ! 146: lptwstat(Chan *c, char *dp) ! 147: { ! 148: USED(c, dp); ! 149: error(Eperm); ! 150: } ! 151: ! 152: long ! 153: lptread(Chan *c, void *a, long n) ! 154: { ! 155: char str[16]; int size; ! 156: ! 157: if(c->qid.path == CHDIR) ! 158: return devdirread(c, a, n, lptdir, NLPT, lptgen); ! 159: size = sprint(str, "0x%2.2ux\n", inb(c->qid.path)); ! 160: if(c->offset >= size) ! 161: return 0; ! 162: if(c->offset+n > size) ! 163: n = size-c->offset; ! 164: memmove(a, str+c->offset, n); ! 165: return n; ! 166: } ! 167: ! 168: long ! 169: lptwrite(Chan *c, void *a, long n) ! 170: { ! 171: char str[16], *p; ! 172: long base, k; ! 173: ! 174: if(n <= 0) ! 175: return 0; ! 176: if(c->qid.path != Qdata){ ! 177: if(n > sizeof str-1) ! 178: n = sizeof str-1; ! 179: memmove(str, a, n); ! 180: str[n] = 0; ! 181: outb(c->qid.path, strtoul(str, 0, 0)); ! 182: return n; ! 183: } ! 184: p = a; ! 185: k = n; ! 186: base = lptbase[c->dev]; ! 187: if(waserror()){ ! 188: outb(base+Qpcr, Finitbar); ! 189: nexterror(); ! 190: } ! 191: while(--k >= 0) ! 192: outch(base, *p++); ! 193: poperror(); ! 194: return n; ! 195: } ! 196: ! 197: static void ! 198: outch(int base, int c) ! 199: { ! 200: int status, tries; ! 201: ! 202: for(tries = 0;; tries++){ ! 203: status = inb(base+Qpsr); ! 204: if(!(status & Fselect) || !(status & Fnoerror)) ! 205: error(Eio); ! 206: if(status & Fnotbusy) ! 207: break; ! 208: if(tries > 1000){ ! 209: outb(base+Qpcr, Finitbar|Fie); ! 210: tsleep(&lptrendez, lptready, (void *)base, MS2HZ); ! 211: } ! 212: } ! 213: outb(base+Qdlr, c); ! 214: outb(base+Qpcr, Finitbar|Fstrobe); ! 215: outb(base+Qpcr, Finitbar); ! 216: } ! 217: ! 218: static int ! 219: lptready(void *base) ! 220: { ! 221: return inb((int)base+Qpsr)&Fnotbusy; ! 222: } ! 223: ! 224: static void ! 225: lptintr(Ureg *ur, void *a) ! 226: { ! 227: USED(ur, a); ! 228: wakeup(&lptrendez); ! 229: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.