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