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