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