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