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