|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1993-1990 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * Parallel port printer driver v1.0
28: * All rights reserved.
29: */
30:
31: #include <lpr.h>
32: #if NLPR > 0
33: #include <par.h>
34: #include <de6c.h>
35:
36: #ifdef MACH_KERNEL
37: #include <mach/std_types.h>
38: #include <sys/types.h>
39: #include <sys/time.h>
40: #include <device/conf.h>
41: #include <device/errno.h>
42: #include <device/tty.h>
43: #include <device/io_req.h>
44: #else MACH_KERNEL
45: #include <sys/param.h>
46: #include <sys/conf.h>
47: #include <sys/dir.h>
48: #include <sys/user.h>
49: #include <sys/proc.h>
50: #include <sys/ioctl.h>
51: #include <sys/tty.h>
52: #include <sys/systm.h>
53: #include <sys/uio.h>
54: #include <sys/file.h>
55: #endif MACH_KERNEL
56:
57: #include <i386/ipl.h>
58: #include <i386/pio.h>
59: #include <chips/busses.h>
60: #include <i386at/lprreg.h>
61:
62: #if NPAR > 0
63: extern int parattach();
64: #endif
65:
66: #if NDE6C > 0
67: extern int de6cattach();
68: #endif
69:
70: extern void splx();
71: extern spl_t spltty();
72: extern void timeout();
73: extern void ttrstrt();
74:
75: /*
76: * Driver information for auto-configuration stuff.
77: */
78:
79: int lprprobe(), lprintr(), lprstart(), lprstop();
80: void lprattach(struct bus_device *);
81: #ifdef MACH_KERNEL
82: int lprstop(), lprgetstat(), lprsetstat();
83: #endif MACH_KERNEL
84:
85: struct bus_device *lprinfo[NLPR]; /* ??? */
86:
87: static vm_offset_t lpr_std[NLPR] = { 0 };
88: static struct bus_device *lpr_info[NLPR];
89: struct bus_driver lprdriver = {
90: lprprobe, 0, lprattach, 0, lpr_std, "lpr", lpr_info, 0, 0, 0};
91:
92: struct tty lpr_tty[NLPR];
93:
94: int lpr_alive[NLPR];
95:
96: lprprobe(port, dev)
97: struct bus_device *dev;
98: {
99: u_short addr = (u_short) dev->address;
100: int unit = dev->unit;
101: int ret;
102:
103: if ((unit < 0) || (unit > NLPR)) {
104: printf("com %d out of range\n", unit);
105: return(0);
106: }
107:
108: outb(INTR_ENAB(addr),0x07);
109: outb(DATA(addr),0xaa);
110: ret = inb(DATA(addr)) == 0xaa;
111: if (ret) {
112: if (lpr_alive[unit]) {
113: printf("lpr: Multiple alive entries for unit %d.\n", unit);
114: printf("lpr: Ignoring entry with address = %x .\n", addr);
115: ret = 0;
116: } else
117: lpr_alive[unit]++;
118: }
119: return(ret);
120: }
121:
122: void lprattach(struct bus_device *dev)
123: {
124: u_char unit = dev->unit;
125: u_short addr = (u_short) dev->address;
126: struct tty *tp = &lpr_tty[unit];
127:
128: take_dev_irq(dev);
129: printf(", port = %x, spl = %d, pic = %d.",
130: dev->address, dev->sysdep, dev->sysdep1);
131: lprinfo[unit] = dev;
132:
133: outb(INTR_ENAB(addr), inb(INTR_ENAB(addr)) & 0x0f);
134:
135: #if NPAR > 0
136: parattach(dev);
137: #endif
138:
139: #if NDE6C > 0 && !defined(LINUX_DEV)
140: de6cattach(dev);
141: #endif
142: return;
143: }
144:
145: lpropen(dev, flag, ior)
146: int dev;
147: int flag;
148: #ifdef MACH_KERNEL
149: io_req_t ior;
150: #endif MACH_KERNEL
151: {
152: int unit = minor(dev);
153: struct bus_device *isai;
154: struct tty *tp;
155: u_short addr;
156:
157: if (unit >= NLPR || (isai = lprinfo[unit]) == 0 || isai->alive == 0)
158: return(ENXIO);
159: tp = &lpr_tty[unit];
160: #ifndef MACH_KERNEL
161: if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
162: return(EBUSY);
163: #endif MACH_KERNEL
164: addr = (u_short) isai->address;
165: tp->t_dev = dev;
166: tp->t_addr = *(caddr_t *)&addr;
167: tp->t_oproc = lprstart;
168: tp->t_state |= TS_WOPEN;
169: #ifdef MACH_KERNEL
170: tp->t_stop = lprstop;
171: tp->t_getstat = lprgetstat;
172: tp->t_setstat = lprsetstat;
173: #endif MACH_KERNEL
174: if ((tp->t_state & TS_ISOPEN) == 0)
175: ttychars(tp);
176: outb(INTR_ENAB(addr), inb(INTR_ENAB(addr)) | 0x10);
177: tp->t_state |= TS_CARR_ON;
178: return (char_open(dev, tp, flag, ior));
179: }
180:
181: lprclose(dev, flag)
182: int dev;
183: int flag;
184: {
185: int unit = minor(dev);
186: struct tty *tp = &lpr_tty[unit];
187: u_short addr = (u_short) lprinfo[unit]->address;
188:
189: #ifndef MACH_KERNEL
190: (*linesw[tp->t_line].l_close)(tp);
191: #endif MACH_KERNEL
192: ttyclose(tp);
193: if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) {
194: outb(INTR_ENAB(addr), inb(INTR_ENAB(addr)) & 0x0f);
195: tp->t_state &= ~TS_BUSY;
196: }
197: }
198:
199: #ifdef MACH_KERNEL
200: lprread(dev, ior)
201: int dev;
202: io_req_t ior;
203: {
204: return char_read(&lpr_tty[minor(dev)], ior);
205: }
206:
207: lprwrite(dev, ior)
208: int dev;
209: io_req_t ior;
210: {
211: return char_write(&lpr_tty[minor(dev)], ior);
212: }
213:
214: lprportdeath(dev, port)
215: dev_t dev;
216: mach_port_t port;
217: {
218: return (tty_portdeath(&lpr_tty[minor(dev)], port));
219: }
220:
221: io_return_t
222: lprgetstat(dev, flavor, data, count)
223: dev_t dev;
224: int flavor;
225: int *data; /* pointer to OUT array */
226: unsigned int *count; /* out */
227: {
228: io_return_t result = D_SUCCESS;
229: int unit = minor(dev);
230:
231: switch (flavor) {
232: default:
233: result = tty_get_status(&lpr_tty[unit], flavor, data, count);
234: break;
235: }
236: return (result);
237: }
238:
239: io_return_t
240: lprsetstat(dev, flavor, data, count)
241: dev_t dev;
242: int flavor;
243: int * data;
244: unsigned int count;
245: {
246: io_return_t result = D_SUCCESS;
247: int unit = minor(dev);
248: u_short dev_addr = (u_short) lprinfo[unit]->address;
249: int s;
250:
251: switch (flavor) {
252: default:
253: result = tty_set_status(&lpr_tty[unit], flavor, data, count);
254: /* if (result == D_SUCCESS && flavor == TTY_STATUS)
255: lprparam(unit);
256: */ return (result);
257: }
258: return (D_SUCCESS);
259: }
260: #else MACH_KERNEL
261: int lprwrite(dev, uio)
262: int dev;
263: struct uio *uio;
264: {
265: struct tty *tp= &lpr_tty[minor(dev)];
266:
267: return ((*linesw[tp->t_line].l_write)(tp, uio));
268: }
269:
270: int lprioctl(dev, cmd, addr, mode)
271: int dev;
272: int cmd;
273: caddr_t addr;
274: int mode;
275: {
276: int error;
277: spl_t s;
278: int unit = minor(dev);
279: struct tty *tp = &lpr_tty[unit];
280:
281: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr,mode);
282: if (error >= 0)
283: return(error);
284: error = ttioctl(tp, cmd, addr,mode);
285: if (error >= 0)
286: return (error);
287: s = spltty();
288: switch (cmd) {
289: default:
290: splx(s);
291: return(ENOTTY);
292: }
293: splx(s);
294: return(0);
295: }
296: #endif MACH_KERNEL
297:
298: int lprintr(unit)
299: int unit;
300: {
301: register struct tty *tp = &lpr_tty[unit];
302:
303: if ((tp->t_state & TS_ISOPEN) == 0)
304: return;
305:
306: tp->t_state &= ~TS_BUSY;
307: if (tp->t_state&TS_FLUSH)
308: tp->t_state &=~TS_FLUSH;
309: tt_write_wakeup(tp);
310: lprstart(tp);
311: }
312:
313: int lprstart(tp)
314: struct tty *tp;
315: {
316: spl_t s = spltty();
317: u_short addr = (natural_t) tp->t_addr;
318: int status = inb(STATUS(addr));
319: char nch;
320:
321: if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) {
322: splx(s);
323: return(0);
324: }
325:
326: if (status & 0x20) {
327: printf("Printer out of paper!\n");
328: splx(s);
329: return(0);
330: }
331:
332: if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
333: #ifdef MACH_KERNEL
334: tt_write_wakeup(tp);
335: #else MACH_KERNEL
336: if (tp->t_state & TS_ASLEEP) {
337: tp->t_state &= ~TS_ASLEEP;
338: wakeup ((caddr_t)&tp->t_outq);
339: }
340: if (tp->t_wsel) {
341: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
342: tp->t_wsel = 0;
343: tp->t_state &= ~TS_WCOLL;
344: }
345: #endif MACH_KERNEL
346: }
347: if (tp->t_outq.c_cc == 0) {
348: splx(s);
349: return(0);
350: }
351: #ifdef MACH_KERNEL
352: nch = getc(&tp->t_outq);
353: if ((tp->t_flags & LITOUT) == 0 && (nch & 0200)) {
354: timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
355: tp->t_state |= TS_TIMEOUT;
356: return;
357: }
358: outb(DATA(addr), nch);
359: outb(INTR_ENAB(addr),inb(INTR_ENAB(addr)) | 0x01);
360: outb(INTR_ENAB(addr),inb(INTR_ENAB(addr)) & 0x1e);
361: tp->t_state |= TS_BUSY;
362: #else MACH_KERNEL
363: if (tp->t_flags & (RAW|LITOUT))
364: nch = ndqb(&tp->t_outq,0);
365: else {
366: nch = ndqb(&tp->t_outq, 0200);
367: if (nch == 0) {
368: nch = getc(&tp->t_outq);
369: timeout(ttrstrt,(caddr_t)tp,(nch&0x7f)+6);
370: tp->t_state |= TS_TIMEOUT;
371: splx(s);
372: return(0);
373: }
374: }
375: if (nch) {
376: nch=getc(&tp->t_outq);
377: outb(DATA(addr), nch);
378: outb(INTR_ENAB(addr),inb(INTR_ENAB(addr)) | 0x01);
379: outb(INTR_ENAB(addr),inb(INTR_ENAB(addr)) & 0x1e);
380: tp->t_state |= TS_BUSY;
381: }
382: #endif MACH_KERNEL
383: splx(s);
384: return(0);
385: }
386:
387: #ifdef MACH_KERNEL
388: lprstop(tp, flags)
389: register struct tty *tp;
390: int flags;
391: {
392: if ((tp->t_state & TS_BUSY) && (tp->t_state & TS_TTSTOP) == 0)
393: tp->t_state |= TS_FLUSH;
394: }
395: #else MACH_KERNEL
396: int lprstop(tp, flag)
397: struct tty *tp;
398: {
399: int s = spltty();
400:
401: if ((tp->t_state&TS_BUSY) && (!(tp->t_state&TS_TTSTOP)))
402: tp->t_state |= TS_FLUSH;
403: splx(s);
404: }
405: #endif MACH_KERNEL
406: lprpr(unit)
407: {
408: lprpr_addr(lprinfo[unit]->address);
409: return 0;
410: }
411:
412: lprpr_addr(addr)
413: {
414: printf("DATA(%x) %x, STATUS(%x) %x, INTR_ENAB(%x) %x\n",
415: DATA(addr), inb(DATA(addr)),
416: STATUS(addr), inb(STATUS(addr)),
417: INTR_ENAB(addr), inb(INTR_ENAB(addr)));
418: }
419: #endif NLPR
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.