|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1994,1993,1991,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: #include <com.h>
28: #if NCOM > 0
29:
30: #include <mach/std_types.h>
31: #include <sys/types.h>
32: #include <sys/time.h>
33: #include <device/conf.h>
34: #include <device/errno.h>
35: #include <device/tty.h>
36: #include <device/io_req.h>
37:
38: #include <i386/ipl.h>
39: #include <i386/pio.h>
40: #include <i386/machspl.h>
41: #include <chips/busses.h>
42: #include <i386at/comreg.h>
43:
44: #include <rc.h>
45: #include <cons.h>
46:
47: extern void timeout(), ttrstrt();
48:
49: int comprobe(), comintr(), comstart(), commctl();
50: void comattach();
51: static void comparam();
52: int comstop(), comgetstat(), comsetstat();
53:
54: static vm_offset_t com_std[NCOM] = { 0 };
55: struct bus_device *cominfo[NCOM];
56: struct bus_driver comdriver = {
57: comprobe, 0, comattach, 0, com_std, "com", cominfo, 0, 0, 0};
58:
59: struct tty com_tty[NCOM];
60: int commodem[NCOM];
61: int comcarrier[NCOM] = {0, 0,};
62: boolean_t comfifo[NCOM];
63: boolean_t comtimer_active;
64: int comtimer_state[NCOM];
65:
66: #if RCLINE >= 0
67: #define RCBAUD B9600
68: static struct bus_device *comcndev;
69: int comcnprobe(struct consdev *cp);
70: int comcninit(struct consdev *cp);
71: int comcngetc(dev_t dev, int wait);
72: int comcnputc(dev_t dev, int c);
73: #endif
74:
75: #ifndef PORTSELECTOR
76: #define ISPEED B9600
77: #define IFLAGS (EVENP|ODDP|ECHO|CRMOD)
78: #else
79: #define ISPEED B4800
80: #define IFLAGS (EVENP|ODDP)
81: #endif
82:
83: u_short divisorreg[] = {
84: 0, 2304, 1536, 1047, /* 0, 50, 75, 110*/
85: 857, 768, 576, 384, 192, /* 134.5, 150, 200, 300, 600*/
86: 96, 64, 48, /* 1200, 1800, 2000, 2400 */
87: 24, 12, /* 3600, 4800, 7200, 9600 */
88: 6, 3, 2}; /* 19200, 38400, 56000 */
89:
90:
91: /*
92: *
93: * Probes are called during kernel boot: return 1 to mean that
94: * the relevant device is present today.
95: *
96: */
97: int
98: comprobe_general(struct bus_device *dev, int noisy)
99: {
100: u_short addr = dev->address;
101: int unit = dev->unit;
102: int oldctl, oldmsb;
103: char *type = "8250";
104: int i;
105:
106: if ((unit < 0) || (unit > NCOM)) {
107: printf("com %d out of range\n", unit);
108: return(0);
109: }
110: oldctl = inb(LINE_CTL(addr)); /* Save old value of LINE_CTL */
111: oldmsb = inb(BAUD_MSB(addr)); /* Save old value of BAUD_MSB */
112: outb(LINE_CTL(addr), 0); /* Select INTR_ENAB */
113: outb(BAUD_MSB(addr), 0);
114: if (inb(BAUD_MSB(addr)) != 0)
115: {
116: outb(LINE_CTL(addr), oldctl);
117: outb(BAUD_MSB(addr), oldmsb);
118: return 0;
119: }
120: outb(LINE_CTL(addr), iDLAB); /* Select BAUD_MSB */
121: outb(BAUD_MSB(addr), 255);
122: if (inb(BAUD_MSB(addr)) != 255)
123: {
124: outb(LINE_CTL(addr), oldctl);
125: outb(BAUD_MSB(addr), oldmsb);
126: return 0;
127: }
128: outb(LINE_CTL(addr), 0); /* Select INTR_ENAB */
129: if (inb(BAUD_MSB(addr)) != 0) /* Check that it has kept its value*/
130: {
131: outb(LINE_CTL(addr), oldctl);
132: outb(BAUD_MSB(addr), oldmsb);
133: return 0;
134: }
135:
136: /* Com port found, now check what chip it has */
137:
138: for(i = 0; i < 256; i++) /* Is there Scratch register */
139: {
140: outb(SCR(addr), i);
141: if (inb(SCR(addr)) != i)
142: break;
143: }
144: if (i == 256)
145: { /* Yes == 450 or 460 */
146: outb(SCR(addr), 0);
147: type = "82450 or 16450";
148: outb(FIFO_CTL(addr), iFIFOENA | iFIFO14CH); /* Enable fifo */
149: if ((inb(FIFO_CTL(addr)) & iFIFO14CH) != 0)
150: { /* Was it successfull */
151: /* if both bits are not set then broken xx550 */
152: if ((inb(FIFO_CTL(addr)) & iFIFO14CH) == iFIFO14CH)
153: {
154: type = "82550 or 16550";
155: comfifo[unit] = TRUE;
156: }
157: else
158: {
159: type = "82550 or 16550 with non-working FIFO";
160: }
161: outb(INTR_ID(addr), 0x00); /* Disable fifos */
162: }
163: }
164: if (noisy)
165: printf("com%d: %s chip.\n", unit, type);
166: return 1;
167: }
168:
169: /*
170: * Probe routine for use during kernel startup when it is probing
171: * all of bus_device_init
172: */
173: int
174: comprobe(int port, struct bus_device *dev)
175: {
176: return comprobe_general(dev, /*noisy*/ 0);
177: }
178:
179: #if RCLINE >= 0
180: /*
181: * Probe routine for use by the console
182: */
183: int
184: comcnprobe(struct consdev *cp)
185: {
186: struct bus_device *b;
187: int maj, unit, pri;
188:
189: maj = 0;
190: unit = -1;
191: pri = CN_DEAD;
192:
193: for (b = bus_device_init; b->driver; b++)
194: if (strcmp(b->name, "com") == 0
195: && b->unit == RCLINE
196: && comprobe_general(b, /*quiet*/ 0))
197: {
198: /* Found one */
199: comcndev = b;
200: unit = b->unit;
201: pri = CN_REMOTE;
202: break;
203: }
204:
205: cp->cn_dev = makedev(maj, unit);
206: cp->cn_pri = pri;
207: }
208: #endif
209:
210:
211: /*
212: *
213: * Device Attach's are called during kernel boot, but only if the matching
214: * device Probe returned a 1.
215: *
216: */
217: void
218: comattach(struct bus_device *dev)
219: {
220: u_char unit = dev->unit;
221: u_short addr = dev->address;
222:
223: take_dev_irq(dev);
224: printf(", port = %x, spl = %d, pic = %d. (DOS COM%d)",
225: dev->address, dev->sysdep, dev->sysdep1, unit+1);
226:
227: /* comcarrier[unit] = addr->flags;*/
228: commodem[unit] = 0;
229:
230: outb(INTR_ENAB(addr), 0);
231: outb(MODEM_CTL(addr), 0);
232: while (!(inb(INTR_ID(addr))&1)) {
233: (void) inb(LINE_STAT (addr)); /* reset overrun error etc */
234: (void) inb(TXRX (addr)); /* reset data-ready */
235: (void) inb(MODEM_STAT(addr)); /* reset modem status reg */
236: }
237: }
238:
239: #if RCLINE >= 0
240: /*
241: * Attach/init routine for console. This isn't called by
242: * configure_bus_device which sets the alive, adaptor, and minfo
243: * fields of the bus_device struct (comattach is), therefore we do
244: * that by hand.
245: */
246: int
247: comcninit(struct consdev *cp)
248: {
249: u_char unit = comcndev->unit;
250: u_short addr = comcndev->address;
251:
252: take_dev_irq(comcndev);
253:
254: comcndev->alive = 1;
255: comcndev->adaptor = 0;
256: cominfo[minor(cp->cn_dev)] = comcndev;
257:
258: outb(LINE_CTL(addr), iDLAB);
259: outb(BAUD_LSB(addr), divisorreg[RCBAUD] & 0xff);
260: outb(BAUD_MSB(addr), divisorreg[RCBAUD] >>8);
261: outb(LINE_CTL(addr), i7BITS|iPEN);
262: outb(INTR_ENAB(addr), 0);
263: outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2);
264:
265: {
266: char msg[128];
267: volatile unsigned char *p = (volatile unsigned char *)0xb8000;
268: int i;
269:
270: sprintf(msg, " **** using COM port %d for console ****",
271: unit+1);
272: for (i = 0; msg[i]; i++) {
273: p[2*i] = msg[i];
274: p[2*i+1] = (0<<7) /* blink */
275: | (0x0<<4) /* bg */
276: | (1<<3) /* hi-intensity */
277: | 0x4; /* fg */
278: }
279: }
280:
281: }
282: #endif
283:
284: /*
285: * Probe for COM<dev> after autoconfiguration.
286: * Used to handle PCMCIA modems, which may appear
287: * at any time.
288: */
289: boolean_t com_reprobe(
290: int unit)
291: {
292: struct bus_device *device;
293:
294: /*
295: * Look for COM device <unit> in the device
296: * initialization list. It must not be alive
297: * (otherwise we would have opened it already).
298: */
299: for (device = bus_device_init; device->driver; device++) {
300: if (device->driver == &comdriver && device->unit == unit &&
301: !device->alive && device->ctlr == (char)-1)
302: {
303: /*
304: * Found an entry for com port <unit>.
305: * Probe it.
306: */
307: if (configure_bus_device(device->name,
308: device->address,
309: device->phys_address,
310: 0,
311: "atbus"))
312: return TRUE;
313: }
314: }
315: return FALSE;
316: }
317:
318: io_return_t comopen(
319: int dev,
320: int flag,
321: io_req_t ior)
322: {
323: int unit = minor(dev);
324: u_short addr;
325: struct bus_device *isai;
326: struct tty *tp;
327: spl_t s;
328: io_return_t result;
329:
330: if (unit >= NCOM)
331: return ENXIO; /* no such device */
332: if ((isai = cominfo[unit]) == 0 || isai->alive == 0) {
333: /*
334: * Try to probe it again
335: */
336: if (!com_reprobe(unit))
337: return ENXIO;
338: }
339: tp = &com_tty[unit];
340:
341: if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0) {
342: ttychars(tp);
343: tp->t_addr = (char *)isai->address;
344: tp->t_dev = dev;
345: tp->t_oproc = comstart;
346: tp->t_stop = comstop;
347: tp->t_mctl = commctl;
348: tp->t_getstat = comgetstat;
349: tp->t_setstat = comsetstat;
350: #ifndef PORTSELECTOR
351: if (tp->t_ispeed == 0) {
352: #else
353: tp->t_state |= TS_HUPCLS;
354: #endif /* PORTSELECTOR */
355: tp->t_ispeed = ISPEED;
356: tp->t_ospeed = ISPEED;
357: tp->t_flags = IFLAGS;
358: tp->t_state &= ~TS_BUSY;
359: #ifndef PORTSELECTOR
360: }
361: #endif /* PORTSELECTOR */
362: }
363: /*rvb tp->t_state |= TS_WOPEN; */
364: if ((tp->t_state & TS_ISOPEN) == 0)
365: comparam(unit);
366: addr = (int)tp->t_addr;
367:
368: s = spltty();
369: if (!comcarrier[unit]) /* not originating */
370: tp->t_state |= TS_CARR_ON;
371: else {
372: int modem_stat = inb(MODEM_STAT(addr));
373: if (modem_stat & iRLSD)
374: tp->t_state |= TS_CARR_ON;
375: else
376: tp->t_state &= ~TS_CARR_ON;
377: fix_modem_state(unit, modem_stat);
378: }
379: splx(s);
380:
381: result = char_open(dev, tp, flag, ior);
382:
383: if (!comtimer_active) {
384: comtimer_active = TRUE;
385: comtimer();
386: }
387:
388: s = spltty();
389: while(!(inb(INTR_ID(addr))&1)) { /* while pending interrupts */
390: (void) inb(LINE_STAT (addr)); /* reset overrun error */
391: (void) inb(TXRX (addr)); /* reset data-ready */
392: (void) inb(MODEM_STAT(addr)); /* reset modem status */
393: }
394: splx(s);
395: return result;
396: }
397:
398: io_return_t comclose(dev, flag)
399: int dev;
400: int flag;
401: {
402: struct tty *tp = &com_tty[minor(dev)];
403: u_short addr = (int)tp->t_addr;
404:
405: ttyclose(tp);
406: if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) {
407: outb(INTR_ENAB(addr), 0);
408: outb(MODEM_CTL(addr), 0);
409: tp->t_state &= ~TS_BUSY;
410: commodem[minor(dev)] = 0;
411: if (comfifo[minor(dev)] != 0)
412: outb(INTR_ID(addr), 0x00); /* Disable fifos */
413: }
414: return 0;
415: }
416:
417: io_return_t comread(dev, ior)
418: int dev;
419: io_req_t ior;
420: {
421: return char_read(&com_tty[minor(dev)], ior);
422: }
423:
424: io_return_t comwrite(dev, ior)
425: int dev;
426: io_req_t ior;
427: {
428: return char_write(&com_tty[minor(dev)], ior);
429: }
430:
431: io_return_t comportdeath(dev, port)
432: dev_t dev;
433: mach_port_t port;
434: {
435: return (tty_portdeath(&com_tty[minor(dev)], port));
436: }
437:
438: io_return_t
439: comgetstat(dev, flavor, data, count)
440: dev_t dev;
441: int flavor;
442: int *data; /* pointer to OUT array */
443: unsigned int *count; /* out */
444: {
445: io_return_t result = D_SUCCESS;
446: int unit = minor(dev);
447:
448: switch (flavor) {
449: case TTY_MODEM:
450: fix_modem_state(unit, inb(MODEM_STAT(cominfo[unit]->address)));
451: *data = commodem[unit];
452: *count = 1;
453: break;
454: default:
455: result = tty_get_status(&com_tty[unit], flavor, data, count);
456: break;
457: }
458: return (result);
459: }
460:
461: io_return_t
462: comsetstat(dev, flavor, data, count)
463: dev_t dev;
464: int flavor;
465: int * data;
466: unsigned int count;
467: {
468: io_return_t result = D_SUCCESS;
469: int unit = minor(dev);
470: struct tty *tp = &com_tty[unit];
471:
472: switch (flavor) {
473: case TTY_SET_BREAK:
474: commctl(tp, TM_BRK, DMBIS);
475: break;
476: case TTY_CLEAR_BREAK:
477: commctl(tp, TM_BRK, DMBIC);
478: break;
479: case TTY_MODEM:
480: commctl(tp, *data, DMSET);
481: break;
482: default:
483: result = tty_set_status(&com_tty[unit], flavor, data, count);
484: if (result == D_SUCCESS && flavor == TTY_STATUS)
485: comparam(unit);
486: return (result);
487: }
488: return (D_SUCCESS);
489: }
490:
491: comintr(unit)
492: int unit;
493: {
494: register struct tty *tp = &com_tty[unit];
495: u_short addr = cominfo[unit]->address;
496: static char comoverrun = 0;
497: char c, line, intr_id;
498: int line_stat;
499:
500: while (! ((intr_id=(inb(INTR_ID(addr))&MASKi)) & 1))
501: switch (intr_id) {
502: case MODi:
503: /* modem change */
504: commodem_intr(unit, inb(MODEM_STAT(addr)));
505: break;
506:
507: case TRAi:
508: comtimer_state[unit] = 0;
509: tp->t_state &= ~(TS_BUSY|TS_FLUSH);
510: tt_write_wakeup(tp);
511: (void) comstart(tp);
512: break;
513: case RECi:
514: case CTIi: /* Character timeout indication */
515: if (tp->t_state&TS_ISOPEN) {
516: while ((line = inb(LINE_STAT(addr))) & iDR) {
517: c = inb(TXRX(addr));
518: ttyinput(c, tp);
519: }
520: } else
521: tt_open_wakeup(tp);
522: break;
523: case LINi:
524: line_stat = inb(LINE_STAT(addr));
525:
526: if ((line_stat & iPE) &&
527: ((tp->t_flags&(EVENP|ODDP)) == EVENP ||
528: (tp->t_flags&(EVENP|ODDP)) == ODDP)) {
529: /* parity error */;
530: } else if (line&iOR && !comoverrun) {
531: printf("com%d: overrun\n", unit);
532: comoverrun = 1;
533: } else if (line_stat & (iFE | iBRKINTR)) {
534: /* framing error or break */
535: ttyinput(tp->t_breakc, tp);
536: }
537: break;
538: }
539: }
540:
541: static void
542: comparam(unit)
543: register int unit;
544: {
545: struct tty *tp = &com_tty[unit];
546: u_short addr = (int)tp->t_addr;
547: spl_t s = spltty();
548: int mode;
549:
550: if (tp->t_ispeed == B0) {
551: tp->t_state |= TS_HUPCLS;
552: outb(MODEM_CTL(addr), iOUT2);
553: commodem[unit] = 0;
554: splx(s);
555: return;
556: }
557:
558: /* Do input buffering */
559: if (tp->t_ispeed >= B300)
560: tp->t_state |= TS_MIN;
561:
562: outb(LINE_CTL(addr), iDLAB);
563: outb(BAUD_LSB(addr), divisorreg[tp->t_ispeed] & 0xff);
564: outb(BAUD_MSB(addr), divisorreg[tp->t_ispeed] >> 8);
565:
566: if (tp->t_flags & (RAW|LITOUT|PASS8))
567: mode = i8BITS;
568: else
569: mode = i7BITS | iPEN;
570: if (tp->t_flags & EVENP)
571: mode |= iEPS;
572: if (tp->t_ispeed == B110)
573: /*
574: * 110 baud uses two stop bits -
575: * all other speeds use one
576: */
577: mode |= iSTB;
578:
579: outb(LINE_CTL(addr), mode);
580:
581: outb(INTR_ENAB(addr), iTX_ENAB|iRX_ENAB|iMODEM_ENAB|iERROR_ENAB);
582: if (comfifo[unit])
583: outb(FIFO_CTL(addr), iFIFOENA|iFIFO14CH);
584: outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2);
585: commodem[unit] |= (TM_DTR|TM_RTS);
586: splx(s);
587: }
588:
589: comparm(int unit, int baud, int intr, int mode, int modem)
590: {
591: u_short addr = (u_short)(cominfo[unit]->address);
592: spl_t s = spltty();
593:
594: if (unit != 0 && unit != 1) {
595: printf("comparm(unit, baud, mode, intr, modem)\n");
596: splx(s);
597: return;
598: }
599: outb(LINE_CTL(addr), iDLAB);
600: outb(BAUD_LSB(addr), divisorreg[baud] & 0xff);
601: outb(BAUD_MSB(addr), divisorreg[baud] >> 8);
602: outb(LINE_CTL(addr), mode);
603: outb(INTR_ENAB(addr), intr);
604: outb(MODEM_CTL(addr), modem);
605: splx(s);
606: }
607:
608: int comst_1, comst_2, comst_3, comst_4, comst_5 = 14;
609:
610: int
611: comstart(tp)
612: struct tty *tp;
613: {
614: char nch;
615: int i;
616:
617: if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) {
618: comst_1++;
619: return(0);
620: }
621: if ((!queue_empty(&tp->t_delayed_write)) &&
622: (tp->t_outq.c_cc <= TTLOWAT(tp))) {
623: comst_2++;
624: tt_write_wakeup(tp);
625: }
626: if (!tp->t_outq.c_cc) {
627: comst_3++;
628: return(0);
629: }
630:
631: #if 0
632: i = (comfifo[minor(tp->t_dev)]) ? /*14*/comst_5 : 1;
633:
634: tp->t_state |= TS_BUSY;
635: while (i-- > 0) {
636: nch = getc(&tp->t_outq);
637: if (nch == -1) break;
638: if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) {
639: timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
640: tp->t_state |= TS_TIMEOUT;
641: comst_4++;
642: return(0);
643: }
644: outb(TXRX((int)tp->t_addr), nch);
645: }
646: #else
647: nch = getc(&tp->t_outq);
648: if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) {
649: timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
650: tp->t_state |= TS_TIMEOUT;
651: comst_4++;
652: return(0);
653: }
654: outb(TXRX((int)tp->t_addr), nch);
655: tp->t_state |= TS_BUSY;
656: #endif
657: return(0);
658: }
659:
660: /* Check for stuck xmitters */
661: int comtimer_interval = 5;
662:
663: comtimer()
664: {
665: spl_t s = spltty();
666: struct tty *tp = com_tty;
667: int i, nch;
668:
669: for (i = 0; i < NCOM; i++, tp++) {
670: if ((tp->t_state & TS_ISOPEN) == 0)
671: continue;
672: if (!tp->t_outq.c_cc)
673: continue;
674: if (++comtimer_state[i] < 2)
675: continue;
676: /* Its stuck */
677: printf("Tty %x was stuck\n", tp);
678: nch = getc(&tp->t_outq);
679: outb(TXRX((int)tp->t_addr), nch);
680: }
681:
682: splx(s);
683: timeout(comtimer, 0, comtimer_interval*hz);
684: }
685:
686: /*
687: * Set receive modem state from modem status register.
688: */
689: fix_modem_state(unit, modem_stat)
690: int unit, modem_stat;
691: {
692: int stat = 0;
693:
694: if (modem_stat & iCTS)
695: stat |= TM_CTS; /* clear to send */
696: if (modem_stat & iDSR)
697: stat |= TM_DSR; /* data set ready */
698: if (modem_stat & iRI)
699: stat |= TM_RNG; /* ring indicator */
700: if (modem_stat & iRLSD)
701: stat |= TM_CAR; /* carrier? */
702:
703: commodem[unit] = (commodem[unit] & ~(TM_CTS|TM_DSR|TM_RNG|TM_CAR))
704: | stat;
705: }
706:
707: /*
708: * Modem change (input signals)
709: */
710: commodem_intr(
711: int unit,
712: int stat)
713: {
714: int changed;
715:
716: changed = commodem[unit];
717: fix_modem_state(unit, stat);
718: stat = commodem[unit];
719:
720: /* Assumption: if the other party can handle
721: modem signals then it should handle all
722: the necessary ones. Else fix the cable. */
723:
724: changed ^= stat; /* what changed ? */
725:
726: if (changed & TM_CTS)
727: tty_cts( &com_tty[unit], stat & TM_CTS );
728:
729: #if 0
730: if (changed & TM_CAR)
731: ttymodem( &com_tty[unit], stat & TM_CAR );
732: #endif
733:
734: }
735:
736: /*
737: * Set/get modem bits
738: */
739: commctl(
740: register struct tty *tp,
741: int bits,
742: int how)
743: {
744: spl_t s;
745: int unit;
746: vm_offset_t dev_addr;
747: register int b;
748:
749: unit = minor(tp->t_dev);
750:
751: if (bits == TM_HUP) { /* close line (internal) */
752: bits = TM_DTR | TM_RTS;
753: how = DMBIC;
754: }
755:
756: if (how == DMGET) return commodem[unit];
757:
758: dev_addr = cominfo[unit]->address;
759:
760: s = spltty();
761:
762: switch (how) {
763: case DMSET:
764: b = bits; break;
765: case DMBIS:
766: b = commodem[unit] | bits; break;
767: case DMBIC:
768: b = commodem[unit] & ~bits; break;
769: }
770: commodem[unit] = b;
771:
772: if (bits & TM_BRK) {
773: if (b & TM_BRK) {
774: outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) | iSETBREAK);
775: } else {
776: outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) & ~iSETBREAK);
777: }
778: }
779:
780: #if 0
781: /* do I need to do something on this ? */
782: if (bits & TM_LE) { /* line enable */
783: }
784: #endif
785: #if 0
786: /* Unsupported */
787: if (bits & TM_ST) { /* secondary transmit */
788: }
789: if (bits & TM_SR) { /* secondary receive */
790: }
791: #endif
792: if (bits & (TM_DTR|TM_RTS)) { /* data terminal ready, request to send */
793: how = iOUT2;
794: if (b & TM_DTR) how |= iDTR;
795: if (b & TM_RTS) how |= iRTS;
796: outb(MODEM_CTL(dev_addr), how);
797: }
798:
799: splx(s);
800:
801: /* the rest are inputs */
802: return commodem[unit];
803: }
804:
805: comstop(tp, flags)
806: register struct tty *tp;
807: int flags;
808: {
809: if ((tp->t_state & TS_BUSY) && (tp->t_state & TS_TTSTOP) == 0)
810: tp->t_state |= TS_FLUSH;
811: }
812:
813: /*
814: *
815: * Code to be called from debugger.
816: *
817: */
818: void compr_addr(addr)
819: {
820: /* The two line_stat prints may show different values, since
821: * touching some of the registers constitutes changing them.
822: */
823: printf("LINE_STAT(%x) %x\n",
824: LINE_STAT(addr), inb(LINE_STAT(addr)));
825:
826: printf("TXRX(%x) %x, INTR_ENAB(%x) %x, INTR_ID(%x) %x, LINE_CTL(%x) %x,\n\
827: MODEM_CTL(%x) %x, LINE_STAT(%x) %x, MODEM_STAT(%x) %x\n",
828: TXRX(addr), inb(TXRX(addr)),
829: INTR_ENAB(addr), inb(INTR_ENAB(addr)),
830: INTR_ID(addr), inb(INTR_ID(addr)),
831: LINE_CTL(addr), inb(LINE_CTL(addr)),
832: MODEM_CTL(addr), inb(MODEM_CTL(addr)),
833: LINE_STAT(addr), inb(LINE_STAT(addr)),
834: MODEM_STAT(addr),inb(MODEM_STAT(addr)));
835: }
836:
837: int compr(unit)
838: {
839: compr_addr(cominfo[unit]->address);
840: return(0);
841: }
842:
843: int
844: comgetc(int unit)
845: {
846: u_short addr = (u_short)(cominfo[unit]->address);
847: spl_t s = spltty();
848: int c;
849:
850: while((inb(LINE_STAT(addr)) & iDR) == 0) ;
851:
852: c = inb(TXRX(addr));
853: splx(s);
854: return c;
855: }
856:
857: #if RCLINE >= 0
858: /*
859: * Routines for the console
860: */
861: int
862: comcnputc(dev_t dev, int c)
863: {
864: u_short addr = (u_short)(cominfo[minor(dev)]->address);
865:
866: /* Wait for transmitter to empty */
867: while((inb(LINE_STAT(addr)) & iTHRE) == 0)
868: continue;
869:
870: /* send the char */
871: if (c == '\n')
872: comcnputc(dev, '\r');
873: outb(addr, c);
874: }
875:
876: int
877: comcngetc(dev_t dev, int wait)
878: {
879: u_short addr = (u_short)(cominfo[minor(dev)]->address);
880: int c;
881:
882: while((inb(LINE_STAT(addr)) & iDR) == 0)
883: if (! wait)
884: return 0;
885:
886: c = inb(TXRX(addr));
887: return c & 0x7f;
888: }
889: #endif /* RCLINE */
890:
891: #endif /* NCOM */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.