|
|
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.