FreeBSD/Linux Kernel Cross Reference
sys/i386at/com.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 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 Software.Distribution@CS.CMU.EDU
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 * HISTORY
28 * $Log: com.c,v $
29 * Revision 2.21 93/11/17 16:42:59 dbg
30 * Restore earlier fix: can`t use ttymodem "flow control" since
31 * modem drops carrier but still talks to machine. Shut down FIFO
32 * on close.
33 * [93/06/15 dbg]
34 *
35 * Include kern/time_out.h for hz.
36 * [93/06/04 dbg]
37 *
38 * Revision 2.20 93/08/10 15:57:14 mrt
39 * Add computc(char ch, int unit) puts a character out on the
40 * give serial line. For mice, etc.
41 * Add comgetc(int unit) for same.
42 * Add comparm(int unit, int baud, int intr, int mode, int modem)
43 * [93/06/06 rvb]
44 *
45 * Revision 2.19 93/05/30 21:08:04 rvb
46 * Changed to use MI modem code, adding commctl.
47 * Does CTS/RTS flow control now.
48 * [93/05/29 09:52:46 af]
49 *
50 * Revision 2.18 93/05/15 19:31:09 mrt
51 * machparam.h -> machspl.h
52 *
53 * Revision 2.17 93/05/14 15:09:59 rvb
54 * Berman is right; check txbusy first then write for comrc_put
55 * [93/05/14 rvb]
56 *
57 * Revision 2.16 93/05/11 13:20:16 rvb
58 * Accept either keyboard in cn_dogetc
59 *
60 * Revision 2.15 93/05/10 21:18:46 rvb
61 * Removed 2.5 compat cruft. FIFOs work, but needs more work.
62 * Added watchdog to cure lost xmit interrupts [there is a
63 * bug somewhere else because I am losing them even on a
64 * chip that has no hardware bugs]. Do input buffering
65 * at all speeds higher than 300 bauds.
66 * [93/05/06 09:29:11 af]
67 *
68 * Revision 2.14 93/05/10 17:47:18 rvb
69 * I spend a little time working out rconsole with Steve Berman
70 * and don't want to lose the code. It's not quite done yet
71 * but it seems close.
72 * [93/05/10 rvb]
73 *
74 * Revision 2.13 93/03/09 10:54:24 danner
75 * Don Lindsay kindly provides us with:
76 * Bug fix in comopen() - cleans up chip status.
77 * Change in debug routine compr_addr() to print line state first,
78 * because touching other things changes the line state.
79 * Made comparam() static, since no outside uses.
80 * Added several (void)s and fixed some function return types.
81 * Changed a return; to return 0; in comparam().
82 * [93/03/05 af]
83 *
84 * Revision 2.12 93/01/24 13:15:06 danner
85 * [93/01/19 11:03:26 rvb]
86 *
87 * convert com_addr to vm_offset_t.
88 *
89 * Revision 2.11 93/01/14 17:30:00 danner
90 * Always disable fifo in comprobe().
91 * [92/12/12 dbg]
92 * Added changes suggested from Finland for FIFOs.
93 * They still do not work, but we'll get there eventually...
94 * [92/12/19 10:55:22 af]
95 *
96 * Disabled FIFOs until we have good code for them.
97 * Do input buffering at 9600 and over.
98 * [92/12/10 af]
99 *
100 * Proper spl typing.
101 * [92/11/30 af]
102 *
103 * Revision 2.10 92/05/22 13:08:34 jfriedl
104 * Moved disable of FIFO in comprobe().
105 * From Jordan K. Hubbard <jkh@meepmeep.pcs.com>
106 *
107 * Revision 2.9 92/02/19 15:08:12 elf
108 * Made comprobe more selective. Try to recognize chip.
109 * [92/01/20 kivinen]
110 *
111 * Revision 2.8 92/01/03 20:10:27 dbg
112 * Don't drop software CARR_ON if carrier drops - modem drops
113 * carrier but still can talk to machine.
114 * [91/10/30 dbg]
115 *
116 * Revision 2.7 91/10/07 17:25:14 af
117 * Add some improvements from 2.5 version.
118 * [91/09/04 22:05:25 rvb]
119 *
120 * Revision 2.6 91/08/24 11:57:21 af
121 * New MI autoconf.
122 * [91/08/02 02:50:03 af]
123 *
124 * Revision 2.5 91/05/14 16:21:14 mrt
125 * Correcting copyright
126 *
127 * Revision 2.4 91/02/14 14:42:06 mrt
128 * Merge of dbg's latest working com.c onto the old com.c
129 * with the new autoconf and other major changes.
130 * [91/01/28 15:26:13 rvb]
131 *
132 * Revision 2.3 91/02/05 17:16:33 mrt
133 * Changed to new Mach copyright
134 * [91/02/01 17:42:21 mrt]
135 *
136 * Revision 2.2 90/11/26 14:49:26 rvb
137 * jsb beat me to XMK34, sigh ...
138 * [90/11/26 rvb]
139 * Apparently first version is r2.2
140 * [90/11/25 10:44:41 rvb]
141 *
142 * Synched 2.5 & 3.0 at I386q (r2.3.1.6) & XMK35 (r2.2)
143 * [90/11/15 rvb]
144 *
145 * Revision 2.3.1.5 90/08/25 15:43:06 rvb
146 * I believe that nothing of the early Olivetti code remains.
147 * Copyright gone.
148 * [90/08/21 rvb]
149 *
150 * Use take_<>_irq() vs direct manipulations of ivect and friends.
151 * [90/08/20 rvb]
152 *
153 * Moved and rewrote much of the code to improve performance.
154 * Still suffers from overruns.
155 * [90/08/14 mg32]
156 *
157 * Revision 2.3.1.4 90/07/10 11:43:07 rvb
158 * Rewrote several functions to look more like vax-BSD dh.c.
159 * [90/06/25 mg32]
160 *
161 * New style probe/attach.
162 * Also com_struct has been radically reworked, ...
163 * [90/06/15 rvb]
164 *
165 * Revision 2.3.1.3 90/02/28 15:49:12 rvb
166 * Fix numerous typo's in Olivetti disclaimer.
167 * [90/02/28 rvb]
168 *
169 * Revision 2.3.1.2 90/01/08 13:32:00 rvb
170 * Add Olivetti copyright.
171 * [90/01/08 rvb]
172 *
173 * Revision 2.3.1.1 89/12/21 18:01:29 rvb
174 * Changes from Ali Ezzet.
175 *
176 * Revision 2.2.0.0 89/07/17 10:39:30 rvb
177 * New from Olivetti.
178 *
179 */
180
181 #include <com.h>
182 #if NCOM > 0
183
184 #include <mach/std_types.h>
185 #include <sys/types.h>
186 #include <kern/kern_io.h>
187 #include <kern/time_out.h>
188 #include <device/conf.h>
189 #include <device/errno.h>
190 #include <device/tty.h>
191 #include <device/io_req.h>
192
193 #include <i386/ipl.h>
194 #include <i386/pio.h>
195 #include <i386/machspl.h>
196 #include <chips/busses.h>
197 #include <i386at/comreg.h>
198
199 extern void ttrstrt();
200
201 /*
202 * Forward declarations
203 */
204 boolean_t comprobe(
205 vm_offset_t port,
206 struct bus_device *dev);
207 void comattach(
208 struct bus_device *dev);
209 void comintr(
210 int unit);
211 void comstart(
212 struct tty *tp);
213 void fix_modem_state(
214 int unit,
215 int modem_stat);
216 int commctl(
217 struct tty *tp,
218 int bits,
219 int how);
220 static void comparam(
221 register int unit);
222 void comtimer(void *);
223 void comstop(
224 register struct tty *tp,
225 int flags);
226 void commodem_intr(
227 int unit,
228 int stat);
229 io_return_t comgetstat(
230 int dev,
231 dev_flavor_t flavor,
232 dev_status_t data,
233 natural_t *count);
234 io_return_t comsetstat(
235 int dev,
236 dev_flavor_t flavor,
237 dev_status_t data,
238 natural_t count);
239
240 struct bus_device *cominfo[NCOM]; /* ??? */
241
242 static vm_offset_t com_std[NCOM] = { 0 };
243 static struct bus_device *com_info[NCOM];
244 struct bus_driver comdriver = {
245 comprobe, 0, comattach, 0, com_std, "com", com_info, 0, 0, 0};
246
247 struct tty com_tty[NCOM];
248 int commodem[NCOM];
249 int comcarrier[NCOM] = {0, 0,};
250 boolean_t comfifo[NCOM];
251 boolean_t comtimer_active;
252 int comtimer_state[NCOM];
253
254 #ifndef PORTSELECTOR
255 #define ISPEED B9600
256 #define IFLAGS (EVENP|ODDP|ECHO|CRMOD)
257 #else
258 #define ISPEED B4800
259 #define IFLAGS (EVENP|ODDP)
260 #endif
261
262 u_short divisorreg[] = {
263 0, 2304, 1536, 1047, /* 0, 50, 75, 110*/
264 857, 768, 576, 384, 192, /* 134.5, 150, 200, 300, 600*/
265 96, 64, 48, /* 1200, 1800, 2000, 2400 */
266 24, 12, /* 3600, 4800, 7200, 9600 */
267 6, 3, 2}; /* 19200, 38400, 56000 */
268
269 /*
270 *
271 * Probe's are called during kernel boot: return 1 to mean that
272 * the relevant device is present today.
273 *
274 */
275 boolean_t
276 comprobe(
277 vm_offset_t port,
278 struct bus_device *dev)
279 {
280 u_short addr = dev->address;
281 int unit = dev->unit;
282 int oldctl, oldmsb;
283 char *type = "8250";
284 int i;
285
286 if ((unit < 0) || (unit > NCOM)) {
287 printf("com %d out of range\n", unit);
288 return(0);
289 }
290 oldctl = inb(LINE_CTL(addr)); /* Save old value of LINE_CTL */
291 oldmsb = inb(BAUD_MSB(addr)); /* Save old value of BAUD_MSB */
292 outb(LINE_CTL(addr), 0); /* Select INTR_ENAB */
293 outb(BAUD_MSB(addr), 0);
294 if (inb(BAUD_MSB(addr)) != 0)
295 {
296 outb(LINE_CTL(addr), oldctl);
297 outb(BAUD_MSB(addr), oldmsb);
298 return 0;
299 }
300 outb(LINE_CTL(addr), iDLAB); /* Select BAUD_MSB */
301 outb(BAUD_MSB(addr), 255);
302 if (inb(BAUD_MSB(addr)) != 255)
303 {
304 outb(LINE_CTL(addr), oldctl);
305 outb(BAUD_MSB(addr), oldmsb);
306 return 0;
307 }
308 outb(LINE_CTL(addr), 0); /* Select INTR_ENAB */
309 if (inb(BAUD_MSB(addr)) != 0) /* Check that it has kept it's value*/
310 {
311 outb(LINE_CTL(addr), oldctl);
312 outb(BAUD_MSB(addr), oldmsb);
313 return 0;
314 }
315
316 /* Com port found, now check what chip it has */
317
318 for(i = 0; i < 256; i++) /* Is there Scratch register */
319 {
320 outb(SCR(addr), i);
321 if (inb(SCR(addr)) != i)
322 break;
323 }
324 if (i == 256)
325 { /* Yes == 450 or 460 */
326 outb(SCR(addr), 0);
327 type = "82450 or 16450";
328 outb(FIFO_CTL(addr), iFIFOENA | iFIFO14CH); /* Enable fifo */
329 if ((inb(FIFO_CTL(addr)) & iFIFO14CH) != 0)
330 { /* Was it successfull */
331 /* if both bits are not set then broken xx550 */
332 if ((inb(FIFO_CTL(addr)) & iFIFO14CH) == iFIFO14CH)
333 {
334 type = "82550 or 16550";
335 comfifo[unit] = TRUE;
336 }
337 else
338 {
339 type = "82550 or 16550 with non-working FIFO";
340 }
341 outb(INTR_ID(addr), 0x00); /* Disable fifos */
342 }
343 }
344 printf("com%d: %s chip.\n", unit, type);
345 return 1;
346 }
347
348 /*
349 *
350 * Device Attach's are called during kernel boot, but only if the matching
351 * device Probe returned a 1.
352 * No return value, despite the "int" signature.
353 *
354 */
355 void comattach(
356 struct bus_device *dev)
357 {
358 u_char unit = dev->unit;
359 u_short addr = dev->address;
360
361 take_dev_irq(dev);
362 printf(", port = %x, spl = %d, pic = %d. (DOS COM%d)",
363 dev->address, dev->sysdep, dev->sysdep1, unit+1);
364
365 cominfo[unit] = dev;
366 /* comcarrier[unit] = addr->flags;*/
367 commodem[unit] = 0;
368
369 outb(INTR_ENAB(addr), 0);
370 outb(MODEM_CTL(addr), 0);
371 while (!(inb(INTR_ID(addr))&1)) {
372 (void) inb(LINE_STAT (addr)); /* reset overrun error etc */
373 (void) inb(TXRX (addr)); /* reset data-ready */
374 (void) inb(MODEM_STAT(addr)); /* reset modem status reg */
375 }
376 }
377
378 io_return_t comopen(
379 int dev,
380 int flag,
381 io_req_t ior)
382 {
383 int unit = minor(dev);
384 u_short addr;
385 struct bus_device *isai;
386 struct tty *tp;
387 spl_t s;
388 io_return_t result;
389
390 if (unit >= NCOM || (isai = cominfo[unit]) == 0 || isai->alive == 0)
391 return(ENXIO);
392 tp = &com_tty[unit];
393
394 if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0) {
395 ttychars(tp);
396 tp->t_addr = (char *)isai->address;
397 tp->t_dev = dev;
398 tp->t_oproc = comstart;
399 tp->t_stop = comstop;
400 tp->t_mctl = commctl;
401 tp->t_getstat = comgetstat;
402 tp->t_setstat = comsetstat;
403 #ifndef PORTSELECTOR
404 if (tp->t_ispeed == 0) {
405 #else
406 tp->t_state |= TS_HUPCLS;
407 #endif /* PORTSELECTOR */
408 tp->t_ispeed = ISPEED;
409 tp->t_ospeed = ISPEED;
410 tp->t_flags = IFLAGS;
411 tp->t_state &= ~TS_BUSY;
412 #ifndef PORTSELECTOR
413 }
414 #endif /* PORTSELECTOR */
415 }
416 /*rvb tp->t_state |= TS_WOPEN; */
417 if ((tp->t_state & TS_ISOPEN) == 0)
418 comparam(unit);
419 addr = (int)tp->t_addr;
420
421 s = spltty();
422 if (!comcarrier[unit]) /* not originating */
423 tp->t_state |= TS_CARR_ON;
424 else {
425 int modem_stat = inb(MODEM_STAT(addr));
426 if (modem_stat & iRLSD)
427 tp->t_state |= TS_CARR_ON;
428 else
429 tp->t_state &= ~TS_CARR_ON;
430 fix_modem_state(unit, modem_stat);
431 }
432 splx(s);
433
434 result = char_open(dev, tp, flag, ior);
435
436 if (!comtimer_active) {
437 comtimer_active = TRUE;
438 comtimer(0);
439 }
440
441 s = spltty();
442 while(!(inb(INTR_ID(addr))&1)) { /* while pending interrupts */
443 (void) inb(LINE_STAT (addr)); /* reset overrun error */
444 (void) inb(TXRX (addr)); /* reset data-ready */
445 (void) inb(MODEM_STAT(addr)); /* reset modem status */
446 }
447 splx(s);
448 return result;
449 }
450
451 io_return_t comclose(
452 int dev,
453 int flag)
454 {
455 struct tty *tp = &com_tty[minor(dev)];
456 u_short addr = (int)tp->t_addr;
457
458 ttyclose(tp);
459 if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) {
460 outb(INTR_ENAB(addr), 0);
461 outb(MODEM_CTL(addr), 0);
462 tp->t_state &= ~TS_BUSY;
463 commodem[minor(dev)] = 0;
464 if (comfifo[minor(dev)])
465 outb(INTR_ID(addr), 0x00); /* Disable fifos */
466 }
467 return 0;
468 }
469
470 io_return_t comread(
471 int dev,
472 io_req_t ior)
473 {
474 return char_read(&com_tty[minor(dev)], ior);
475 }
476
477 io_return_t comwrite(
478 int dev,
479 io_req_t ior)
480 {
481 return char_write(&com_tty[minor(dev)], ior);
482 }
483
484 io_return_t comportdeath(
485 dev_t dev,
486 mach_port_t port)
487 {
488 return tty_portdeath(&com_tty[minor(dev)], port);
489 }
490
491 io_return_t
492 comgetstat(
493 int dev,
494 dev_flavor_t flavor,
495 dev_status_t data, /* pointer to OUT array */
496 natural_t *count) /* out */
497 {
498 io_return_t result = D_SUCCESS;
499 int unit = minor(dev);
500
501 switch (flavor) {
502 case TTY_MODEM:
503 fix_modem_state(unit, inb(MODEM_STAT(cominfo[unit]->address)));
504 *data = commodem[unit];
505 *count = 1;
506 break;
507 default:
508 result = tty_get_status(&com_tty[unit], flavor, data, count);
509 break;
510 }
511 return result;
512 }
513
514 io_return_t
515 comsetstat(
516 int dev,
517 dev_flavor_t flavor,
518 dev_status_t data,
519 natural_t count)
520 {
521 io_return_t result = D_SUCCESS;
522 int unit = minor(dev);
523 struct tty *tp = &com_tty[unit];
524
525 switch (flavor) {
526 case TTY_SET_BREAK:
527 commctl(tp, TM_BRK, DMBIS);
528 break;
529 case TTY_CLEAR_BREAK:
530 commctl(tp, TM_BRK, DMBIC);
531 break;
532 case TTY_MODEM:
533 commctl(tp, *data, DMSET);
534 break;
535 default:
536 result = tty_set_status(&com_tty[unit], flavor, data, count);
537 if (result == D_SUCCESS && flavor == TTY_STATUS)
538 comparam(unit);
539 return result;
540 }
541 return D_SUCCESS;
542 }
543
544 void comintr(
545 int unit)
546 {
547 register struct tty *tp = &com_tty[unit];
548 u_short addr = cominfo[unit]->address;
549 static char comoverrun = 0;
550 char c, line, intr_id;
551 int line_stat;
552
553 while (! ((intr_id=(inb(INTR_ID(addr))&MASKi)) & 1))
554 switch (intr_id) {
555 case MODi:
556 /* modem change */
557 commodem_intr(unit, inb(MODEM_STAT(addr)));
558 break;
559
560 case TRAi:
561 comtimer_state[unit] = 0;
562 tp->t_state &= ~(TS_BUSY|TS_FLUSH);
563 tt_write_wakeup(tp);
564 comstart(tp);
565 break;
566 case RECi:
567 case CTIi: /* Character timeout indication */
568 if (tp->t_state&TS_ISOPEN) {
569 while ((line = inb(LINE_STAT(addr))) & iDR) {
570 c = inb(TXRX(addr));
571 ttyinput(c, tp);
572 }
573 } else
574 tt_open_wakeup(tp);
575 break;
576 case LINi:
577 line_stat = inb(LINE_STAT(addr));
578
579 if ((line_stat & iPE) &&
580 ((tp->t_flags&(EVENP|ODDP)) == EVENP ||
581 (tp->t_flags&(EVENP|ODDP)) == ODDP)) {
582 /* parity error */;
583 } else if (line&iOR && !comoverrun) {
584 printf("com%d: overrun\n", unit);
585 comoverrun = 1;
586 } else if (line_stat & (iFE | iBRKINTR)) {
587 /* framing error or break */
588 ttyinput(tp->t_breakc, tp);
589 }
590 break;
591 }
592 }
593
594 static void
595 comparam(
596 register int unit)
597 {
598 struct tty *tp = &com_tty[unit];
599 u_short addr = (int)tp->t_addr;
600 spl_t s = spltty();
601 int mode;
602
603 if (tp->t_ispeed == B0) {
604 tp->t_state |= TS_HUPCLS;
605 outb(MODEM_CTL(addr), iOUT2);
606 commodem[unit] = 0;
607 splx(s);
608 return;
609 }
610
611 /* Do input buffering */
612 if (tp->t_ispeed >= B300)
613 tp->t_state |= TS_MIN;
614
615 outb(LINE_CTL(addr), iDLAB);
616 outb(BAUD_LSB(addr), divisorreg[tp->t_ispeed] & 0xff);
617 outb(BAUD_MSB(addr), divisorreg[tp->t_ispeed] >> 8);
618
619 if (tp->t_flags & (RAW|LITOUT|PASS8))
620 mode = i8BITS;
621 else
622 mode = i7BITS | iPEN;
623 if (tp->t_flags & EVENP)
624 mode |= iEPS;
625 if (tp->t_ispeed == B110)
626 /*
627 * 110 baud uses two stop bits -
628 * all other speeds use one
629 */
630 mode |= iSTB;
631
632 outb(LINE_CTL(addr), mode);
633
634 outb(INTR_ENAB(addr), iTX_ENAB|iRX_ENAB|iMODEM_ENAB|iERROR_ENAB);
635 if (comfifo[unit])
636 outb(FIFO_CTL(addr), iFIFOENA|iFIFO14CH);
637 outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2);
638 commodem[unit] |= (TM_DTR|TM_RTS);
639 splx(s);
640 }
641
642 void computc(char ch, int unit)
643 {
644 u_short addr = (u_short)(cominfo[unit]->address);
645
646 /* send the char */
647 outb(addr, ch);
648
649 /* wait for transmitter to empty */
650 while((inb(LINE_STAT(addr)) & iTHRE) == 0);
651 }
652
653 int comgetc(int unit)
654 {
655 u_short addr = (u_short)(cominfo[unit]->address);
656 spl_t s = spltty();
657 natural_t c;
658
659 while((inb(LINE_STAT(addr)) & iDR) == 0) ;
660
661 c = inb(TXRX(addr));
662 splx(s);
663 return c;
664 }
665
666 void comparm(int unit, int baud, int intr, int mode, int modem)
667 {
668 u_short addr = (u_short)(cominfo[unit]->address);
669 spl_t s = spltty();
670
671 if (unit != 0 && unit != 1) {
672 printf("comparm(unit, baud, mode, intr, modem)\n");
673 splx(s);
674 return;
675 }
676 outb(LINE_CTL(addr), iDLAB);
677 outb(BAUD_LSB(addr), divisorreg[baud] & 0xff);
678 outb(BAUD_MSB(addr), divisorreg[baud] >> 8);
679 outb(LINE_CTL(addr), mode);
680 outb(INTR_ENAB(addr), intr);
681 outb(MODEM_CTL(addr), modem);
682 splx(s);
683 }
684
685 int comst_1, comst_2, comst_3, comst_4, comst_5 = 14;
686
687 void comstart(
688 struct tty *tp)
689 {
690 char nch;
691 #if 0
692 int i;
693 #endif
694
695 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) {
696 comst_1++;
697 return;
698 }
699 if ((!queue_empty(&tp->t_delayed_write)) &&
700 (tp->t_outq.c_cc <= TTLOWAT(tp))) {
701 comst_2++;
702 tt_write_wakeup(tp);
703 }
704 if (!tp->t_outq.c_cc) {
705 comst_3++;
706 return;
707 }
708
709 #if 0
710 i = (comfifo[minor(tp->t_dev)]) ? /*14*/comst_5 : 1;
711
712 tp->t_state |= TS_BUSY;
713 while (i-- > 0) {
714 nch = getc(&tp->t_outq);
715 if (nch == -1) break;
716 if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) {
717 timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
718 tp->t_state |= TS_TIMEOUT;
719 comst_4++;
720 return;
721 }
722 outb(TXRX((int)tp->t_addr), nch);
723 }
724 #else
725 nch = getc(&tp->t_outq);
726 if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) {
727 timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
728 tp->t_state |= TS_TIMEOUT;
729 comst_4++;
730 return;
731 }
732 outb(TXRX((int)tp->t_addr), nch);
733 tp->t_state |= TS_BUSY;
734 #endif
735 return;
736 }
737
738 /* Check for stuck xmitters */
739 int comtimer_interval = 5;
740
741 void comtimer(void *param)
742 {
743 spl_t s = spltty();
744 struct tty *tp = com_tty;
745 int i, nch;
746
747 for (i = 0; i < NCOM; i++, tp++) {
748 if ((tp->t_state & TS_ISOPEN) == 0)
749 continue;
750 if (!tp->t_outq.c_cc)
751 continue;
752 if (++comtimer_state[i] < 2)
753 continue;
754 /* Its stuck */
755 printf("Tty %#x was stuck\n", (vm_offset_t)tp);
756 nch = getc(&tp->t_outq);
757 outb(TXRX((int)tp->t_addr), nch);
758 }
759
760 splx(s);
761 timeout(comtimer, 0, comtimer_interval*hz);
762 }
763
764 /*
765 * Set receive modem state from modem status register.
766 */
767 void fix_modem_state(
768 int unit,
769 int modem_stat)
770 {
771 int stat = 0;
772
773 if (modem_stat & iCTS)
774 stat |= TM_CTS; /* clear to send */
775 if (modem_stat & iDSR)
776 stat |= TM_DSR; /* data set ready */
777 if (modem_stat & iRI)
778 stat |= TM_RNG; /* ring indicator */
779 if (modem_stat & iRLSD)
780 stat |= TM_CAR; /* carrier? */
781
782 commodem[unit] = (commodem[unit] & ~(TM_CTS|TM_DSR|TM_RNG|TM_CAR))
783 | stat;
784 }
785
786 /*
787 * Modem change (input signals)
788 */
789 void commodem_intr(
790 int unit,
791 int stat)
792 {
793 int changed;
794
795 changed = commodem[unit];
796 fix_modem_state(unit, stat);
797 stat = commodem[unit];
798
799 /* Assumption: if the other party can handle
800 modem signals then it should handle all
801 the necessary ones. Else fix the cable. */
802
803 changed ^= stat; /* what changed ? */
804
805 if (changed & TM_CTS)
806 tty_cts( &com_tty[unit], stat & TM_CTS );
807
808 #if 0
809 if (changed & TM_CAR)
810 ttymodem( &com_tty[unit], stat & TM_CAR );
811 #endif
812
813 }
814
815 /*
816 * Set/get modem bits
817 */
818 int commctl(
819 register struct tty *tp,
820 int bits,
821 int how)
822 {
823 spl_t s;
824 int unit;
825 vm_offset_t dev_addr;
826 register int b;
827
828 unit = minor(tp->t_dev);
829
830 if (bits == TM_HUP) { /* close line (internal) */
831 bits = TM_DTR | TM_RTS;
832 how = DMBIC;
833 }
834
835 if (how == DMGET) return commodem[unit];
836
837 dev_addr = cominfo[unit]->address;
838
839 s = spltty();
840
841 switch (how) {
842 case DMSET:
843 b = bits; break;
844 case DMBIS:
845 b = commodem[unit] | bits; break;
846 case DMBIC:
847 b = commodem[unit] & ~bits; break;
848 }
849 commodem[unit] = b;
850
851 if (bits & TM_BRK) {
852 if (b & TM_BRK) {
853 outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) | iSETBREAK);
854 } else {
855 outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) & ~iSETBREAK);
856 }
857 }
858
859 #if 0
860 /* do I need to do something on this ? */
861 if (bits & TM_LE) { /* line enable */
862 }
863 #endif
864 #if 0
865 /* Unsupported */
866 if (bits & TM_ST) { /* secondary transmit */
867 }
868 if (bits & TM_SR) { /* secondary receive */
869 }
870 #endif
871 if (bits & (TM_DTR|TM_RTS)) { /* data terminal ready, request to send */
872 how = iOUT2;
873 if (b & TM_DTR) how |= iDTR;
874 if (b & TM_RTS) how |= iRTS;
875 outb(MODEM_CTL(dev_addr), how);
876 }
877
878 splx(s);
879
880 /* the rest are inputs */
881 return commodem[unit];
882 }
883
884 void comstop(
885 register struct tty *tp,
886 int flags)
887 {
888 if ((tp->t_state & TS_BUSY) && (tp->t_state & TS_TTSTOP) == 0)
889 tp->t_state |= TS_FLUSH;
890 }
891
892 /*
893 *
894 * Code to be called from debugger.
895 *
896 */
897 void compr_addr(int addr)
898 {
899 /* The two line_stat prints may show different values, since
900 * touching some of the registers constitutes changing them.
901 */
902 printf("LINE_STAT(%x) %x\n",
903 LINE_STAT(addr), inb(LINE_STAT(addr)));
904
905 printf("TXRX(%x) %x, INTR_ENAB(%x) %x, INTR_ID(%x) %x, LINE_CTL(%x) %x,\n\
906 MODEM_CTL(%x) %x, LINE_STAT(%x) %x, MODEM_STAT(%x) %x\n",
907 TXRX(addr), inb(TXRX(addr)),
908 INTR_ENAB(addr), inb(INTR_ENAB(addr)),
909 INTR_ID(addr), inb(INTR_ID(addr)),
910 LINE_CTL(addr), inb(LINE_CTL(addr)),
911 MODEM_CTL(addr), inb(MODEM_CTL(addr)),
912 LINE_STAT(addr), inb(LINE_STAT(addr)),
913 MODEM_STAT(addr),inb(MODEM_STAT(addr)));
914 }
915
916 int compr(int unit)
917 {
918 compr_addr(cominfo[unit]->address);
919 return(0);
920 }
921
922 int rcline = -1;
923 int rcbaud = B9600;
924 void comrc_put(
925 int ch)
926 {
927 static int opened = 0;
928 u_short addr;
929
930 if (cominfo[rcline] == 0) return;
931
932 addr = (u_short)(cominfo[rcline]->address);
933
934 if (!opened) { /* whap down chip config for rconsole */
935 int mode = i7BITS | iPEN;
936
937 opened = 1;
938 outb(LINE_CTL(addr), iDLAB);
939 outb(BAUD_LSB(addr), divisorreg[rcbaud] & 0xff);
940 outb(BAUD_MSB(addr), divisorreg[rcbaud] >>8);
941 outb(LINE_CTL(addr), mode);
942 outb(INTR_ENAB(addr), 0);
943 outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2);
944 }
945
946 /* wait for transmitter to empty */
947 while((inb(LINE_STAT(addr)) & iTHRE) == 0);
948 /* send the char */
949 outb(addr, ch);
950 }
951
952 int comrc_may(
953 boolean_t wait)
954 {
955 unsigned char c;
956 u_short addr;
957
958 if (cominfo[rcline] == 0) return -1;
959
960 addr = (u_short)(cominfo[rcline]->address);
961
962 if ((inb(LINE_STAT(addr)) & iDR) == 0) {
963 return -1;
964 }
965
966 c = inb(TXRX(addr));
967 return (c & 0x7f);
968 }
969
970 int
971 comrc_get(
972 boolean_t wait)
973 {
974 unsigned char c;
975 u_short addr;
976
977
978 addr = (u_short)(cominfo[rcline]->address);
979
980 while((inb(LINE_STAT(addr)) & iDR) == 0) {
981 if (!wait)
982 return -1;
983 }
984
985 c = inb(TXRX(addr));
986 return (c & 0x7f);
987 }
988
989 #endif /* NCOM */
Cache object: cbea28b23718711984658440ebcd6ff4
|