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