|
|
1.1 root 1: /* (-lgl
2: * COHERENT Driver Kit Version x.x.x
3: * Copyright (c) 1982, 1990 by Mark Williams Company.
4: * All rights reserved. May not be copied without permission.
5: *
6: * $Log: alx.c,v $
7: * Revision 1.2 92/08/04 12:51:47 bin
8: * update for ker59
9: *
10: * Revision 1.11 92/04/30 08:59:18 hal
11: * Add asy. Remove silos from tty struct.
12: *
13: * Revision 1.10 92/04/13 14:53:15 hal
14: * Silos moved out of TTY struct.
15: *
16: * Revision 1.9 92/04/13 10:12:27 hal
17: * Add NO_ISILO test code.
18: *
19: * Revision 1.8 92/03/19 18:33:17 hal
20: * LSR_READ debug macro.
21: *
22: * Revision 1.7 92/03/16 16:51:39 hal
23: * t_hal diagnostics.
24: *
25: * Revision 1.6 92/02/20 19:43:13 piggy
26: * Add "mode" arg to ttsetgrp() for NOCTTY support.
27: *
28: * Revision 1.5 92/02/16 18:27:47 hal
29: * Binary compatibility with Sys V sgtty
30: *
31: * Revision 1.4 92/02/07 09:41:21 hal
32: * Fix Wallenberg bug.
33: *
34: * Revision 2.10 92/02/04 18:50:00 hal
35: * Use EBUSY, not EDBUSY - merge for 386 code.
36: *
37: * Revision 2.9 92/01/13 08:38:24 hal
38: * Rearrange alxopen() to deal with ill-behaved daemons.
39: *
40: * Revision 2.8 92/01/12 19:23:50 hal
41: * Tracking nasty Kelly bug.
42: *
43: * Revision 2.6 91/12/26 16:52:05 hal
44: * Flags left in bad state if open r-device got killed.
45: *
46: * Revision 2.5 91/12/20 14:08:27 hal
47: * Add static alx_send().
48: * From alxstart(), don't toggle Tx interrupts - call alx_send().
49: *
50: * Revision 2.4 91/12/10 08:04:13 hal
51: * Make interrupt routine clear all UART irq conditions if it gets an
52: * interrupt without an argument telling which port interrupted.
53: *
54: * Revision 2.3 91/12/05 09:35:06 hal
55: * Working 16550A code. Nfg on GeeSee.
56: *
57: * Revision 2.2 91/12/02 19:21:45 hal
58: * Last version before FIFO testing.
59: *
60: * Revision 2.1 91/11/21 18:17:44 hal
61: * Same as V1.13 - used in 3.2.05k
62: *
63: -lgl) */
64: /*
65: * Shared parts of IBM async port drivers.
66: */
67: #include <sys/coherent.h>
68: #ifndef _I386
69: #include <sys/i8086.h>
70: #endif
71: #include <sys/al.h>
72: #include <sys/con.h>
73: #include <errno.h>
74: #include <sys/stat.h>
75: #include <sys/tty.h>
76: #include <sys/timeout.h>
77: #include <sys/clist.h>
78: #include <sys/ins8250.h>
79: #include <sys/sched.h>
80: #include <sys/silo.h>
81:
82: #ifdef _I386
83: #define EEBUSY EBUSY
84: #else
85: #define EEBUSY EDBUSY
86: #endif
87:
88: #define ALPORT (((COM_DDP *)(tp->t_ddp))->port)
89: #define AL_NUM (((COM_DDP *)(tp->t_ddp))->com_num)
90:
91: #define DTRTMOUT 3 /* DTR timeout interval in seconds for close */
92:
93: /*
94: * For rawin silo (see poll_clk.h), use last element of si_buf to count
95: * the number of characters in the silo.
96: */
97: #define SILO_CHAR_COUNT si_buf[SI_BUFSIZ-1]
98: #define SILO_HIGH_MARK (SI_BUFSIZ-SI_BUFSIZ/4)
99: #define SILO_LOW_MARK (SI_BUFSIZ/4)
100: #define MAX_SILO_INDEX (SI_BUFSIZ-2)
101: #define MAX_SILO_CHARS (SI_BUFSIZ-1)
102:
103: /*
104: * The following silo FLUSH macros are always called at high priority!
105: */
106: #ifdef NO_ISILO
107: #define RAWIN_FLUSH(in_silo)
108: #else
109: #define RAWIN_FLUSH(in_silo) { in_silo->si_ox = in_silo->si_ix; \
110: in_silo->SILO_CHAR_COUNT = 0; }
111: #endif
112: #define RAWOUT_FLUSH(out_silo) { out_silo->si_ox = out_silo->si_ix; }
113:
114: int al_sg_set = 0;
115: int al_sg_clr = 0;
116: static int poll_divisor; /* set by set_poll_rate(), read by alxclk() */
117:
118: /*
119: * functions herein
120: */
121: int alxopen();
122: int alxclose();
123: int alxtimer();
124: int alxioctl();
125: int alxparam();
126: int alxcycle();
127: int alxstart();
128: int alxbreak();
129: int alxintr();
130: static int alxclk();
131: static set_poll_rate();
132: static void alxpoll();
133: static void alx_send();
134: static int iocbaud[4];
135: static char ioclcr[4];
136:
137: /*
138: * Port addresses are now patchable.
139: */
140: int AL_ADDR[] = {
141: #if BOB_H
142: 0x280, 0x288, 0x290, 0x298
143: #else
144: 0x3F8, 0x2F8, 0x3E8, 0x2E8
145: #endif
146: };
147:
148: /*
149: * Baud rate table and polling rate table.
150: * Indexed by ioctl bit rates.
151: */
152: extern int albaud[], alp_rate[];
153:
154: /*
155: * the following is for debug only
156: */
157: #if TRACER
158: int ASY_OR = 0;
159: #define LSR_READ(lval, port) \
160: { lval = inb((port)+LSR); if (lval & LS_OVER) ASY_OR++; }
161: #define CDUMP(text, tp) cdump(text, tp);
162: #define tprintf(str) { T_HAL(4, printf(str)); }
163: #define REPORT_OE {if(ASY_OR&&(t_hal&0x20)){printf("oe=%d ",ASY_OR);ASY_OR=0;}}
164: cdump(message, tp)
165: char *message;
166: TTY *tp;
167: {
168: int i, b;
169: char cmd[11];
170:
171: if ((t_hal & 4) == 0)
172: return;
173: for (i = 0; i < NUM_AL_PORTS; i++) {
174: if (tp_table[i]) {
175: b = ((COM_DDP *)(tp_table[i]->t_ddp))->port;
176: printf("%x:%x:%x:%x ", i+1, b, inb(b+MCR), inb(b+IER));
177: }
178: }
179: for (i = 0; i < 10; i++) {
180: cmd[i] = u.u_comm[i];
181: }
182: cmd[10] = '\0';
183: printf("poll=%d cmd=%s pid=%d ", poll_rate, cmd, SELF->p_pid);
184: printf("%s\n", message);
185: if (tp) {
186: printf("#%d f=%x op=%d ", AL_NUM, tp->t_flags, tp->t_open);
187: printf("in_use=%d irq=%d has_irq=%d ",
188: com_usage[AL_NUM].in_use,
189: com_usage[AL_NUM].irq,
190: com_usage[AL_NUM].has_irq);
191: printf("poll=%d hcls=%d ohlt=%d\n",
192: com_usage[AL_NUM].poll,
193: com_usage[AL_NUM].hcls,
194: com_usage[AL_NUM].ohlt);
195: }
196: }
197: #else
198: #define CDUMP(text, tp)
199: #define REPORT_OE
200: #define LSR_READ(lval, port) { lval = inb((port)+LSR); }
201: #endif
202:
203: /*
204: * alxopen()
205: */
206: alxopen(dev, mode, tp, irqtty)
207: dev_t dev;
208: int mode;
209: register TTY *tp, **irqtty;
210: {
211: int s;
212: int b;
213: int minor_h; /* minor device number including high bit */
214: unsigned char msr;
215:
216: minor_h = minor(dev); /* complete minor number */
217: b = ALPORT;
218:
219: if (com_usage[AL_NUM].uart_type == US_NONE) { /* chip not found */
220: u.u_error = ENXIO;
221: goto bad_open;
222: }
223:
224: if ((tp->t_flags & T_EXCL) && !super()) {
225: u.u_error = ENODEV;
226: goto bad_open;
227: }
228:
229: if (drvl[major(dev)].d_time != 0) { /* Modem settling */
230: u.u_error = EEBUSY;
231: goto bad_open;
232: }
233:
234: /*
235: * Can't open a polled port if another driver is using polling.
236: */
237: if (dev & CPOLL && poll_owner & ~ POLL_AL) {
238: u.u_error = EEBUSY;
239: goto bad_open;
240: }
241:
242: /*
243: * Can't have both com[13] or both com[24] IRQ at once.
244: */
245: if ( !(dev & CPOLL)
246: && com_usage[AL_NUM^2].irq
247: && com_usage[AL_NUM^2].in_use) {
248: u.u_error = EEBUSY;
249: goto bad_open;
250: }
251:
252: /*
253: * If port already in use, are new and old open modes compatible?
254: */
255: if (com_usage[AL_NUM].in_use) {
256: int oldmode = 0, newmode = 0; /* mctl:1 poll:2 flow:4 */
257:
258: if (tp->t_flags & T_MODC)
259: oldmode += 1;
260: if (com_usage[AL_NUM].irq == 0)
261: oldmode += 2;
262: if (tp->t_flags & T_CFLOW)
263: oldmode += 4;
264: if ((minor_h & NMODC) == 0)
265: newmode += 1;
266: if (dev & CPOLL)
267: newmode += 2;
268: if (minor_h & CFLOW)
269: newmode += 4;
270: if (oldmode != newmode) {
271: u.u_error = EEBUSY;
272: goto bad_open;
273: }
274: }
275:
276: /*
277: * Sleep here if another process is opening or closing the port.
278: * This can happen if:
279: * another process is trying a first open and awaiting CD;
280: * another process is closing the port after losing CD;
281: * a remote process opened the port, spawned a daemon,
282: * and disconnected, and the daemon ignored SIGHUP and is
283: * improperly keeping the port open.
284: * Don't try to set tp->t_flags before this sleep! During
285: * the sleep, ttclose() may be called and clear the flags.
286: */
287: while (com_usage[AL_NUM].in_use &&
288: (com_usage[AL_NUM].hcls ||
289: ((minor_h & NMODC) == 0 && (inb(b+MSR) & MS_RLSD) == 0))) {
290: sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT, SVTTOUT);
291: if (SELF->p_ssig && nondsig()) { /* signal? */
292: u.u_error = EINTR;
293: goto bad_open;
294: }
295: }
296:
297: /*
298: * If port already in use, are new and old open modes compatible?
299: * If not in use, mark it as such.
300: */
301: if (com_usage[AL_NUM].in_use) {
302: int oldmode = 0, newmode = 0; /* mctl:1 poll:2 flow:4 */
303:
304: if (tp->t_flags & T_MODC)
305: oldmode += 1;
306: if (com_usage[AL_NUM].irq == 0)
307: oldmode += 2;
308: if (tp->t_flags & T_CFLOW)
309: oldmode += 4;
310: if ((minor_h & NMODC) == 0)
311: newmode += 1;
312: if (dev & CPOLL)
313: newmode += 2;
314: if (minor_h & CFLOW)
315: newmode += 4;
316: if (oldmode != newmode) {
317: u.u_error = EEBUSY;
318: goto bad_open;
319: }
320: } else {
321: /*
322: * Save modes for this open attempt to avoid future conflicts.
323: * Then start alxcycle() for this port.
324: */
325: if (dev & CPOLL)
326: com_usage[AL_NUM].irq = 0;
327: else
328: com_usage[AL_NUM].irq = 1;
329: if (minor_h & CFLOW)
330: tp->t_flags |= T_CFLOW;
331: else
332: tp->t_flags &= ~T_CFLOW;
333: if (minor_h & NMODC)
334: tp->t_flags &= ~T_MODC;
335: else
336: tp->t_flags |= T_MODC;
337: }
338: com_usage[AL_NUM].in_use++;
339: /*
340: * From here, error exit is bad_open_u.
341: */
342:
343: if (tp->t_open == 0) { /* not already open */
344: if (!(dev & CPOLL)) {
345: *irqtty = tp_table[AL_NUM];
346: com_usage[AL_NUM].has_irq = 1;
347: }
348:
349: /*
350: * Need to start cycling to scan for CD.
351: */
352: alxcycle(tp);
353:
354: s = sphi();
355: /*
356: * Raise basic modem control lines even if modem
357: * control hasn't been specified.
358: * MC_OUT2 turns on NON-open-collector IRQ line from the UART.
359: * since we can't have two UART's on same IRQ with MC_OUT2 on
360: */
361: if (dev & CPOLL) {
362: outb(b+MCR, MC_RTS|MC_DTR);
363: } else {
364: outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
365: outb(b+IER, IENABLE);
366: }
367:
368: if ((minor_h & NMODC) == 0) { /* want modem control? */
369: tp->t_flags |= T_HOPEN | T_STOP;
370: for (;;) { /* wait for carrier */
371: msr = inb(b+MSR);
372: /*
373: * If carrier detect present
374: * if port not already open
375: * break out of loop and finish first open
376: * else
377: * do second (or third, etc.) open
378: */
379: if (msr & MS_RLSD)
380: break;
381: sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
382: SVTTOUT); /* wait for carrier */
383: if (SELF->p_ssig && nondsig()) { /* signal? */
384: outb(b+MCR, 0);
385: outb(b+IER, 0);
386: u.u_error = EINTR;
387: tp->t_flags &= ~(T_HOPEN | T_STOP);
388: spl(s);
389: goto bad_open_u;
390: }
391: }
392:
393: /*
394: * Mark that we are no longer hanging in open.
395: * Allow output over the port unless hardware flow
396: * control says not to.
397: */
398: tp->t_flags &= ~T_HOPEN;
399: tp->t_flags &= ~T_STOP;
400: if (!(tp->t_flags & T_CFLOW) || (msr & MS_CTS))
401: com_usage[AL_NUM].ohlt = 0;
402: else
403: com_usage[AL_NUM].ohlt = 1;
404:
405: /*
406: * Awaken any other opens on same device.
407: */
408: wakeup((char *)(&tp->t_open));
409: }
410: tp->t_flags |= T_CARR;
411: ttopen(tp); /* stty inits */
412:
413: /*
414: * Allow custom modification of defaults.
415: */
416: tp->t_sgttyb.sg_flags |= al_sg_set;
417: tp->t_sgttyb.sg_flags &= ~al_sg_clr;
418:
419: alxparam(tp);
420: spl(s);
421: } /* end of first-open case */
422:
423: tp->t_open++;
424: ttsetgrp(tp, dev, mode);
425:
426: /*
427: * Turn on polling for the port.
428: */
429: if (dev & CPOLL) {
430: com_usage[AL_NUM].poll = 1;
431: set_poll_rate();
432: }
433:
434: CDUMP((dev&CPOLL)?"open polled":"open irq", tp)
435: return;
436:
437: bad_open_u:
438: --com_usage[AL_NUM].in_use;
439: wakeup((char *)(&tp->t_open));
440: bad_open:
441: return;
442: }
443:
444: /*
445: * alxclose()
446: *
447: * Called whenever kernel closes a com port.
448: */
449: alxclose(dev, mode, tp)
450: dev_t dev;
451: int mode;
452: TTY *tp;
453: {
454: register int b;
455: int maj;
456: int flags;
457: int s;
458: unsigned char lsr;
459: silo_t * out_silo = &com_usage[AL_NUM].raw_out;
460: silo_t * in_silo = &com_usage[AL_NUM].raw_in;
461:
462: if (--tp->t_open)
463: goto closed;
464: s = sphi();
465:
466: /*
467: * Called at high priority by alclose after al_buff is drained
468: */
469: com_usage[AL_NUM].hcls = 1; /* disallow reopen til done closing */
470: flags = tp->t_flags; /* save flags - ttclose zeroes them */
471: ttclose(tp);
472: b = ALPORT;
473:
474: /*
475: * Wait for output silo and uart xmit buffer to empty.
476: * Allow signal to break the sleep.
477: */
478: for (;;) {
479: LSR_READ(lsr, b);
480: if ((lsr & LS_TxIDLE)
481: && (out_silo->si_ix == out_silo->si_ox))
482: break;
483: CDUMP("slp cls", tp)
484: sleep((char *)out_silo, CVTTOUT, IVTTOUT, SVTTOUT);
485: if (SELF->p_ssig && nondsig()) { /* signal? */
486: RAWOUT_FLUSH(out_silo);
487: break;
488: }
489: }
490:
491: /*
492: * If not hanging in open
493: */
494: if ((flags & T_HOPEN) == 0) {
495: /*
496: * Disable interrupts.
497: */
498: outb(b+IER, 0);
499: outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
500: }
501:
502: /*
503: * If hupcls
504: */
505: if (flags & T_HPCL) {
506: /*
507: * Hangup port - drop DTR and RTS.
508: */
509: outb(b+MCR, inb(b+MCR)&MC_OUT2);
510:
511: /*
512: * Hold dtr low for timeout
513: */
514: maj = major(dev);
515: drvl[maj].d_time = 1;
516: CDUMP("slp DTR", tp)
517: sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
518: drvl[maj].d_time = 0;
519: }
520: com_usage[AL_NUM].poll = 0;
521: set_poll_rate();
522: RAWIN_FLUSH(in_silo);
523: com_usage[AL_NUM].hcls = 0; /* allow reopen - done closing */
524: wakeup((char *)(&tp->t_open));
525: spl(s);
526: closed:;
527: --com_usage[AL_NUM].in_use;
528: wakeup((char *)(&tp->t_open));
529: CDUMP("closed", tp)
530: }
531:
532: /*
533: * Common c_timer routine for async ports.
534: */
535: alxtimer(dev)
536: dev_t dev;
537: {
538: if (++drvl[major(dev)].d_time > DTRTMOUT)
539: wakeup((char *)&drvl[major(dev)].d_time);
540: }
541:
542:
543: /*
544: * Common c_ioctl routine for async ports.
545: */
546: alxioctl(dev, com, vec, tp)
547: dev_t dev;
548: struct sgttyb *vec;
549: register TTY *tp;
550: {
551: register int s, b;
552: int stat1, stat2;
553: unsigned char msr;
554: unsigned char ier_save;
555: silo_t * out_silo = &com_usage[AL_NUM].raw_out;
556: silo_t * in_silo = &com_usage[AL_NUM].raw_in;
557:
558: s = sphi();
559: b = ALPORT;
560: ier_save=inb(b+IER);
561: stat1 = inb(b+MCR); /* get current MCR register status */
562: stat2 = inb(b+LCR); /* get current LCR register status */
563:
564: switch(com) {
565: case TIOCSBRK: /* set BREAK */
566: outb(b+LCR, stat2|LC_SBRK);
567: break;
568: case TIOCCBRK: /* clear BREAK */
569: outb(b+LCR, stat2 & ~LC_SBRK);
570: break;
571: case TIOCSDTR: /* set DTR */
572: outb(b+MCR, stat1|MC_DTR);
573: break;
574: case TIOCCDTR: /* clear DTR */
575: outb(b+MCR, stat1 & ~MC_DTR);
576: break;
577: case TIOCSRTS: /* set RTS */
578: outb(b+MCR, stat1|MC_RTS);
579: break;
580: case TIOCCRTS: /* clear RTS */
581: outb(b+MCR, stat1 & ~MC_RTS);
582: break;
583: case TIOCRSPEED: /* set "raw" I/O speed divisor */
584: outb(b+LCR, stat2|LC_DLAB); /* set speed latch bit */
585: outb(b+DLL, (unsigned) vec);
586: outb(b+DLH, (unsigned) vec >> 8);
587: outb(b+LCR, stat2); /* reset latch bit */
588: break;
589: case TIOCWORDL: /* set word length and stop bits */
590: outb(b+LCR, ((stat2&~0x7) | ((unsigned) vec & 0x7)));
591: break;
592: case TIOCRMSR: /* get CTS/DSR/RI/RLSD (MSR) */
593: msr = inb(b+MSR);
594: stat1 = msr >> 4;
595: kucopy(&stat1, (unsigned *) vec, sizeof(unsigned));
596: break;
597: case TIOCFLUSH: /* Flush silos here, queues in tty.c */
598: RAWIN_FLUSH(in_silo);
599: RAWOUT_FLUSH(out_silo);
600: /* fall through to default... */
601: default:
602: ttioctl(tp, com, vec);
603: }
604: outb(b+IER, ier_save);
605: spl(s);
606: }
607:
608: alxparam(tp)
609: TTY *tp;
610: {
611: register int b;
612: register int baud;
613: int s;
614: char newlcr;
615: int write_baud=1, write_lcr=1;
616: int alnum;
617:
618: b = ALPORT;
619:
620: /*
621: * error if input speed not the same as output speed
622: */
623: if (tp->t_sgttyb.sg_ispeed!=tp->t_sgttyb.sg_ospeed) {
624: u.u_error = ENODEV;
625: return;
626: }
627:
628: if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) {
629: if (tp->t_flags & T_MODC) { /* modem control? */
630: s = sphi();
631: tp->t_flags &= ~T_CARR; /* indicate no carrier */
632: outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
633: spl(s);
634: }
635: write_baud = 0;
636: }
637:
638: switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
639: case ODDP:
640: newlcr = LC_CS7|LC_PARENB;
641: break;
642: case EVENP:
643: newlcr = LC_CS7|LC_PARENB|LC_PAREVEN;
644: break;
645: default:
646: newlcr = LC_CS8;
647: break;
648: }
649:
650: alnum = AL_NUM;
651: if (alnum >= 0 && alnum < 4) {
652: if (baud == iocbaud[alnum]) {
653: write_baud = 0;
654: if (newlcr == ioclcr[alnum]) {
655: write_lcr = 0;
656: }
657: }
658: iocbaud[alnum] = baud;
659: ioclcr[alnum] = newlcr;
660: }
661:
662: if (write_lcr) {
663: unsigned char ier_save;
664: s=sphi();
665: ier_save=inb(b+IER);
666: if (write_baud) {
667: outb(b+LCR, LC_DLAB);
668: outb(b+DLL, baud);
669: outb(b+DLH, baud >> 8);
670: }
671: outb(b+LCR, newlcr);
672: if (com_usage[AL_NUM].uart_type == US_16550A)
673: outb(b+FCR, FC_ENABLE | FC_Rx_RST | FC_Rx_08);
674: outb(b+IER, ier_save);
675: spl(s);
676: }
677:
678: set_poll_rate();
679: }
680:
681: /*
682: * Middle level processor.
683: *
684: * Invoked 10 times per second. (Once every ten clock ticks.)
685: * Tranfers rawin buffer [from intr level] to canonical input queue.
686: * Checks modem status for loss of carrier.
687: * Transfers output queue to rawout buffer [for intr level].
688: */
689: alxcycle(tp)
690: register TTY * tp;
691: {
692: register int b;
693: register int n;
694: unsigned char msr, mcr;
695: int s;
696: silo_t * out_silo = &com_usage[AL_NUM].raw_out;
697: silo_t * in_silo = &com_usage[AL_NUM].raw_in;
698:
699: REPORT_OE;
700: /*
701: * Check Carrier Detect (RLSD).
702: *
703: * Modem status interrupts were not enabled due to 8250 hardware bug.
704: * Enabling modem status and receive interrupts may cause lockup
705: * on older parts.
706: */
707: if (tp->t_flags & T_MODC) {
708:
709: /*
710: * Get status
711: */
712: msr = inb(ALPORT+MSR);
713:
714: /*
715: * Carrier changed.
716: */
717: if ((msr & MS_RLSD) && !(tp->t_flags & T_CARR)) {
718: /*
719: * Carrier is on - wakeup open.
720: */
721: s = sphi();
722: tp->t_flags |= T_CARR;
723: spl(s);
724: wakeup((char *)(&tp->t_open));
725: }
726:
727: if (!(msr & MS_RLSD) && (tp->t_flags & T_CARR)) {
728: s = sphi();
729: RAWIN_FLUSH(in_silo);
730: RAWOUT_FLUSH(out_silo);
731: tp->t_flags &= ~T_CARR;
732: spl(s);
733: tthup(tp);
734: }
735: }
736:
737: /*
738: * Empty raw input buffer.
739: *
740: * The line discipline module (tty.c) will set T_ISTOP true when the
741: * tt input queue is nearly full (tp->t_iq.cq_cc >= IHILIM), and make
742: * T_ISTOP false when it's ready for more input.
743: *
744: * When T_ISTOP is true, ttin() simply discards the character passed.
745: */
746: #ifndef NOISILO
747: if (!(tp->t_flags & T_ISTOP)) {
748: while (in_silo->SILO_CHAR_COUNT > 0) {
749: s = sphi();
750: ttin(tp, in_silo->si_buf[in_silo->si_ox]);
751: if (in_silo->si_ox < MAX_SILO_INDEX)
752: in_silo->si_ox++;
753: else
754: in_silo->si_ox = 0;
755: in_silo->SILO_CHAR_COUNT--;
756: spl(s);
757: }
758: }
759: #endif
760:
761: /*
762: * Hardware flow control.
763: * Check CTS to see if we need to halt output.
764: * (MS_INTR should have done this - repeat code here to be sure)
765: * Check input silo to see if we need to raise RTS.
766: */
767: if (tp->t_flags & T_CFLOW) {
768:
769: /*
770: * Get status
771: */
772: msr = inb(ALPORT+MSR);
773:
774: s = sphi();
775: if (msr & MS_CTS)
776: com_usage[AL_NUM].ohlt = 0;
777: else
778: com_usage[AL_NUM].ohlt = 1;
779: spl(s);
780: #if TRACER
781: if(t_hal & 4) {static cts = 0;
782: if (!cts && (msr & MS_CTS)) {
783: cts = 1;
784: printf("[");
785: } else if (cts && !(msr & MS_CTS)) {
786: cts = 0;
787: printf("]");
788: }}
789: #endif
790:
791: /*
792: * If using hardware flow control, see if we need to drop RTS.
793: */
794: if ( (tp->t_flags & T_CFLOW)
795: #ifdef NO_ISILO
796: && (tp->t_flags & T_ISTOP)) {
797: #else
798: && (in_silo->SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
799: #endif
800: s = sphi();
801: mcr = inb(ALPORT+MCR);
802: if (mcr & MC_RTS) {
803: outb(ALPORT+MCR, mcr & ~MC_RTS);
804: #if TRACER
805: tprintf("-");
806: #endif
807: }
808: spl(s);
809: }
810:
811: /*
812: * If input silo below low mark, assert RTS.
813: */
814: #ifdef NO_ISILO
815: if ((tp->t_flags & T_ISTOP) == 0) {
816: #else
817: if (in_silo->SILO_CHAR_COUNT <= SILO_LOW_MARK) {
818: #endif
819: s = sphi();
820: mcr = inb(ALPORT+MCR);
821: if ((mcr & MC_RTS) == 0) {
822: outb(ALPORT+MCR, mcr | MC_RTS);
823: #if TRACER
824: tprintf("+");
825: #endif
826: }
827: spl(s);
828: }
829: }
830:
831: /*
832: * Calculate free output slot count.
833: */
834: n = sizeof(out_silo->si_buf) - 1;
835: n += out_silo->si_ox - out_silo->si_ix;
836: n %= sizeof(out_silo->si_buf);
837:
838: /*
839: * Fill raw output buffer.
840: */
841: for (;;) {
842: if (--n < 0)
843: break;
844: s = sphi();
845: b = ttout(tp);
846: spl(s);
847: if (b < 0)
848: break;
849:
850: s = sphi();
851: out_silo->si_buf[out_silo->si_ix] = b;
852: if (out_silo->si_ix >= sizeof(out_silo->si_buf) - 1)
853: out_silo->si_ix = 0;
854: else
855: out_silo->si_ix++;
856: spl(s);
857: }
858:
859: /*
860: * (Re)start output, wake sleeping processes, etc.
861: */
862: ttstart(tp);
863:
864: /*
865: * Schedule next cycle.
866: */
867: if (com_usage[AL_NUM].in_use)
868: timeout(&tp->t_rawtim, HZ/10, alxcycle, tp);
869: }
870:
871: /*
872: * Serial Transmit Start Routine.
873: */
874: alxstart(tp)
875: register TTY * tp;
876: {
877: int b;
878: int s;
879: extern alxbreak();
880: int need_xmit = 1; /* True if should start sending data now. */
881: silo_t * out_silo = &com_usage[AL_NUM].raw_out;
882:
883: /*
884: * Read line status register AFTER disabling interrupts.
885: */
886: s = sphi();
887: LSR_READ(b, ALPORT);
888:
889: /*
890: * Process break indication.
891: * NOTE: Break indication cleared when line status register was read.
892: */
893: if (b & LS_BREAK)
894: defer(alxbreak, tp);
895:
896: /*
897: * If no output data, it may be time to finish closing the port;
898: * but won't need another xmit interrupt.
899: */
900: if (out_silo->si_ix == out_silo->si_ox) {
901: wakeup((char *)out_silo);
902: need_xmit = 0;
903: }
904:
905: /*
906: * Do nothing if output is stopped.
907: */
908: if (tp->t_flags & T_STOP)
909: need_xmit = 0;
910: if (com_usage[AL_NUM].ohlt)
911: need_xmit = 0;
912:
913: /*
914: * Start data transmission by writing to UART xmit reg.
915: */
916: if ((b & LS_TxRDY) && need_xmit) {
917: int xmit_count;
918:
919: xmit_count = (com_usage[AL_NUM].uart_type == US_16550A)?16:1;
920: alx_send(out_silo, ALPORT+DREG, xmit_count);
921: }
922:
923: spl(s);
924: }
925:
926: /*
927: * Serial Received Break Handler.
928: */
929: alxbreak(tp)
930: TTY * tp;
931: {
932: int s;
933: silo_t * out_silo = &com_usage[AL_NUM].raw_out;
934: silo_t * in_silo = &com_usage[AL_NUM].raw_in;
935:
936: s = sphi();
937: RAWIN_FLUSH(in_silo);
938: RAWOUT_FLUSH(out_silo);
939: spl(s);
940: ttsignal(tp, SIGINT);
941: }
942:
943: /*
944: * Serial Interrupt Handler.
945: */
946: alxintr(tp)
947: register TTY * tp;
948: {
949: int c;
950: register int port = ALPORT;
951: unsigned char msr, lsr;
952: int xmit_count;
953: silo_t * in_silo = &com_usage[AL_NUM].raw_in;
954: silo_t * out_silo = &com_usage[AL_NUM].raw_out;
955:
956: if (tp) {
957: rescan:
958: switch (inb(port+IIR) & 0x07) {
959:
960: case LS_INTR:
961: LSR_READ(lsr, port);
962: if (lsr & LS_BREAK)
963: defer(alxbreak, tp);
964: goto rescan;
965:
966: case Rx_INTR:
967: c = inb(port+DREG);
968: if (tp->t_open == 0)
969: goto rescan;
970: /*
971: * Must recognize XOFF quickly to avoid transmit overrun.
972: * Recognize XON here as well to avoid race conditions.
973: */
974: if (!ISRIN) {
975: /*
976: * XOFF.
977: */
978: if (ISSTOP) {
979: tp->t_flags |= T_STOP;
980: goto rescan;
981: }
982:
983: /*
984: * XON.
985: */
986: if (ISSTART) {
987: tp->t_flags &= ~T_STOP;
988: goto rescan;
989: }
990: }
991:
992: /*
993: * Save char in raw input buffer.
994: */
995: #ifdef NO_ISILO
996: if (tp->t_flags & T_ISTOP) {
997: /*
998: * If using hardware flow control, we need to drop RTS.
999: */
1000: if (tp->t_flags & T_CFLOW) {
1001: unsigned char mcr = inb(port+MCR);
1002: if (mcr & MC_RTS)
1003: outb(port+MCR, mcr & ~MC_RTS);
1004: }
1005: } else {
1006: ttin(tp, c);
1007: }
1008: #else
1009: if (in_silo->SILO_CHAR_COUNT < MAX_SILO_CHARS) {
1010: in_silo->si_buf[in_silo->si_ix] = c;
1011: if (in_silo->si_ix < MAX_SILO_INDEX)
1012: in_silo->si_ix++;
1013: else
1014: in_silo->si_ix = 0;
1015: in_silo->SILO_CHAR_COUNT++;
1016: }
1017:
1018: /*
1019: * If using hardware flow control, see if we need to drop RTS.
1020: */
1021: if ( (tp->t_flags & T_CFLOW)
1022: && (in_silo->SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
1023: unsigned char mcr = inb(port+MCR);
1024: if (mcr & MC_RTS) {
1025: outb(port+MCR, mcr & ~MC_RTS);
1026: }
1027: }
1028: #endif
1029: goto rescan;
1030:
1031: case Tx_INTR:
1032: /*
1033: * Do nothing if output is stopped.
1034: */
1035: if (tp->t_flags & T_STOP)
1036: goto rescan;
1037: if (com_usage[AL_NUM].ohlt)
1038: goto rescan;
1039:
1040: /*
1041: * Transmit next char in raw output buffer.
1042: */
1043: xmit_count =
1044: (com_usage[AL_NUM].uart_type == US_16550A)?16:1;
1045: alx_send(out_silo, port+DREG, xmit_count);
1046: goto rescan;
1047:
1048: case MS_INTR:
1049: /*
1050: * Get status (and clear interrupt).
1051: */
1052: msr = inb(port+MSR);
1053:
1054: /*
1055: * Hardware flow control.
1056: * Check CTS to see if we need to halt output.
1057: */
1058: if (tp->t_flags & T_CFLOW) {
1059: if (msr & MS_CTS)
1060: com_usage[AL_NUM].ohlt = 0;
1061: else
1062: com_usage[AL_NUM].ohlt = 1;
1063: }
1064:
1065: goto rescan;
1066: } /* endswitch */
1067: } else {
1068: /*
1069: * If tp is zero, an interrupt occurred before things
1070: * are fully set up. Just try to clear all pending
1071: * interrupts from ANY serial ports.
1072: */
1073: int com_num;
1074: for (com_num = 0; com_num < 4; com_num++) {
1075: port = AL_ADDR[com_num];
1076: inb(port+IIR);
1077: inb(port+LSR);
1078: inb(port+MSR);
1079: inb(port+DREG);
1080: }
1081: }
1082: }
1083:
1084: /*
1085: * alxclk will be called every time T0 interrupts - if it returns 0,
1086: * the usual system timer interrupt stuff is done
1087: */
1088: static int alxclk()
1089: {
1090: static int count;
1091: int i;
1092:
1093: for (i = 0; i < NUM_AL_PORTS; i++)
1094: if (com_usage[i].poll)
1095: alxpoll(tp_table[i]);
1096: count++;
1097: if (count >= poll_divisor)
1098: count = 0;
1099: return count;
1100: }
1101:
1102: /*
1103: * set_poll_rate is called when a port is opened or closed or changes speed
1104: * it sets the polling rate only as fast as needed, and shuts off polling
1105: * whenever possible
1106: */
1107: static set_poll_rate()
1108: {
1109: int port_num, max_rate, port_rate;
1110:
1111: /*
1112: * If another driver has the polling clock, do nothing.
1113: */
1114: if (poll_owner & ~ POLL_AL)
1115: return;
1116:
1117: /*
1118: * Find highest valid polling rate in units of HZ/10.
1119: * If using FIFO chip, can poll at 1/16 the usual rate.
1120: */
1121: max_rate = 0;
1122: for (port_num = 0; port_num < NUM_AL_PORTS; port_num++) {
1123: if (com_usage[port_num].poll) {
1124: port_rate = alp_rate[(tp_table[port_num])->t_sgttyb.sg_ispeed];
1125: if (com_usage[port_num].uart_type == US_16550A) {
1126: port_rate /= 16;
1127: if (port_rate % HZ)
1128: port_rate += HZ - (port_rate % HZ);
1129: }
1130: if (max_rate < port_rate)
1131: max_rate = port_rate;
1132: }
1133: }
1134: /*
1135: * if max_rate is not current rate, adjust the system clock
1136: */
1137: if (max_rate != poll_rate) {
1138: poll_rate = max_rate;
1139: poll_divisor = poll_rate/HZ; /* used in alxclk() */
1140: altclk_out(); /* stop previous polling */
1141: poll_owner &= ~ POLL_AL;
1142: if (max_rate) { /* resume polling at new rate if needed */
1143: poll_owner |= POLL_AL;
1144: altclk_in(poll_rate, alxclk);
1145: }
1146: CDUMP("new rate", 0)
1147: }
1148: }
1149:
1150: /*
1151: * alxpoll()
1152: *
1153: * Serial polling handler. Compare to alxintr().
1154: */
1155: static void alxpoll(tp)
1156: register TTY * tp;
1157: {
1158: int c;
1159: int port = ALPORT;
1160: int xmit_count;
1161: unsigned char lsr;
1162: silo_t * in_silo = &com_usage[AL_NUM].raw_in;
1163: silo_t * out_silo = &com_usage[AL_NUM].raw_out;
1164:
1165: /*
1166: * Check for received break first.
1167: * This status is wiped out on reading the LSR.
1168: */
1169: LSR_READ(lsr, port);
1170: if (lsr & LS_BREAK)
1171: defer(alxbreak, tp);
1172:
1173: /*
1174: * Handle all incoming characters.
1175: */
1176: for (;;) {
1177: LSR_READ(lsr, port);
1178: if ((lsr & LS_RxRDY) == 0)
1179: break;
1180: c = inb(port+DREG);
1181: if (tp->t_open == 0)
1182: continue;
1183: /*
1184: * Must recognize XOFF quickly to avoid transmit overrun.
1185: * Recognize XON here as well to avoid race conditions.
1186: */
1187: if (!ISRIN) {
1188: /*
1189: * XOFF.
1190: */
1191: if (ISSTOP) {
1192: tp->t_flags |= T_STOP;
1193: continue;
1194: }
1195:
1196: /*
1197: * XON.
1198: */
1199: if (ISSTART) {
1200: tp->t_flags &= ~T_STOP;
1201: continue;
1202: }
1203: }
1204:
1205: /*
1206: * Save char in raw input buffer.
1207: */
1208: #ifdef NO_ISILO
1209: if (tp->t_flags & T_ISTOP) {
1210: /*
1211: * If using hardware flow control, we need to drop RTS.
1212: */
1213: if (tp->t_flags & T_CFLOW) {
1214: unsigned char mcr = inb(port+MCR);
1215: if (mcr & MC_RTS)
1216: outb(port+MCR, mcr & ~MC_RTS);
1217: }
1218: } else {
1219: ttin(tp, c);
1220: }
1221: #else
1222: if (in_silo->SILO_CHAR_COUNT < MAX_SILO_CHARS) {
1223: in_silo->si_buf[in_silo->si_ix] = c;
1224: if (in_silo->si_ix < MAX_SILO_INDEX)
1225: in_silo->si_ix++;
1226: else
1227: in_silo->si_ix = 0;
1228: in_silo->SILO_CHAR_COUNT++;
1229: }
1230:
1231: /*
1232: * If using hardware flow control, see if we need to drop RTS.
1233: */
1234: if ( (tp->t_flags & T_CFLOW)
1235: && (in_silo->SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
1236: unsigned char mcr = inb(port+MCR);
1237: if (mcr & MC_RTS) {
1238: outb(port+MCR, mcr & ~MC_RTS);
1239: }
1240: }
1241: #endif
1242: }
1243:
1244: /*
1245: * Handle outgoing characters.
1246: * Do nothing if output is stopped.
1247: */
1248: LSR_READ(lsr, port);
1249: if ((lsr & LS_TxRDY)
1250: && !(tp->t_flags & T_STOP)
1251: && !(com_usage[AL_NUM].ohlt)) {
1252: /*
1253: * Transmit next char in raw output buffer.
1254: */
1255: xmit_count = (com_usage[AL_NUM].uart_type == US_16550A)?16:1;
1256: alx_send(out_silo, port+DREG, xmit_count);
1257: }
1258:
1259: /*
1260: * Hardware flow control.
1261: * Check CTS to see if we need to halt output.
1262: */
1263: if (tp->t_flags & T_CFLOW) {
1264: if (inb(port+MSR) & MS_CTS)
1265: com_usage[AL_NUM].ohlt = 0;
1266: else
1267: com_usage[AL_NUM].ohlt = 1;
1268: }
1269: }
1270:
1271: /*
1272: * alx_send()
1273: *
1274: * Write to xmit data register of the UART.
1275: * Assume all checking about whether it's time to send has been done already.
1276: * Called by time-critical IRQ and polling routines!
1277: *
1278: * "rawout" is the output silo for the TTY struct supplying data to the port.
1279: * "dreg" is the i/o address of the UART xmit data register.
1280: * "xmit_count" is the max number of chars we can write (16 for FIFO parts).
1281: */
1282: static void alx_send(rawout, dreg, xmit_count)
1283: register silo_t * rawout;
1284: int dreg, xmit_count;
1285: {
1286: /*
1287: * Transmit next chars in raw output buffer.
1288: */
1289: for (;(rawout->si_ix != rawout->si_ox) && xmit_count; xmit_count--) {
1290: outb(dreg, rawout->si_buf[rawout->si_ox]);
1291: /*
1292: * Adjust raw output buffer output index.
1293: */
1294: if (++rawout->si_ox >= sizeof(rawout->si_buf))
1295: rawout->si_ox = 0;
1296: }
1297: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.