FreeBSD/Linux Kernel Cross Reference
sys/ipsc/usm.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 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 * Copyright 1988, 1989, 1990, 1991 by Intel Corporation,
28 * Santa Clara, California.
29 *
30 * All Rights Reserved
31 *
32 * Permission to use, copy, modify, and distribute this software and its
33 * documentation for any purpose and without fee is hereby granted,
34 * provided that the above copyright notice appears in all copies and that
35 * both the copyright notice and this permission notice appear in
36 * supporting documentation, and that the name of Intel not be used in
37 * advertising or publicity pertaining to distribution of the software
38 * without specific, written prior permission.
39 *
40 * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
41 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
42 * SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
43 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44 * PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS
45 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
46 * THIS SOFTWARE.
47 */
48 /*
49 * Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
50 * Cupertino, California.
51 *
52 * All Rights Reserved
53 *
54 * Permission to use, copy, modify, and distribute this software and
55 * its documentation for any purpose and without fee is hereby
56 * granted, provided that the above copyright notice appears in all
57 * copies and that both the copyright notice and this permission notice
58 * appear in supporting documentation, and that the name of Olivetti
59 * not be used in advertising or publicity pertaining to distribution
60 * of the software without specific, written prior permission.
61 *
62 * OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
63 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
64 * IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
65 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
66 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
67 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
68 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
69 */
70 /*
71 * HISTORY
72 * $Log: usm.c,v $
73 * Revision 2.7 91/12/10 16:32:35 jsb
74 * Fixes from Intel
75 * [91/12/10 15:33:41 jsb]
76 *
77 * Revision 2.3 91/09/04 11:28:22 jsb
78 * This is Intel's most recent usm.c, with my JUSTHACKIT code added
79 * and enabled since things still act funny without it.
80 * [91/09/04 08:39:09 jsb]
81 *
82 * Revision 2.2 91/06/18 20:52:42 jsb
83 * First checkin. Just a hack until ipsc/usm.c gets merged again.
84 * [91/06/18 19:04:14 jsb]
85 *
86 * Revision 2.3 90/12/22 00:00:00 prp
87 * Change to use slot number
88 *
89 * Revision 2.2 90/12/04 14:50:53 jsb
90 * Eliminated compiler warning.
91 * [90/12/04 12:18:23 jsb]
92 *
93 * Merged (and mostly replaced) with i386ipsc version.
94 * Unmerged parts are conditionalized with JUSTHACKIT;
95 * the i386ipsc seems to need this code.
96 * [90/12/04 10:46:15 jsb]
97 *
98 * First checkin.
99 * [90/12/03 21:57:51 jsb]
100 *
101 */
102
103 #include <mach_kdb.h>
104 #include <sys/types.h>
105 #include <device/conf.h>
106 #include <device/tty.h>
107 #include <device/io_req.h>
108 #include <device/errno.h>
109 #include <device/cirbuf.h>
110
111 #define JUSTHACKIT 0
112
113 #if i860
114 #include <i860ipsc/nodehw.h>
115 #endif
116 #include <ipsc/usm.h>
117
118 /* These magic values from NX's kt.h */
119 #define KT_RDY 0x81
120 #define KT_HOLD 0x82
121 #define KT_SELECT 0x83
122 #define KT_KDB 0x84
123
124 /* Multiplex states */
125 #define NOT_WAITING 0
126 #define WAITING_FOR_KT_RDY 1
127 #define WAITING_FOR_SELECT 2
128
129 extern void timeout(), ttrstrt();
130 int usmstop(), usmgetstat(), usmsetstat();
131
132
133 /*
134 * Switches for polling vs. interrupt.
135 */
136 static int polling = 0;
137 static int interrupts_on = 0;
138
139 extern void splx();
140 extern int spltty();
141 extern int soft_pic_enable(), soft_pic_disable();
142
143 struct tty usm_tty;
144 static int initialized = 0;
145
146 /* variables below allow USM serial line to be shared by more than one node */
147 static boolean_t selected = FALSE; /* is serial line selected for this node */
148 static int state = NOT_WAITING; /* are we waiting for special characters */
149
150 /* variables for polled IO */
151 #define UNSBUF 2048
152 static char unselbuf[UNSBUF]; /* buffer to hold output when unselected */
153 static char stray[64]; /* characters rcv'd while waiting for KT_RDY */
154 static struct cirbuf conbuf; /* circular buffer for output */
155 static char column = 0; /* for tab expansion */
156 static short stray_count = 0;
157
158 extern ipsc_slot;
159
160 /* forward declarations */
161 static int enable_interrupts();
162 static int disable_interrupts();
163 int usmstart();
164 int usmstop();
165
166 #if i860
167 int led_console = 0;
168 int led_usm = 0;
169 #endif i860
170
171 /*
172 * Initialize the console.
173 */
174 cninit()
175 {
176 if (!initialized) {
177 /*
178 * I'd like to use cb_alloc(&conbuf, UNSBUF),
179 * but kalloc() hasn't been initialized yet.
180 */
181 conbuf.c_start = unselbuf;
182 conbuf.c_end = unselbuf + UNSBUF;
183 conbuf.c_cf = unselbuf;
184 conbuf.c_cl = unselbuf;
185 conbuf.c_cc = 0;
186
187 uart_hardreset();
188 disable_interrupts();
189
190 while (!inb(iUSM_GIR) & 1) {
191 (void) inb(iUSM_LSR);
192 (void) inb(iUSM_RXD);
193 (void) inb(iUSM_MSR);
194 }
195
196 column = 0;
197 polling = 1;
198 initialized++;
199 }
200 }
201
202
203 usmopen(dev, flag, ior)
204 dev_t dev;
205 int flag;
206 io_req_t ior;
207 {
208 int s;
209 struct tty * tp;
210 int unit;
211 io_return_t ret_val;
212
213 unit = minor(dev);
214 if (unit != 0) {
215 /* we only support a single usm device */
216 return(ENXIO);
217 }
218
219 tp = &usm_tty;
220 s = spltty();
221
222 if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0) {
223 ttychars(tp);
224 tp->t_addr = (caddr_t) tp;
225 tp->t_dev = dev;
226 tp->t_oproc = usmstart;
227 tp->t_stop = usmstop;
228 tp->t_getstat = usmgetstat;
229 tp->t_setstat = usmsetstat;
230 tp->t_ispeed = B9600;
231 tp->t_ospeed = B9600;
232 tp->t_flags = ODDP|EVENP|ECHO|CRMOD;
233 tp->t_state &= ~TS_BUSY;
234 #if i860
235 uart_softreset();
236 uart_clkstart();
237 #endif
238 polling = 0;
239 enable_interrupts();
240 }
241 if ((tp->t_state & TS_ISOPEN) == 0)
242 usmparam(unit);
243 tp->t_state |= TS_CARR_ON;
244
245 splx(s);
246
247 ret_val = char_open(dev, tp, flag, ior);
248 return ret_val;
249 }
250
251
252 int usmclose(dev, flag)
253 int dev;
254 int flag;
255 {
256 struct tty *tp;
257 int s;
258
259 tp = &usm_tty;
260
261 s = spltty();
262 ttyclose(tp);
263 disable_interrupts();
264 polling = 1;
265 splx(s);
266
267 return 0;
268
269 }
270
271
272 int usmread(dev, ior)
273 int dev;
274 io_req_t ior;
275 {
276 int r;
277
278 r = char_read(&usm_tty, ior);
279 return r;
280 }
281
282
283 int usmwrite(dev, ior)
284 int dev;
285 io_req_t ior;
286 {
287 int r;
288
289 r = char_write(&usm_tty, ior);
290 return r;
291 }
292
293
294 usmportdeath(dev, port)
295 dev_t dev;
296 mach_port_t port;
297 {
298 return (tty_portdeath(&usm_tty, port));
299 }
300
301
302 /*ARGSUSED*/
303 io_return_t usmgetstat(dev, flavor, data, count)
304 dev_t dev;
305 int flavor;
306 int *data; /* pointer to OUT array */
307 unsigned int *count; /* OUT */
308 {
309 return (tty_get_status(&usm_tty, flavor, data, count));
310 }
311
312
313 /*ARGSUSED*/
314 io_return_t usmsetstat(dev, flavor, data, count)
315 dev_t dev;
316 int flavor;
317 int *data;
318 unsigned int count;
319 {
320 io_return_t result = D_SUCCESS;
321 int unit = minor(dev);
322
323 result = tty_set_status(&usm_tty, flavor, data, count);
324 if (result == D_SUCCESS && flavor == TTY_STATUS)
325 usmparam(unit);
326 return (result);
327 }
328
329
330 usmparam(unit)
331 register int unit;
332 {
333 /* we don't need no stinking params... */
334 return;
335 }
336
337
338 /*
339 * we're only called if there was an RX interrupt from the usm...
340 * ...but that can mean more than one thing...
341 */
342 usmintr(unit)
343 int unit;
344 {
345 register struct tty *tp;
346 register int c;
347 int s;
348 #if i860
349 extern int intr_debug;
350 #endif i860
351
352 if (polling) {
353 return;
354 }
355
356 #if i860
357 if (intr_debug) led_char('u');
358 #endif i860
359
360 tp = &usm_tty;
361 if (!(tp->t_state & TS_ISOPEN)) {
362 tt_open_wakeup(tp);
363 return;
364 }
365
366 #if i860
367 if (intr_debug) led_char('R');
368 #endif i860
369
370 c = inb(iUSM_RXD) & 0xff;
371
372 if (state == WAITING_FOR_SELECT) {
373 state = NOT_WAITING;
374 if ((c & 0x7F) == ipsc_slot || (c & 0x80)) {
375 selected = TRUE;
376 } else {
377 selected = FALSE;
378 }
379 } else if (c == KT_SELECT) {
380 state = WAITING_FOR_SELECT;
381 } else if (! selected) {
382 ;
383 } else if (c == KT_RDY) {
384 if (state == WAITING_FOR_KT_RDY) {
385 /*
386 * getting a KT_RDY is kind of like getting
387 * a TX interrupt from a *normal* uart.
388 */
389 state = NOT_WAITING;
390 tp->t_state &= ~TS_BUSY;
391 } else {
392 outb(iUSM_TXD, KT_HOLD);
393 }
394 } else if (c == KT_KDB) {
395 kdb_kintr();
396 } else {
397 if (tp->t_state&TS_ISOPEN) {
398 ttyinput(c, tp);
399 } else {
400 tt_open_wakeup(tp);
401 }
402 }
403
404 if (selected) {
405 usmstart(tp);
406 }
407
408 #if i860
409 if (intr_debug) led_char(';');
410 #endif i860
411 }
412
413
414 #if JUSTHACKIT
415 int kt_rdy_deficit = 0;
416 #define MAX_KT_RDY_DEFICIT 16
417
418 justhackit(c, tp)
419 u_char c;
420 struct tty *tp;
421 {
422 while ((inb(iUSM_LSR) & iTHRE) == 0) {
423 continue;
424 }
425 outb(iUSM_TXD, c);
426 if (++kt_rdy_deficit < MAX_KT_RDY_DEFICIT) {
427 return;
428 }
429 while (kt_rdy_deficit > 0) {
430 while((inb(iUSM_LSR) & iDR) == 0) {
431 continue;
432 }
433 c = inb(iUSM_RXD) & 0xff;
434 if (c == KT_RDY) {
435 kt_rdy_deficit--;
436 break;
437 }
438 if (tp) {
439 (*linesw[tp->t_line].l_rint)(c, tp);
440 } else if (stray_count < sizeof(stray)) {
441 stray[stray_count++] = c;
442 }
443 }
444 }
445 #endif
446
447
448 usmstart(tp)
449 struct tty *tp;
450 {
451 char nch;
452
453 if (polling) {
454 return;
455 }
456 if (!selected) {
457 return;
458 }
459 if (state != NOT_WAITING) {
460 return;
461 }
462 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) {
463 return;
464 }
465 #if JUSTHACKIT
466 while (tp->t_outq.c_cc > 0 && (nch=getc(&tp->t_outq)) != -1) {
467 justhackit(nch, tp);
468 }
469 tp->t_state &= ~TS_BUSY;
470 tt_write_wakeup(tp);
471 #else JUSTHACKIT
472 if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
473 tt_write_wakeup(tp);
474 }
475 if (!tp->t_outq.c_cc) {
476 return;
477 }
478 nch = getc(&tp->t_outq);
479 if ((tp->t_flags & LITOUT) == 0 && (nch & 0200)) {
480 timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6);
481 tp->t_state |= TS_TIMEOUT;
482 return;
483 }
484 #if i860
485 if (led_usm) led_char(nch);
486 #endif
487 outb(iUSM_TXD, nch);
488 state = WAITING_FOR_KT_RDY;
489 tp->t_state |= TS_BUSY;
490 return;
491 #endif JUSTHACKIT
492 }
493
494
495 usmstop(tp, flags)
496 register struct tty *tp;
497 int flags;
498 {
499 if ((tp->t_state & TS_BUSY) && (tp->t_state & TS_TTSTOP) == 0)
500 tp->t_state |= TS_FLUSH;
501 }
502
503
504 dumpunsel()
505 {
506 int c;
507
508 while ((c = getc(&conbuf)) != -1) {
509 cnputc(c);
510 }
511 }
512
513
514 /*
515 * This procedure provides the console out routine for the
516 * kernel's putchar (printf) routine. When output for this
517 * node is selected, it polls the UART until the TX Ready bit
518 * is set and then outputs the character. If IO is not selected
519 * then the character is saved in a buffer so that it can be
520 * written later.
521 */
522 cnputc(c)
523 char c;
524 {
525 unsigned char x;
526 int s, i, was;
527
528 if (!initialized) {
529 cninit();
530 }
531
532 switch (c) {
533 case '\n':
534 cnputc('\r');
535 case '\r':
536 column = 0;
537 break;
538 case '\t':
539 do {
540 cnputc(' ');
541 } while (column & 07);
542 return(c);
543 case '\b':
544 if (column)
545 column--;
546 break;
547 default:
548 column++;
549 break;
550
551 }
552
553 #if i860
554 if (led_console) led_char(c);
555 #endif i860
556
557 if (!selected) {
558 if (putc(c, &conbuf)) {
559 int drop = getc(&conbuf);
560 (void) putc(c, &conbuf);
561 }
562 return (c);
563 }
564
565 #if JUSTHACKIT
566 justhackit(c, 0);
567 #else JUSTHACKIT
568
569 was = usm2cn();
570 outb(iUSM_TXD, c);
571 for (;;) {
572 while((inb(iUSM_LSR) & iDR) == 0);
573 if ((x = inb(iUSM_RXD)) == KT_RDY) {
574 break;
575 } else if (stray_count < sizeof(stray)) {
576 stray[stray_count++] = x;
577 }
578 outb(iUSM_TXD, c);
579 }
580 cn2usm(was);
581
582 #endif JUSTHACKIT
583
584 return(c);
585 }
586
587
588 usm2cn()
589 {
590 int was, s;
591
592 was = interrupts_on;
593 if (was) {
594 s = spltty();
595 /*
596 * we need to let the interrupt driven state machine
597 * kick around until we can jump in.
598 */
599 while (state != NOT_WAITING) {
600 #if i860
601 /*led_printf("usm2cn: state = %d\n", state);*/
602 #endif i860
603 splx(s);
604 s = spltty();
605 }
606 disable_interrupts();
607 polling = 1;
608 splx(s);
609 }
610
611 return was;
612 }
613
614
615 cn2usm(was)
616 int was;
617 {
618 if (was) {
619 polling = 0;
620 enable_interrupts();
621 }
622 }
623
624
625 cnswitch(wait)
626 boolean_t wait;
627 {
628 int c, was;
629
630 was = usm2cn();
631 c = cndogetc(wait);
632 cn2usm(was);
633
634 return c;
635 }
636
637
638 cngetc()
639 {
640 return (cnswitch(TRUE));
641 }
642
643
644 cnmaygetc()
645 {
646 return (cnswitch(FALSE));
647 }
648
649
650 /*
651 * This procedure reads a character from the console. It returns
652 * -1 if there is no character in the UART receive buffer or if
653 * this node is not selected for IO.
654 *
655 * Note that interrupts must be disabled so that usmintr doesn't
656 * get the character first.
657 */
658 cndogetc(wait)
659 boolean_t wait;
660 {
661 int i, c, s, was;
662
663 assert(interrupts_on == 0);
664
665 if (stray_count > 0) {
666 c = stray[0];
667 for (i = 1; i < stray_count; i++) {
668 stray[i - 1] = stray[i]; /* lazyness */
669 }
670 stray_count--;
671 } else {
672 do {
673 c = uart_getc();
674 if (c == KT_RDY) {
675 if (selected) {
676 outb(iUSM_TXD, KT_HOLD);
677 }
678 c = -1;
679 } else if (c == KT_SELECT) {
680
681 do { c = uart_getc(); } while (c == -1);
682 if (((c & 0x7F) == ipsc_slot) || (c & 0x80)) {
683 selected = TRUE;
684 dumpunsel();
685 } else {
686 selected = FALSE;
687 }
688 c = -1;
689 } else if (! selected) {
690 c = -1;
691 } else if (c == KT_KDB) {
692 #if MACH_KDB
693 kdb_kintr();
694 #endif MACH_KDB
695 c = -1;
696 }
697
698 } while (wait && (c == -1));
699 }
700 if (c == '\r')
701 c = '\n';
702
703 if (c != -1) {
704 c &= 0177;
705 }
706
707 return(c);
708 }
709
710
711 /* Called by kdb to switch keyboard from polled to interrupt */
712 cnpollc(on)
713 boolean_t on;
714 {
715 static int usm_interrupt_state = 0;
716 static int usm_interrupt_state_valid = 0;
717 int s;
718
719 s = sploff();
720 if (on) {
721 usm_interrupt_state = interrupts_on;
722 usm_interrupt_state_valid = 1;
723 disable_interrupts();
724 polling = 1;
725 }
726 else {
727 assert(usm_interrupt_state_valid != 0);
728 if (usm_interrupt_state) {
729 usm_interrupt_state = 0;
730 polling = 0;
731 enable_interrupts();
732 }
733 }
734 splon(s);
735 }
736
737
738 static disable_interrupts()
739 {
740 int s;
741
742 s = sploff();
743
744 /* switch to bank 0, 8250 compatibility */
745 outb(iUSM_BANK, iBANK0);
746
747 /* disable interrupts */
748 outb(iUSM_GER, inb(iUSM_GER) & ~(iRX_ENAB | iTX_ENAB));
749 interrupts_on = FALSE;
750
751 splon(s);
752 }
753
754 static enable_interrupts()
755 {
756 int s;
757
758 s = sploff();
759
760 /* switch to bank 0, 8250 compatibility */
761 outb(iUSM_BANK, iBANK0);
762
763 /* enable interrupts */
764 outb(iUSM_GER, inb(iUSM_GER) | iRX_ENAB);
765
766 interrupts_on = TRUE;
767
768 #if i860
769 soft_pic_enable(SERIAL_INT_MASK);
770 #endif i860
771
772 splon(s);
773 }
774
775
776 /*
777 * Hard reset the uart.
778 * Not really a hardware reset, but it does send a software reset command
779 * to the uart (which is more "firm" than reprogramming a bunch of registers).
780 */
781 uart_hardreset()
782 {
783 uart_reset(1);
784 }
785
786
787 /*
788 * Reprogram the uart without zapping some of the timer registers
789 * that are used in uart_clkstart().
790 */
791 uart_softreset()
792 {
793 uart_reset(0);
794 }
795
796
797 /*
798 * Program the uart to a known state.
799 * If a hard reset, it fakes it with a software reset command (which is
800 * slightly more firm than simply programming a few of the registers).
801 */
802 uart_reset(hard)
803 int hard;
804 {
805 int b;
806
807 if (hard) {
808 outb(iUSM_BANK, iBANK1); /* move to work bank (bank 1) */
809 outb(iUSM_ICM, 0x10); /* do a SW reset usmmand */
810 uart_delay();
811 uart_delay();
812 uart_delay();
813 uart_delay();
814 }
815 else {
816 outb(iUSM_BANK, iBANK0);
817 }
818
819 /*
820 * Set timer B count for 100 Hz
821 */
822 b = 25000;
823
824 /* we are now in bank 0 (because a SW reset usmmand puts us there) */
825 outb(iUSM_LCR, 0x80); /* turn on DLAB bit to load BAL & BAH regs */
826 outb(iUSM_BAL, 0x01); /* set duty cycle of baud rate generator A */
827 outb(iUSM_BAH, 0x00); /* same as external serial clock */
828 outb(iUSM_BANK, iBANK3); /* Switch to bank 3 */
829 outb(iUSM_BBL, b & 0xff); /* set baud rate generator B */
830 outb(iUSM_BBH, b >> 8);
831 outb(iUSM_BANK, iBANK0); /* Switch back to bank 0 */
832 outb(iUSM_LCR, 0x03); /* 1 stop, 8 bits, non-parity, clear DLAB */
833 outb(iUSM_MCR, 0x00); /* clear modem I/O pins status register */
834 /*hmm*/ outb(iUSM_GER, 0x28); /* Enable modem, timer interrupt */
835
836 outb(iUSM_BANK, iBANK2); /* move to general config (bank 2) */
837 outb(iUSM_FMD, 0x00); /* normal */
838 outb(iUSM_RMD, 0x00); /* normal */
839 outb(iUSM_TMD, 0xC0); /* manual mode, 4/4 stop bits */
840 outb(iUSM_IMD, 0x08); /* auto interrupt ack, FIFO depth 4 bytes */
841 outb(iUSM_RIE, 0x00); /* disable receive interrupts */
842
843 outb(iUSM_BANK, iBANK3); /* Switch to bank 3 */
844 outb(iUSM_CLCF, 0x50); /* X16 mode, BRG A is clock source */
845 outb(iUSM_BACF, 0x44); /* SCLK pin is clk src, enables BRG mode */
846 outb(iUSM_BBCF, 0x00); /* timer mode (system clock input) */
847 outb(iUSM_MIE, 0x09); /* enable CTS/, DCD/ change interrupts */
848 outb(iUSM_TMIE, 0x02); /* enable timer B interrupts */
849 outb(iUSM_PMD, 0xA0); /* make DSR/, DCD/ inputs */
850
851 outb(iUSM_BANK, iBANK1); /* move to work bank (bank 1) */
852 outb(iUSM_RCM, 0xB4); /* enables reception of characters */
853 outb(iUSM_TCM, 0x0E); /* enables transmission of characters */
854 outb(iUSM_ICM, 0x0C); /* status clear, int acknowledge */
855
856 outb(iUSM_BANK, iBANK0); /* move to compat bank (bank 0) */
857 }
858
859
860 /*
861 * Retrigger timer B to interrupt.
862 * It assumes that the timer value set in uart_reset() is
863 * still intact.
864 */
865 uart_clkstart()
866 {
867 int s;
868
869 s = sploff();
870 outb(iUSM_BANK, iBANK1);
871 inb(iUSM_TMST);
872 outb(iUSM_TMCR, 0x22);
873 outb(iUSM_BANK, iBANK0);
874
875 #if i860
876 soft_pic_enable(SERIAL_INT_MASK);
877 #endif i860
878
879 splon(s);
880 }
881
882
883 #if i386
884 int uart_delay()
885 {
886 volatile long time = 64000;
887
888 while (time--);
889 }
890 #endif i386
891
892 #if i860
893 /*
894 * uart_delay allows the serial chip to recover from read or write
895 */
896 uart_delay()
897 {
898 while ((inb(COUNTER_PORT) & 0x20) == 0);
899 while ((inb(COUNTER_PORT) & 0x20) != 0);
900 }
901 #endif
902
903 /*
904 * Pull in a character from the uart.
905 * No interrupts while checking...
906 */
907 uart_getc()
908 {
909 int s, c;
910
911 s = sploff();
912 if ((inb(iUSM_LSR) & iDR) == 0) {
913 splon(s);
914 return (-1);
915 }
916 c = inb(iUSM_RXD) & 0xff;
917 splon(s);
918
919 return (c);
920 }
921
922
923 #if 0
924 /*
925 * Push a character out of the uart.
926 * No interrupts while waiting for TX ready...
927 */
928 uart_putc(c)
929 char c;
930 {
931 int s = sploff();
932
933 while ((inb(iUSM_LSR) & iTHRE) == 0);
934 outb(iUSM_TXD, c);
935
936 splon(s);
937
938 return (c);
939 }
940 #endif 0
Cache object: 68777d601a3e0efb6c4c1cd9e6c6d79a
|