2 #include "../port/lib.h"
7 #include "../port/error.h"
9 /* Centronix parallel (printer) port */
12 static int lptbase[] = {
15 0x278 /* lpt3 (sic) */
17 #define NDEV nelem(lptbase)
18 static int lptallocd[NDEV];
20 /* offsets, and bits in the registers */
24 /* data latch register */
26 /* printer status register */
33 /* printer control register */
40 /* fake `data register' */
44 static int lptready(void*);
45 static void outch(int, int);
46 static void lptintr(Ureg*, void*);
48 static Rendez lptrendez;
51 ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
52 "dlr", {Qdlr}, 1, 0666,
53 "psr", {Qpsr}, 5, 0444,
54 "pcr", {Qpcr}, 0, 0222,
55 "data", {Qdata}, 0, 0222,
59 lptgen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp)
64 mkqid(&qid, Qdir, 0, QTDIR);
65 devdir(c, qid, ".", 0, eve, 0555, dp);
68 i++; /* skip first element for . itself */
75 qid.path += lptbase[c->dev];
77 snprint(up->genbuf, sizeof up->genbuf, "lpt%lud%s", c->dev+1, tab->name);
78 devdir(c, qid, up->genbuf, tab->length, eve, tab->perm, dp);
86 int i = (spec && *spec) ? strtol(spec, 0, 0) : 1;
91 outb(lptbase[i-1]+Qpcr, 0); /* turn off interrupts */
93 intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN, "lpt");
97 if(lptallocd[i-1] == 0){
99 snprint(name, sizeof name, "lpt%d", i-1);
100 if(ioalloc(lptbase[i-1], 3, 0, name) < 0)
101 error("lpt port space in use");
103 /* Detect ECP - if found, put into PS/2 mode to suit style of driver */
104 ecr = lptbase[i-1] + 0x402;
105 if ((inb(ecr) & 3) == 1) {
107 if (inb(ecr) == 0x35) {
108 outb(ecr, (inb(ecr) & 0x1f) | (1 << 5));
109 if(ioalloc(ecr, 1, 0, name) < 0)
110 error("lpt ecr port space in use");
114 c = devattach('L', spec);
121 lptwalk(Chan *c, Chan *nc, char **name, int nname)
123 return devwalk(c, nc, name, nname, lptdir, nelem(lptdir), lptgen);
127 lptstat(Chan *c, uchar *dp, int n)
129 return devstat(c, dp, n, lptdir, nelem(lptdir), lptgen);
133 lptopen(Chan *c, int omode)
135 return devopen(c, omode, lptdir, nelem(lptdir), lptgen);
144 lptread(Chan *c, void *a, long n, vlong)
150 if(c->qid.path == Qdir)
151 return devdirread(c, a, n, lptdir, nelem(lptdir), lptgen);
152 size = snprint(str, sizeof str, "0x%2.2ux\n", inb(c->qid.path));
158 memmove(a, str+o, n);
163 lptwrite(Chan *c, void *a, long n, vlong)
170 if(c->qid.path != Qdata){
175 outb(c->qid.path, strtoul(str, 0, 0));
180 base = lptbase[c->dev];
182 outb(base+Qpcr, Finitbar);
192 outch(int base, int c)
196 for(tries=0;; tries++) {
197 status = inb(base+Qpsr);
200 if((status&Fpe)==0 && (status&(Fselect|Fnoerror)) != (Fselect|Fnoerror))
202 outb(base+Qpcr, Finitbar|Fie);
203 tsleep(&lptrendez, lptready, (void *)base, 100);
206 outb(base+Qpcr, Finitbar|Fstrobe);
207 outb(base+Qpcr, Finitbar);
213 return inb((int)base+Qpsr)&Fnotbusy;
217 lptintr(Ureg *, void *)