📄 devlpt.c
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h"/* Centronix parallel (printer) port *//* base addresses */static int lptbase[] = { 0x378, /* lpt1 */ 0x3bc, /* lpt2 */ 0x278 /* lpt3 (sic) */};#define NDEV nelem(lptbase)static int lptallocd[NDEV];/* offsets, and bits in the registers */enum{ Qdir= 0x8000, /* data latch register */ Qdlr= 0x0, /* printer status register */ Qpsr= 0x1, Fnotbusy= 0x80, Fack= 0x40, Fpe= 0x20, Fselect= 0x10, Fnoerror= 0x08, /* printer control register */ Qpcr= 0x2, Fie= 0x10, Fselectin= 0x08, Finitbar= 0x04, Faf= 0x02, Fstrobe= 0x01, /* fake `data register' */ Qdata= 0x3,};static int lptready(void*);static void outch(int, int);static void lptintr(Ureg*, void*);static Rendez lptrendez;Dirtab lptdir[]={ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "dlr", {Qdlr}, 1, 0666, "psr", {Qpsr}, 5, 0444, "pcr", {Qpcr}, 0, 0222, "data", {Qdata}, 0, 0222,};static intlptgen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp){ Qid qid; if(i == DEVDOTDOT){ mkqid(&qid, Qdir, 0, QTDIR); devdir(c, qid, ".", 0, eve, 0555, dp); return 1; } i++; /* skip first element for . itself */ if(tab==0 || i>=ntab) return -1; tab += i; qid = tab->qid; qid.path &= ~Qdir; if(qid.path < Qdata) qid.path += lptbase[c->dev]; qid.vers = c->dev; sprint(up->genbuf, "lpt%lud%s", c->dev+1, tab->name); devdir(c, qid, up->genbuf, tab->length, eve, tab->perm, dp); return 1;}static Chan*lptattach(char *spec){ Chan *c; int i = (spec && *spec) ? strtol(spec, 0, 0) : 1; char name[5]; static int set; if(!set){ outb(lptbase[i-1]+Qpcr, 0); /* turn off interrupts */ set = 1; intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN, "lpt"); } if(i < 1 || i > NDEV) error(Ebadarg); if(lptallocd[i-1] == 0){ int ecr; sprint(name, "lpt%d", i-1); if(ioalloc(lptbase[i-1], 3, 0, name) < 0) error("lpt port space in use"); lptallocd[i-1] = 1; // Detect ECP - if found, put into PS/2 mode to suit style of driver ecr = lptbase[i-1] + 0x402; if ((inb(ecr) & 3) == 1) { outb(ecr, 0x34); if (inb(ecr) == 0x35) { outb(ecr, (inb(ecr) & 0x1f) | (1 << 5)); if(ioalloc(ecr, 1, 0, name) < 0) error("lpt ecr port space in use"); } } } c = devattach('L', spec); c->qid.path = Qdir; c->dev = i-1; return c;}static Walkqid*lptwalk(Chan *c, Chan *nc, char **name, int nname){ return devwalk(c, nc, name, nname, lptdir, nelem(lptdir), lptgen);}static intlptstat(Chan *c, uchar *dp, int n){ return devstat(c, dp, n, lptdir, nelem(lptdir), lptgen);}static Chan*lptopen(Chan *c, int omode){ return devopen(c, omode, lptdir, nelem(lptdir), lptgen);}static voidlptclose(Chan *){}static longlptread(Chan *c, void *a, long n, vlong){ char str[16]; int size; ulong o; if(c->qid.path == Qdir) return devdirread(c, a, n, lptdir, nelem(lptdir), lptgen); size = sprint(str, "0x%2.2ux\n", inb(c->qid.path)); o = c->offset; if(o >= size) return 0; if(o+n > size) n = size-c->offset; memmove(a, str+o, n); return n;}static longlptwrite(Chan *c, void *a, long n, vlong){ char str[16], *p; long base, k; if(n <= 0) return 0; if(c->qid.path != Qdata){ if(n > sizeof str-1) n = sizeof str-1; memmove(str, a, n); str[n] = 0; outb(c->qid.path, strtoul(str, 0, 0)); return n; } p = a; k = n; base = lptbase[c->dev]; if(waserror()){ outb(base+Qpcr, Finitbar); nexterror(); } while(--k >= 0) outch(base, *p++); poperror(); return n;}static voidoutch(int base, int c){ int status, tries; for(tries=0;; tries++) { status = inb(base+Qpsr); if(status&Fnotbusy) break; if((status&Fpe)==0 && (status&(Fselect|Fnoerror)) != (Fselect|Fnoerror)) error(Eio); if(tries < 10) tsleep(&lptrendez, return0, nil, 1); else { outb(base+Qpcr, Finitbar|Fie); tsleep(&lptrendez, lptready, (void *)base, 100); } } outb(base+Qdlr, c); outb(base+Qpcr, Finitbar|Fstrobe); outb(base+Qpcr, Finitbar);}static intlptready(void *base){ return inb((int)base+Qpsr)&Fnotbusy;}static voidlptintr(Ureg *, void *){ wakeup(&lptrendez);}Dev lptdevtab = { 'L', "lpt", devreset, devinit, devshutdown, lptattach, lptwalk, lptstat, lptopen, devcreate, lptclose, lptread, devbread, lptwrite, devbwrite, devremove, devwstat,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -