|
|
1.1 root 1: /* (-lgl
2: * COHERENT Driver Kit Version 1.1.0
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.12 91/08/06 10:32:23 bin
8: * 2nd rts/cts version form hal
9: *
10: * Revision 1.7 91/08/02 07:59:27 hal
11: * Raw input silo uses last slot for byte count.
12: * Modem control now gives RTS/CTS flow control:
13: * CTS is checked 10x/sec (probably not often enough).
14: * On Rx_INT, check T_ISTOP and rawin silo levels; drop RTS if need to.
15: *
16: * Revision 1.6 91/04/03 18:55:07 root
17: * alxclose(): do closing state machine BEFORE dropping control lines.
18: * alxioctl(): save and restore interrupt enable register.
19: * alxopen(): wait for pending last close (fixes SLOW port bug).
20: * This version needs al.h 1.3 or later.
21: *
22: * Revision 1.5 91/04/02 17:53:37 root
23: * save MSR delta status; add MS_INTR handling; use al.h 1.2
24: *
25: * Revision 1.4 91/02/22 09:21:17 root
26: * alxintr(): replace repeated use of ALPORT macro by local variable
27: *
28: * Revision 1.3 91/02/21 14:58:16 root
29: * Fix unconditional "hupcl" bug in 3.1.0 version.
30: *
31: * Revision 1.2 91/02/21 11:21:40 hal
32: * Used in COH Release 3.1.0 - add COM3/COM4 and polling
33: *
34: * Revision 1.1 91/02/21 11:08:31 hal
35: * Used in COH Release 3.0.0 - no COM3/COM4
36: *
37: -lgl) */
38: /*
39: * Shared parts of IBM async port drivers.
40: */
41: #include <sys/coherent.h>
42: #include <sys/i8086.h>
43: #include <sys/al.h>
44: #include <sys/con.h>
45: #include <errno.h>
46: #include <sys/stat.h>
47: #include <sys/tty.h>
48: #include <sys/uproc.h>
49: #include <sys/timeout.h>
50: #include <sys/clist.h>
51: #include <sys/ins8250.h>
52: #include <sys/sched.h>
53:
54: #define ALPORT (((COM_DDP *)(tp->t_ddp))->port)
55: #define AL_TIM (((COM_DDP *)(tp->t_ddp))->tim)
56: #define AL_NUM (((COM_DDP *)(tp->t_ddp))->com_num)
57: #define AL_MSR_DELTAS (((COM_DDP *)(tp->t_ddp))->msr_deltas)
58: #define AL_H_CLOSE (((COM_DDP *)(tp->t_ddp))->h_close)
59:
60: #define DTRTMOUT 3 /* DTR timeout interval in seconds for close */
61: #define IENABLE (IE_RxI+IE_TxI+IE_LSI+IE_MSI)
62:
63: /*
64: * For rawin silo (see ktty.h), use last element of si_buf to count the number
65: * of characters in the silo.
66: */
67: #define SILO_CHAR_COUNT si_buf[SI_BUFSIZ-1]
68: #define SILO_HIGH_MARK (SI_BUFSIZ-SI_BUFSIZ/4)
69: #define MAX_SILO_INDEX (SI_BUFSIZ-2)
70: #define MAX_SILO_CHARS (SI_BUFSIZ-1)
71:
72: int al_sg_set = 0;
73: int al_sg_clr = 0;
74: static int poll_divisor; /* set by set_poll_rate(), read by alxclk() */
75:
76: /*
77: * functions herein
78: */
79: int alxopen();
80: int alxclose();
81: int alxtimer();
82: int alxioctl();
83: int alxparam();
84: int alxcycle();
85: int alxstart();
86: int alxbreak();
87: int alxintr();
88: static int alxclk();
89: static set_poll_rate();
90:
91: /*
92: * Baud rate table and polling rate table.
93: * Indexed by ioctl bit rates.
94: */
95: int albaud[] ={
96: 0, /* 0 */
97: 2304, /* 50 */
98: 1536, /* 75 */
99: 1047, /* 110 */
100: 857, /* 134.5 */
101: 768, /* 150 */
102: 576, /* 200 */
103: 384, /* 300 */
104: 192, /* 600 */
105: 96, /* 1200 */
106: 64, /* 1800 */
107: 58, /* 2000 */
108: 48, /* 2400 */
109: 32, /* 3600 */
110: 24, /* 4800 */
111: 16, /* 7200 */
112: 12, /* 9600 */
113: 6, /* 19200 */
114: 0, /* EXTA */
115: 0 /* EXTB */
116: };
117:
118: /*
119: * alp_rate[] is tied to albaud[] - it gives the minimum polling
120: * rate for the corresponding port speed; it must be a multiple
121: * of 100 (system clock Hz) and >= baud/6
122: */
123: int alp_rate[] ={ /* baud/6 or zero */
124: 0, /* 0 */
125: 1*HZ, /* 50 */
126: 1*HZ, /* 75 */
127: 1*HZ, /* 110 */
128: 1*HZ, /* 134.5 */
129: 1*HZ, /* 150 */
130: 1*HZ, /* 200 */
131: 1*HZ, /* 300 */
132: 1*HZ, /* 600 */
133: 2*HZ, /* 1200 */
134: 3*HZ, /* 1800 */
135: 4*HZ, /* 2000 */
136: 4*HZ, /* 2400 */
137: 6*HZ, /* 3600 */
138: 8*HZ, /* 4800 */
139: 12*HZ, /* 7200 */
140: 16*HZ, /* 9600 */
141: 0, /* 19200 */
142: 0, /* EXTA */
143: 0 /* EXTB */
144: };
145:
146: /*
147: * the following is for debug only
148: */
149: #if 0
150: #define CDUMP(text) cdump(text);
151:
152: cdump(message)
153: char *message;
154: {
155: int i, b;
156:
157: for (i = 0; i < NUM_AL_PORTS; i++) {
158: b = ((COM_DDP *)(tp_table[i]->t_ddp))->port;
159: printf("%x:%x:%x:%x ", i+1, b, inb(b+MCR), inb(b+IER));
160: }
161: printf("poll=%d ", poll_rate);
162: printf("%s\n", message);
163: }
164: #else
165: #define CDUMP(text)
166: #endif
167:
168: /*
169: * alxopen()
170: */
171: alxopen(dev, mode, tp, irqtty)
172: dev_t dev;
173: int mode;
174: register TTY *tp, **irqtty;
175: {
176: register int s;
177: register int b;
178: register int minor_h; /* minor device number including high bit */
179: unsigned char msr;
180:
181: minor_h = minor(dev); /* complete minor number */
182:
183: b = ALPORT;
184:
185: if (inb(b+IER) & ~IENABLE) { /* chip not found */
186: u.u_error = ENXIO;
187: return;
188: }
189:
190: if ((tp->t_flags & T_EXCL) && !super()) {
191: u.u_error = ENODEV;
192: return;
193: }
194:
195: if (drvl[major(dev)].d_time != 0) { /* Modem settling */
196: u.u_error = EDBUSY;
197: return;
198: }
199:
200: /*
201: * Can't open a polled port if another driver is using polling.
202: */
203: if (dev & CPOLL && poll_owner & ~ POLL_AL) {
204: u.u_error = EDBUSY;
205: return;
206: }
207:
208: /*
209: * exclusion conditions:
210: * can't have same port polled and IRQ at once
211: * can't have both com[13] or both com[24] IRQ at once
212: */
213: if (dev & CPOLL) {
214: if (com_usage[AL_NUM] == COM_IRQ) {
215: u.u_error = EDBUSY;
216: return;
217: }
218: } else {
219: if (com_usage[AL_NUM] == COM_POLLED
220: || com_usage[AL_NUM ^ 2] == COM_IRQ) {
221: u.u_error = EDBUSY;
222: return;
223: }
224: }
225:
226: if (tp->t_open == 0) { /* not already open */
227: /*
228: * Wait for pending last close (if any) to finish.
229: */
230: while (AL_H_CLOSE) {
231: sleep((char *)(&AL_H_CLOSE), CVTTOUT, IVTTOUT,
232: SVTTOUT);
233: }
234: s = sphi();
235: /*
236: * Raise basic modem control lines even if modem
237: * control hasn't been specified.
238: * MC_OUT2 turns on NON-open-collector IRQ line from the UART.
239: * since we can't have two UART's on same IRQ with MC_OUT2 on
240: */
241: if (dev & CPOLL) {
242: outb(b+MCR, MC_RTS|MC_DTR);
243: } else {
244: *irqtty = tp_table[AL_NUM];
245: outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
246: }
247:
248: outb(b+IER, IENABLE); /* enable interrupts */
249:
250: if ((minor_h & NMODC) == 0) { /* want modem control? */
251: tp->t_flags |= T_MODC | T_HOPEN | T_STOP;
252: while (1) { /* wait for carrier */
253: msr = inb(b+MSR);
254: AL_MSR_DELTAS |= msr;
255: if (msr & MS_RLSD)
256: break;
257: sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
258: SVTTOUT); /* wait for carrier */
259: if (SELF->p_ssig && nondsig()) { /* signal? */
260: outb(b+MCR, inb(b+MCR)&MC_OUT2);
261: /*
262: * make sure port is hungup
263: * disable all ints except for TxI
264: */
265: outb(b+IER, IE_TxI);
266: u.u_error = EINTR;
267: spl(s);
268: return;
269: }
270: }
271: tp->t_flags &= ~T_HOPEN; /* no longer hanging in open */
272: if (msr & MS_CTS)
273: tp->t_flags &= ~T_STOP;
274: } else {
275: tp->t_flags &= ~T_MODC; /* no modem control */
276: }
277: tp->t_flags |= T_CARR; /* carrier on */
278: ttopen(tp); /* stty inits */
279:
280: /*
281: * Allow custom modification of defaults.
282: */
283: tp->t_sgttyb.sg_flags |= al_sg_set;
284: tp->t_sgttyb.sg_flags &= ~al_sg_clr;
285: alxparam(tp);
286: spl(s);
287: } else { /* already open */
288: if ((minor_h & NMODC) == 0) { /* want modem control? */
289: if ((tp->t_flags & T_MODC)==0) { /* already not modem control? */
290: u.u_error = ENODEV; /* yes, don't allow open */
291: return;
292: }
293: } else { /* don't want modem control */
294: if (tp->t_flags & T_MODC) { /* already modem control? */
295: u.u_error = ENODEV; /* yes, don't allow open */
296: return;
297: }
298: }
299: }
300: tp->t_open++;
301: ttsetgrp(tp, dev);
302:
303: /*
304: * now that we've successfully opened, designate port as
305: * polled or interrupt driven to avoid future conflicts
306: */
307: if (dev & CPOLL) {
308: com_usage[AL_NUM] = COM_POLLED;
309: set_poll_rate();
310: } else { /* irq-driven port */
311: com_usage[AL_NUM] = COM_IRQ;
312: }
313:
314: CDUMP((dev&CPOLL)?"open polled":"open irq")
315: }
316:
317: /*
318: * alxclose()
319: *
320: * Called at high priority on last close for the device.
321: */
322: alxclose(dev, mode, tp)
323: dev_t dev;
324: int mode;
325: TTY *tp;
326: {
327: register unsigned holdflags;
328: register int b;
329: int state, maj;
330: int s;
331:
332: /*
333: * Called at high priority by alclose after al_buff is drained
334: */
335: holdflags = tp->t_flags; /* save flags */
336: AL_H_CLOSE = 1; /* disallow reopen til done closing */
337: ttclose(tp); /* clear flags */
338: b = ALPORT;
339: /*
340: * ttclose() only emptied the output queue tp->t_oq;
341: * now wait for the silo tp->rawout to empty
342: * and allow a delay for the UART on-chip xmit buffer to empty
343: * state 2: waiting for silo to empty
344: * state 1: stalling so UART can empty xmit buffer
345: * state 0: done! ok to shut off IRQ for this chip by clearing MC_OUT2
346: */
347: state = 2;
348: while (state) {
349: timeout(&AL_TIM, 10, wakeup, (int)&AL_TIM);
350: sleep((char *)&AL_TIM, CVTTOUT, IVTTOUT, SVTTOUT);
351: if (tp->t_rawout.si_ix == tp->t_rawout.si_ox && state)
352: state--;
353: }
354:
355: /*
356: * If not hanging in open
357: */
358: if ((holdflags & T_HOPEN) == 0) {
359: /*
360: * Disable all ints except TxI
361: */
362: outb(b+IER, IE_TxI);
363: } else {
364: /*
365: * Flags for first open
366: */
367: tp->t_flags = T_MODC | T_HOPEN;
368: }
369:
370: /*
371: * If hupcls
372: */
373: if (holdflags & T_HPCL) {
374: /*
375: * Hangup port
376: */
377: s = sphi();
378: outb(b+MCR, inb(b+MCR)&MC_OUT2);
379: spl(s);
380:
381: /*
382: * Hold dtr low for timeout
383: */
384: maj = major(dev);
385: drvl[maj].d_time = 1;
386: sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
387: drvl[maj].d_time = 0;
388: }
389: s = sphi();
390: outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
391: spl(s);
392: com_usage[AL_NUM] = COM_UNUSED;
393: set_poll_rate();
394: AL_H_CLOSE = 0; /* allow reopen - done closing */
395: wakeup((char *)&AL_H_CLOSE);
396: CDUMP("closed")
397: }
398:
399: /*
400: * Common c_timer routine for async ports.
401: */
402: alxtimer(dev)
403: dev_t dev;
404: {
405: if (++drvl[major(dev)].d_time > DTRTMOUT)
406: wakeup((char *)&drvl[major(dev)].d_time);
407: }
408:
409:
410: /*
411: * Common c_ioctl routine for async ports.
412: */
413: alxioctl(dev, com, vec, tp)
414: dev_t dev;
415: struct sgttyb *vec;
416: register TTY *tp;
417: {
418: register int s, b;
419: int stat1, stat2;
420: unsigned char msr;
421: unsigned char ier_save;
422:
423: s = sphi();
424: b = ALPORT;
425: ier_save=inb(b+IER);
426: stat1 = inb(b+MCR); /* get current MCR register status */
427: stat2 = inb(b+LCR); /* get current LCR register status */
428:
429: switch(com) {
430: case TIOCSBRK: /* set BREAK */
431: outb(b+LCR, stat2|LC_SBRK);
432: break;
433: case TIOCCBRK: /* clear BREAK */
434: outb(b+LCR, stat2 & ~LC_SBRK);
435: break;
436: case TIOCSDTR: /* set DTR */
437: outb(b+MCR, stat1|MC_DTR);
438: break;
439: case TIOCCDTR: /* clear DTR */
440: outb(b+MCR, stat1 & ~MC_DTR);
441: break;
442: case TIOCSRTS: /* set RTS */
443: outb(b+MCR, stat1|MC_RTS);
444: break;
445: case TIOCCRTS: /* clear RTS */
446: outb(b+MCR, stat1 & ~MC_RTS);
447: break;
448: case TIOCRSPEED: /* set "raw" I/O speed divisor */
449: outb(b+LCR, stat2|LC_DLAB); /* set speed latch bit */
450: outb(b+DLL, (unsigned) vec);
451: outb(b+DLH, (unsigned) vec >> 8);
452: outb(b+LCR, stat2); /* reset latch bit */
453: break;
454: case TIOCWORDL: /* set word length and stop bits */
455: outb(b+LCR, ((stat2&~0x7) | ((unsigned) vec & 0x7)));
456: break;
457: case TIOCRMSR: /* get CTS/DSR/RI/RLSD (MSR) */
458: msr = inb(b+MSR);
459: AL_MSR_DELTAS |= msr;
460: stat1 = msr >> 4;
461: kucopy(&stat1, (unsigned *) vec, sizeof(unsigned));
462: break;
463: default:
464: ttioctl(tp, com, vec);
465: }
466: outb(b+IER, ier_save);
467: spl(s);
468: }
469:
470: alxparam(tp)
471: TTY *tp;
472: {
473: register int b;
474: register int baud;
475: int s;
476:
477: b = ALPORT;
478:
479: /*
480: * error if input speed not the same as output speed
481: */
482: if (tp->t_sgttyb.sg_ispeed!=tp->t_sgttyb.sg_ospeed) {
483: u.u_error = ENODEV;
484: return;
485: }
486:
487: if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) {
488: if (tp->t_flags & T_MODC) { /* modem control? */
489: tp->t_flags &= ~T_CARR; /* indicate no carrier */
490: s = sphi();
491: outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
492: spl(s);
493: }
494: }
495:
496: if (baud) {
497: unsigned char ier_save;
498:
499: s=sphi();
500: ier_save=inb(b+IER); /* some chips need this */
501: outb(b+LCR, LC_DLAB);
502: outb(b+DLL, baud);
503: outb(b+DLH, baud >> 8);
504: switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
505: case EVENP:
506: outb(b+LCR, LC_CS7 + LC_PARENB + LC_PAREVEN);
507: break;
508:
509: case ODDP:
510: outb(b+LCR, LC_CS7 + LC_PARENB);
511: break;
512:
513: default:
514: outb(b+LCR, LC_CS8);
515: break;
516: }
517: outb(b+IER, ier_save);
518: spl(s);
519: }
520: set_poll_rate();
521: }
522:
523: /*
524: * Middle level processor.
525: *
526: * Invoked 10 times per second.
527: * Checks modem status for loss of carrier.
528: * Tranfers rawin buffer [from intr level] to canonical input queue.
529: * Transfers output queue to rawout buffer [for intr level].
530: */
531: alxcycle(tp)
532: register TTY * tp;
533: {
534: register int b;
535: register int n;
536: unsigned char msr, mcr;
537: int s;
538:
539: /*
540: * Check modem status every ten clock ticks.
541: *
542: * Modem status interrupts were not enabled due to 8250 hardware bug.
543: * Enabling modem status and receive interrupts may cause lockup
544: * on older parts.
545: *
546: * Also check if input silo is nearly full in case we need RTS
547: * flow control.
548: */
549: if (tp->t_flags & T_MODC) {
550:
551: /*
552: * Get status
553: */
554: msr = inb(ALPORT+MSR);
555: AL_MSR_DELTAS |= msr;
556:
557: /*
558: * Carrier changed.
559: */
560: if (AL_MSR_DELTAS & MS_DRLSD) {
561: AL_MSR_DELTAS &= ~MS_DRLSD;
562: /*
563: * wakeup open
564: */
565: if (tp->t_open == 0) {
566: wakeup((char *)(&tp->t_open));
567: }
568:
569: /*
570: * carrier off?
571: */
572: else if ((msr & MS_RLSD) == 0) {
573: /*
574: * clear carrier flag; send hangup signal
575: */
576: s = sphi();
577: tp->t_rawin.si_ox = tp->t_rawin.si_ix;
578: tp->t_rawin.SILO_CHAR_COUNT = 0;
579: spl(s);
580: tthup(tp);
581: }
582: }
583:
584: /*
585: * CTS changed.
586: */
587: if (AL_MSR_DELTAS & MS_DCTS) {
588: AL_MSR_DELTAS &= ~MS_DCTS;
589: if (msr & MS_CTS)
590: tp->t_flags &= ~T_STOP;
591: else
592: tp->t_flags |= T_STOP;
593: }
594:
595: /*
596: * If input silo not nearly full, assert RTS.
597: */
598: if (tp->t_rawin.SILO_CHAR_COUNT <= SILO_HIGH_MARK) {
599: mcr = inb(ALPORT+MCR);
600: if ((mcr & MC_RTS) == 0) {
601: printf("%x RTS ON\n", ALPORT);
602: outb(ALPORT+MCR, mcr | MC_RTS);
603: }
604: }
605: }
606:
607: /*
608: * Empty raw input buffer.
609: * If modem control enabled and tt input queue is at high limit
610: * (e.g., tp->t_iq.cq_cc >= IHILIM), don't copy from rawin silo
611: * to tt input queue.
612: */
613: if (!(tp->t_flags & T_MODC) || !(tp->t_flags & T_ISTOP))
614: while (tp->t_rawin.SILO_CHAR_COUNT > 0) {
615: ttin(tp, tp->t_rawin.si_buf[tp->t_rawin.si_ox]);
616: if (tp->t_rawin.si_ox < MAX_SILO_INDEX)
617: tp->t_rawin.si_ox++;
618: else
619: tp->t_rawin.si_ox = 0;
620: tp->t_rawin.SILO_CHAR_COUNT--;
621: }
622:
623: /*
624: * Calculate free output slot count.
625: */
626: n = sizeof(tp->t_rawout.si_buf) - 1;
627: n += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
628: n %= sizeof(tp->t_rawout.si_buf);
629:
630: /*
631: * Fill raw output buffer.
632: */
633: while ((--n >= 0) && ((b = ttout(tp)) >= 0)) {
634: tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = b;
635: if (tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1)
636: tp->t_rawout.si_ix = 0;
637: else
638: tp->t_rawout.si_ix++;
639: }
640:
641: /*
642: * (Re)start output, wake sleeping processes, etc.
643: */
644: ttstart(tp);
645:
646: /*
647: * Schedule next cycle.
648: */
649: timeout(&tp->t_rawtim, HZ/10, alxcycle, tp);
650: }
651:
652: /*
653: * Serial Transmit Start Routine.
654: */
655: alxstart(tp)
656: register TTY * tp;
657: {
658: register int b;
659: register int s;
660: extern alxbreak();
661:
662: /*
663: * Read line status register AFTER disabling interrupts.
664: */
665: s = sphi();
666: b = inb(ALPORT+LSR);
667:
668: /*
669: * Process break indication.
670: * NOTE: Break indication cleared when line status register was read.
671: */
672: if (b & LS_BREAK)
673: defer(alxbreak, tp);
674:
675: /*
676: * Transmitter is empty, output data is pending.
677: */
678: if ((b & LS_TxRDY) && (tp->t_rawout.si_ix != tp->t_rawout.si_ox)) {
679: outb( ALPORT+DREG,
680: tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);
681: if (++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf))
682: tp->t_rawout.si_ox = 0;
683: }
684: spl(s);
685: }
686:
687: /*
688: * Serial Received Break Handler.
689: */
690: alxbreak(tp)
691: TTY * tp;
692: {
693: ttsignal(tp, SIGINT);
694: }
695:
696: /*
697: * Serial Interrupt Handler.
698: */
699: alxintr(tp)
700: register TTY * tp;
701: {
702: register int b;
703: int port = ALPORT;
704: unsigned char mcr;
705:
706: rescan:
707: switch (inb(port+IIR)) {
708:
709: case LS_INTR:
710: if (inb(port+LSR) & LS_BREAK)
711: defer(alxbreak, tp);
712: goto rescan;
713:
714: case Rx_INTR:
715: b = inb(port+DREG);
716: if (tp->t_open == 0)
717: goto rescan;
718: /*
719: * Must recognize XOFF quickly to avoid transmit overrun.
720: * Recognize XON here as well to avoid race conditions.
721: */
722: if ((tp->t_sgttyb.sg_flags & RAWIN) == 0) {
723: /*
724: * XOFF.
725: */
726: if (tp->t_tchars.t_stopc == (b & 0177)) {
727: tp->t_flags |= T_STOP;
728: goto rescan;
729: }
730:
731: /*
732: * XON.
733: */
734: if (tp->t_tchars.t_startc == (b & 0177)) {
735: tp->t_flags &= ~T_STOP;
736: goto rescan;
737: }
738: }
739:
740: /*
741: * Save char in raw input buffer.
742: */
743: if (tp->t_rawin.SILO_CHAR_COUNT < MAX_SILO_CHARS) {
744: tp->t_rawin.si_buf[tp->t_rawin.si_ix] = b;
745: if (tp->t_rawin.si_ix < MAX_SILO_INDEX)
746: tp->t_rawin.si_ix++;
747: else
748: tp->t_rawin.si_ix = 0;
749: tp->t_rawin.SILO_CHAR_COUNT++;
750: }
751: if (tp->t_flags & T_MODC)
752: if ((tp->t_flags & T_ISTOP)
753: || (tp->t_rawin.SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
754: mcr = inb(port+MCR);
755: if (mcr & MC_RTS) {
756: outb(port+MCR, mcr & ~MC_RTS);
757: printf("%x RTS OFF\n", port);
758: }
759: }
760: goto rescan;
761:
762: case Tx_INTR:
763: /*
764: * Do nothing if no raw output data or output is stopped.
765: */
766: if (tp->t_rawout.si_ix == tp->t_rawout.si_ox) {
767: goto rescan;
768: }
769: if (tp->t_flags & T_STOP)
770: goto rescan;
771:
772: /*
773: * Transmit next char in raw output buffer.
774: */
775: outb(port+DREG,
776: tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);
777:
778: /*
779: * Adjust raw output buffer output index.
780: */
781: if (++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf))
782: tp->t_rawout.si_ox = 0;
783:
784: /*
785: * Try to fill buffer if now empty.
786: */
787: if (tp->t_rawout.si_ox == tp->t_rawout.si_ix) {
788: defer(alxcycle, tp);
789: }
790: goto rescan;
791:
792: case MS_INTR:
793: AL_MSR_DELTAS |= inb(port+MSR);
794: defer(alxcycle, tp);
795: goto rescan;
796: }
797: }
798:
799: /*
800: * alxclk will be called every time T0 interrupts - if it returns 0,
801: * the usual system timer interrupt stuff is done
802: */
803: static int alxclk()
804: {
805: static int count;
806: int i;
807:
808: for (i = 0; i < NUM_AL_PORTS; i++)
809: if (com_usage[i] == COM_POLLED)
810: alxintr(tp_table[i]);
811: count++;
812: if (count >= poll_divisor)
813: count = 0;
814: return count;
815: }
816:
817: /*
818: * set_poll_rate is called when a port is opened or closed or changes speed
819: * it sets the polling rate only as fast as needed, and shuts off polling
820: * whenever possible
821: */
822: static set_poll_rate()
823: {
824: int port_num, max_rate, port_rate;
825:
826: /*
827: * If another driver has the polling clock, do nothing.
828: */
829: if (poll_owner & ~ POLL_AL)
830: return;
831:
832: /*
833: * find highest valid polling rate in units of HZ/10
834: */
835: max_rate = 0;
836: for (port_num = 0; port_num < NUM_AL_PORTS; port_num++) {
837: if (com_usage[port_num] == COM_POLLED) {
838: port_rate = alp_rate[(tp_table[port_num])->t_sgttyb.sg_ispeed];
839: if (max_rate < port_rate)
840: max_rate = port_rate;
841: }
842: }
843: /*
844: * if max_rate is not current rate, adjust the system clock
845: */
846: if (max_rate != poll_rate) {
847: poll_rate = max_rate;
848: poll_divisor = poll_rate/HZ; /* used in alxclk() */
849: altclk_out(); /* stop previous polling */
850: poll_owner &= ~ POLL_AL;
851: if (max_rate) { /* resume polling at new rate if needed */
852: poll_owner |= POLL_AL;
853: altclk_in(poll_rate, alxclk);
854: }
855: CDUMP("new rate")
856: }
857: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.