|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)ser.c 7.12 (Berkeley) 6/27/91
34: */
35:
36: #include "ser.h"
37:
38: #if NSER > 0
39: #include "sys/param.h"
40: #include "sys/systm.h"
41: #include "sys/ioctl.h"
42: #include "sys/tty.h"
43: #include "sys/proc.h"
44: #include "sys/conf.h"
45: #include "sys/file.h"
46: #include "sys/malloc.h"
47: #include "sys/uio.h"
48: #include "sys/kernel.h"
49: #include "sys/syslog.h"
50:
51: #include "device.h"
52: #include "serreg.h"
53: #include "machine/cpu.h"
54:
55: #include "../amiga/custom.h"
56: #include "../amiga/cia.h"
57:
58: int serprobe();
59: struct driver serdriver = {
60: serprobe, "ser",
61: };
62:
63: int serstart(), serparam(), serintr();
64: int sersoftCAR;
65: int ser_active;
66: int ser_hasfifo;
67: int nser = NSER;
68: #ifdef SERCONSOLE
69: int serconsole = SERCONSOLE;
70: #else
71: int serconsole = -1;
72: #endif
73: int serconsinit;
74: int serdefaultrate = TTYDEF_SPEED;
75: int sermajor;
76: struct serdevice *ser_addr[NSER];
77: struct tty ser_cons;
78: struct tty *ser_tty[NSER] = { &ser_cons };
79:
80: struct speedtab serspeedtab[] = {
81: 0, 0,
82: 50, SERBRD(50),
83: 75, SERBRD(75),
84: 110, SERBRD(110),
85: 134, SERBRD(134),
86: 150, SERBRD(150),
87: 200, SERBRD(200),
88: 300, SERBRD(300),
89: 600, SERBRD(600),
90: 1200, SERBRD(1200),
91: 1800, SERBRD(1800),
92: 2400, SERBRD(2400),
93: 4800, SERBRD(4800),
94: 9600, SERBRD(9600),
95: 19200, SERBRD(19200),
96: 38400, SERBRD(38400),
97: -1, -1
98: };
99:
100:
101: /* since this UART is not particularly bright (nice put), we'll have to do
102: parity stuff on our own. this table contains the 8th bit in 7bit character
103: mode, for even parity. If you want odd parity, flip the bit. (for
104: generation of the table, see genpar.c) */
105:
106: u_char even_parity[] = {
107: 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
108: 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
109: 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
110: 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
111: 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
112: 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
113: 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
114: 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
115: };
116:
117:
118: /* since we don't get interrupts for changes on the modem control line,
119: well have to fake them by comparing current settings to the settings
120: we remembered on last invocation. */
121: u_char last_ciab_pra;
122:
123: extern struct tty *constty;
124: #ifdef KGDB
125: #include "machine/remote-sl.h"
126:
127: extern dev_t kgdb_dev;
128: extern int kgdb_rate;
129: extern int kgdb_debug_init;
130: #endif
131:
132: #if 0
133: #define UNIT(x) minor(x)
134: #else
135: /* just always force this to 0, so we can later interprete special
136: settings out of the unit number.. */
137: #define UNIT(x) 0
138: #endif
139:
140: #ifdef DEBUG
141: long fifoin[17];
142: long fifoout[17];
143: long serintrcount[16];
144: long sermintcount[16];
145: #endif
146:
147: serprobe(ad)
148: register struct amiga_device *ad;
149: {
150: register struct serdevice *ser;
151: register int unit;
152:
153: ser = (struct serdevice *) ad->amiga_addr;
154: unit = ad->amiga_unit;
155: if (unit == serconsole)
156: DELAY(100000);
157:
158: ad->amiga_ipl = 2;
159: ser_addr[unit] = ser;
160: ser_active |= 1 << unit;
161: sersoftCAR = ad->amiga_flags;
162: #ifdef KGDB
163: if (kgdb_dev == makedev(sermajor, unit)) {
164: if (serconsole == unit)
165: kgdb_dev = NODEV; /* can't debug over console port */
166: else {
167: (void) serinit(unit, kgdb_rate);
168: serconsinit = 1; /* don't re-init in serputc */
169: if (kgdb_debug_init) {
170: /*
171: * Print prefix of device name,
172: * let kgdb_connect print the rest.
173: */
174: printf("ser%d: ", unit);
175: kgdb_connect(1);
176: } else
177: printf("ser%d: kgdb enabled\n", unit);
178: }
179: }
180: #endif
181: /*
182: * Need to reset baud rate, etc. of next print so reset serconsinit.
183: * Also make sure console is always "hardwired."
184: */
185: if (unit == serconsole) {
186: serconsinit = 0;
187: sersoftCAR |= (1 << unit);
188: }
189: return (1);
190: }
191:
192: /* ARGSUSED */
193: #ifdef __STDC__
194: seropen(dev_t dev, int flag, int mode, struct proc *p)
195: #else
196: seropen(dev, flag, mode, p)
197: dev_t dev;
198: int flag, mode;
199: struct proc *p;
200: #endif
201: {
202: register struct tty *tp;
203: register int unit;
204: int error = 0;
205:
206: unit = minor (dev);
207:
208: if (unit == 1)
209: {
210: unit = 0;
211: sersoftCAR = 0;
212: }
213: else if (unit == 2)
214: {
215: unit = 0;
216: sersoftCAR = 0xff;
217: }
218: else
219: unit = 0;
220:
221: if (unit >= NSER || (ser_active & (1 << unit)) == 0)
222: return (ENXIO);
223: if(!ser_tty[unit]) {
224: MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK);
225: bzero(tp, sizeof(struct tty));
226: ser_tty[unit] = tp;
227: } else
228: tp = ser_tty[unit];
229: tp->t_oproc = serstart;
230: tp->t_param = serparam;
231: tp->t_dev = dev;
232: if ((tp->t_state & TS_ISOPEN) == 0) {
233: tp->t_state |= TS_WOPEN;
234: ttychars(tp);
235: if (tp->t_ispeed == 0) {
236: tp->t_iflag = TTYDEF_IFLAG | IXOFF; /* XXXXX */
237: tp->t_oflag = TTYDEF_OFLAG;
238: #if 0
239: tp->t_cflag = TTYDEF_CFLAG;
240: #else
241: tp->t_cflag = (CREAD | CS8 | CLOCAL); /* XXXXX */
242: #endif
243: tp->t_lflag = TTYDEF_LFLAG;
244: tp->t_ispeed = tp->t_ospeed = serdefaultrate;
245: }
246: serparam(tp, &tp->t_termios);
247: ttsetwater(tp);
248: } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
249: return (EBUSY);
250: (void) sermctl (dev, TIOCM_DTR | TIOCM_RTS, DMSET);
251: if ((sersoftCAR & (1 << unit)) || (sermctl(dev, 0, DMGET) & TIOCM_CD))
252: tp->t_state |= TS_CARR_ON;
253: (void) spltty();
254: while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
255: (tp->t_state & TS_CARR_ON) == 0) {
256: tp->t_state |= TS_WOPEN;
257: if (error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH,
258: ttopen, 0))
259: break;
260: }
261: (void) spl0();
262: if (error == 0)
263: error = (*linesw[tp->t_line].l_open)(dev, tp);
264: return (error);
265: }
266:
267: /*ARGSUSED*/
268: serclose(dev, flag, mode, p)
269: dev_t dev;
270: int flag, mode;
271: struct proc *p;
272: {
273: register struct tty *tp;
274: register struct serdevice *ser;
275: register int unit;
276:
277: unit = UNIT(dev);
278:
279: ser = ser_addr[unit];
280: tp = ser_tty[unit];
281: (*linesw[tp->t_line].l_close)(tp, flag);
282: custom.adkcon = ADKCONF_UARTBRK; /* clear break */
283: #ifdef KGDB
284: /* do not disable interrupts if debugging */
285: if (dev != kgdb_dev)
286: #endif
287: custom.intena = INTF_RBF | INTF_VERTB; /* clear interrupt enable */
288: custom.intreq = INTF_RBF | INTF_VERTB; /* and interrupt request */
289: #if 0
290: /* if the device is closed, it's close, no matter whether we deal with modem
291: control signals nor not. */
292: if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
293: (tp->t_state&TS_ISOPEN) == 0)
294: #endif
295: (void) sermctl(dev, 0, DMSET);
296: ttyclose(tp);
297: #if 0
298: if (tp != &ser_cons)
299: {
300: FREE(tp, M_TTYS);
301: ser_tty[unit] = (struct tty *)NULL;
302: }
303: #endif
304: return (0);
305: }
306:
307: serread(dev, uio, flag)
308: dev_t dev;
309: struct uio *uio;
310: {
311: register struct tty *tp = ser_tty[UNIT(dev)];
312: int error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
313:
314: return error;
315: }
316:
317: serwrite(dev, uio, flag)
318: dev_t dev;
319: struct uio *uio;
320: {
321: int unit = UNIT(dev);
322: register struct tty *tp = ser_tty[unit];
323:
324: /*
325: * (XXX) We disallow virtual consoles if the physical console is
326: * a serial port. This is in case there is a display attached that
327: * is not the console. In that situation we don't need/want the X
328: * server taking over the console.
329: */
330: if (constty && unit == serconsole)
331: constty = NULL;
332: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
333: }
334:
335: serintr(unit)
336: register int unit;
337: {
338: register struct serdevice *ser;
339: register u_short code;
340: register u_char ch;
341: register u_short ints;
342: register struct tty *tp;
343:
344: ser = ser_addr[unit];
345:
346: again:
347: ints = custom.intreqr & INTF_RBF;
348: if (! ints)
349: return 0;
350:
351: /* clear interrupt(s) */
352: custom.intreq = ints;
353:
354: /* this register contains both data and status bits! */
355: code = custom.serdatr;
356:
357: if (ints & INTF_RBF)
358: {
359: tp = ser_tty[unit];
360: /*
361: * Process a received byte. Inline for speed...
362: */
363: #ifdef KGDB
364: #define RCVBYTE() \
365: ch = code & 0xff; \
366: if ((tp->t_state & TS_ISOPEN) == 0) { \
367: if (ch == FRAME_END && \
368: kgdb_dev == makedev(sermajor, unit)) \
369: kgdb_connect(0); /* trap into kgdb */ \
370: }
371: #else
372: #define RCVBYTE()
373: #endif
374: RCVBYTE();
375: /* sereint does the receive-processing */
376: sereint (unit, code, ser);
377: }
378:
379: /* fake modem-control interrupt */
380: sermint (unit, ser);
381: /* try to save interrupt load.. */
382: goto again;
383: }
384:
385: sereint(unit, stat, ser)
386: register int unit, stat;
387: register struct serdevice *ser;
388: {
389: register struct tty *tp;
390: register int c;
391: register u_char ch;
392:
393: tp = ser_tty[unit];
394: if ((tp->t_state & TS_ISOPEN) == 0) {
395: #ifdef KGDB
396: /* we don't care about parity errors */
397: if (kgdb_dev == makedev(sermajor, unit) && c == FRAME_END)
398: kgdb_connect(0); /* trap into kgdb */
399: #endif
400: return;
401: }
402: ch = stat & 0xff;
403: c = ch;
404: /* all databits 0 including stop indicate break condition */
405: if (!(stat & 0x1ff))
406: c |= TTY_FE;
407:
408: /* if parity checking enabled, check parity */
409: else if ((tp->t_cflag & PARENB) &&
410: (((ch >> 7) + even_parity[ch & 0x7f] + !!(tp->t_cflag & PARODD)) & 1))
411: c |= TTY_PE;
412:
413: if (stat & SERDATRF_OVRUN)
414: log(LOG_WARNING, "ser%d: silo overflow\n", unit);
415:
416: (*linesw[tp->t_line].l_rint)(c, tp);
417: }
418:
419: sermint(unit)
420: register int unit;
421: {
422: register struct tty *tp;
423: register u_char stat, last, istat;
424: register struct serdevice *ser;
425:
426: tp = ser_tty[unit];
427: stat = ciab.pra;
428: last = last_ciab_pra;
429: last_ciab_pra = stat;
430:
431: /* check whether any interesting signal changed state */
432: istat = stat ^ last;
433:
434: if ((istat & CIAB_PRA_CD) && (sersoftCAR & (1 << unit)) == 0)
435: {
436: if (ISDCD (stat))
437: (*linesw[tp->t_line].l_modem)(tp, 1);
438: else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
439: {
440: CLRDTR (stat);
441: CLRRTS (stat);
442: ciab.pra = stat;
443: last_ciab_pra = stat;
444: }
445: }
446: else if ((istat & CIAB_PRA_CTS) && (tp->t_state & TS_ISOPEN) &&
447: (tp->t_flags & CRTSCTS))
448: {
449: /* the line is up and we want to do rts/cts flow control */
450: if (ISCTS (stat))
451: {
452: tp->t_state &=~ TS_TTSTOP;
453: ttstart(tp);
454: }
455: else
456: tp->t_state |= TS_TTSTOP;
457: }
458: }
459:
460: serioctl(dev, cmd, data, flag)
461: dev_t dev;
462: caddr_t data;
463: {
464: register struct tty *tp;
465: register int unit = UNIT(dev);
466: register struct serdevice *ser;
467: register int error;
468:
469: tp = ser_tty[unit];
470: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
471: if (error >= 0)
472: return (error);
473: error = ttioctl(tp, cmd, data, flag);
474: if (error >= 0)
475: return (error);
476:
477: ser = ser_addr[unit];
478: switch (cmd) {
479:
480: case TIOCSBRK:
481: custom.adkcon = ADKCONF_SETCLR | ADKCONF_UARTBRK;
482: break;
483:
484: case TIOCCBRK:
485: custom.adkcon = ADKCONF_UARTBRK;
486: break;
487:
488: case TIOCSDTR:
489: (void) sermctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
490: break;
491:
492: case TIOCCDTR:
493: (void) sermctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
494: break;
495:
496: case TIOCMSET:
497: (void) sermctl(dev, *(int *)data, DMSET);
498: break;
499:
500: case TIOCMBIS:
501: (void) sermctl(dev, *(int *)data, DMBIS);
502: break;
503:
504: case TIOCMBIC:
505: (void) sermctl(dev, *(int *)data, DMBIC);
506: break;
507:
508: case TIOCMGET:
509: *(int *)data = sermctl(dev, 0, DMGET);
510: break;
511:
512: default:
513: return (ENOTTY);
514: }
515: return (0);
516: }
517:
518: serparam(tp, t)
519: register struct tty *tp;
520: register struct termios *t;
521: {
522: register struct serdevice *ser;
523: register int cfcr, cflag = t->c_cflag;
524: int unit = UNIT(tp->t_dev);
525: int ospeed = ttspeedtab(t->c_ospeed, serspeedtab);
526:
527: /* check requested parameters */
528: if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
529: return (EINVAL);
530: /* and copy to tty */
531: tp->t_ispeed = t->c_ispeed;
532: tp->t_ospeed = t->c_ospeed;
533: tp->t_cflag = cflag;
534:
535: custom.intena = INTF_SETCLR | INTF_RBF;
536: custom.intreq = INTF_RBF;
537: last_ciab_pra = ciab.pra;
538:
539: if (ospeed == 0) {
540: (void) sermctl(unit, 0, DMSET); /* hang up line */
541: return (0);
542: }
543: /* set the baud rate */
544: custom.serper = (0<<15) | ospeed; /* select 8 bit mode (instead of 9 bit) */
545:
546: return (0);
547: }
548:
549: serstart(tp)
550: register struct tty *tp;
551: {
552: register struct serdevice *ser;
553: int s, unit;
554: u_short c;
555:
556: unit = UNIT(tp->t_dev);
557: ser = ser_addr[unit];
558: s = spltty();
559: again:
560: if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
561: goto out;
562: if (RB_LEN(&tp->t_out) <= tp->t_lowat) {
563: if (tp->t_state&TS_ASLEEP) {
564: tp->t_state &= ~TS_ASLEEP;
565: wakeup((caddr_t)&tp->t_out);
566: }
567: selwakeup (&tp->t_wsel);
568: }
569: if (RB_LEN(&tp->t_out) == 0)
570: goto out;
571:
572: while (! (custom.serdatr & SERDATRF_TBE)) ;
573:
574: c = rbgetc(&tp->t_out);
575: /* tp->t_state |= TS_BUSY; */
576:
577: /* handle truncation of character if necessary */
578: if ((tp->t_cflag & CSIZE) == CS7)
579: c &= 0x7f;
580:
581: /* handle parity if necessary (forces CS7) */
582: if (tp->t_cflag & PARENB)
583: {
584: if (even_parity[c & 0x7f])
585: c |= 0x80;
586: if (tp->t_cflag & PARODD)
587: c ^= 0x80;
588: }
589:
590: /* add stop bit(s) */
591: if (tp->t_cflag & CSTOPB)
592: c |= 0x300;
593: else
594: c |= 0x100;
595:
596: custom.serdat = c;
597:
598: /* if there's input on the line, stop spitting out characters */
599: if (! (custom.intreqr & INTF_RBF))
600: goto again;
601:
602: out:
603: splx(s);
604: }
605:
606: /*
607: * Stop output on a line.
608: */
609: /*ARGSUSED*/
610: serstop(tp, flag)
611: register struct tty *tp;
612: {
613: register int s;
614:
615: s = spltty();
616: if (tp->t_state & TS_BUSY) {
617: if ((tp->t_state&TS_TTSTOP)==0)
618: tp->t_state |= TS_FLUSH;
619: }
620: splx(s);
621: }
622:
623: sermctl(dev, bits, how)
624: dev_t dev;
625: int bits, how;
626: {
627: register struct serdevice *ser;
628: register int unit;
629: u_char ub;
630: int s;
631:
632: unit = UNIT(dev);
633: ser = ser_addr[unit];
634:
635: /* convert TIOCM* mask into CIA mask (which is really low-active!!) */
636: if (how != DMGET)
637: {
638: ub = 0;
639: if (bits & TIOCM_DTR) ub |= CIAB_PRA_DTR;
640: if (bits & TIOCM_RTS) ub |= CIAB_PRA_RTS;
641: if (bits & TIOCM_CTS) ub |= CIAB_PRA_CTS;
642: if (bits & TIOCM_CD) ub |= CIAB_PRA_CD;
643: if (bits & TIOCM_RI) ub |= CIAB_PRA_SEL; /* collision with /dev/par ! */
644: if (bits & TIOCM_DSR) ub |= CIAB_PRA_DSR;
645: }
646:
647:
648: s = spltty();
649: switch (how) {
650:
651: case DMSET:
652: /* invert and set */
653: ciab.pra = ~ub;
654: break;
655:
656: case DMBIC:
657: ciab.pra |= ub;
658: ub = ~ciab.pra;
659: break;
660:
661: case DMBIS:
662: ciab.pra &= ~ub;
663: ub = ~ciab.pra;
664: break;
665:
666: case DMGET:
667: ub = ~ciab.pra;
668: break;
669: }
670: (void) splx(s);
671:
672: bits = 0;
673: if (ub & CIAB_PRA_DTR) bits |= TIOCM_DTR;
674: if (ub & CIAB_PRA_RTS) bits |= TIOCM_RTS;
675: if (ub & CIAB_PRA_CTS) bits |= TIOCM_CTS;
676: if (ub & CIAB_PRA_CD) bits |= TIOCM_CD;
677: if (ub & CIAB_PRA_SEL) bits |= TIOCM_RI;
678: if (ub & CIAB_PRA_DSR) bits |= TIOCM_DSR;
679:
680: return bits;
681: }
682:
683: /*
684: * Following are all routines needed for SER to act as console
685: */
686: #include "../amiga/cons.h"
687:
688: sercnprobe(cp)
689: struct consdev *cp;
690: {
691: int unit = CONUNIT;
692:
693: /* locate the major number */
694: for (sermajor = 0; sermajor < nchrdev; sermajor++)
695: if (cdevsw[sermajor].d_open == seropen)
696: break;
697:
698: /* XXX: ick */
699: unit = CONUNIT;
700:
701: /* initialize required fields */
702: cp->cn_dev = makedev(sermajor, unit);
703: cp->cn_tp = ser_tty[unit];
704: cp->cn_pri = CN_NORMAL;
705:
706: /*
707: * If serconsole is initialized, raise our priority.
708: */
709: if (serconsole == unit)
710: cp->cn_pri = CN_REMOTE;
711: #ifdef KGDB
712: if (major(kgdb_dev) == 1) /* XXX */
713: kgdb_dev = makedev(sermajor, minor(kgdb_dev));
714: #endif
715: }
716:
717: sercninit(cp)
718: struct consdev *cp;
719: {
720: int unit = UNIT(cp->cn_dev);
721:
722: serinit(unit, serdefaultrate);
723: serconsole = unit;
724: serconsinit = 1;
725: }
726:
727: serinit(unit, rate)
728: int unit, rate;
729: {
730: int s;
731:
732: #ifdef lint
733: stat = unit; if (stat) return;
734: #endif
735: s = splhigh();
736: /* might want to fiddle with the CIA later ??? */
737: custom.serper = ttspeedtab(rate, serspeedtab);
738: splx(s);
739: }
740:
741: sercngetc(dev)
742: {
743: u_short stat;
744: int c, s;
745:
746: #ifdef lint
747: stat = dev; if (stat) return (0);
748: #endif
749: s = splhigh();
750: while (!((stat = custom.serdatr & 0xffff) & SERDATRF_RBF))
751: ;
752: c = stat & 0xff;
753: /* clear interrupt */
754: custom.intreq = INTF_RBF;
755: splx(s);
756: return (c);
757: }
758:
759: /*
760: * Console kernel output character routine.
761: */
762: sercnputc(dev, c)
763: dev_t dev;
764: register int c;
765: {
766: register int timo;
767: short stat;
768: int s = splhigh();
769:
770: #ifdef lint
771: stat = dev; if (stat) return;
772: #endif
773: if (serconsinit == 0) {
774: (void) serinit(UNIT(dev), serdefaultrate);
775: serconsinit = 1;
776: }
777: /* wait for any pending transmission to finish */
778: timo = 50000;
779: while (! (custom.serdatr & SERDATRF_TBE) && --timo)
780: ;
781: custom.serdat = (c&0xff) | 0x100;
782: /* wait for this transmission to complete */
783: timo = 1500000;
784: while (! (custom.serdatr & SERDATRF_TBE) && --timo)
785: ;
786: /* wait for the device (my vt100..) to process the data, since
787: we don't do flow-control with cnputc */
788: for (timo = 0; timo < 30000; timo++) ;
789:
790: /* clear any interrupts generated by this transmission */
791: custom.intreq = INTF_TBE;
792: splx(s);
793: }
794:
795:
796: serspit(c)
797: int c;
798: {
799: register struct Custom *cu asm("a2") = CUSTOMbase;
800: register int timo asm("d2");
801: extern int cold;
802: int s;
803:
804: if (c == 10)
805: serspit (13);
806:
807: s = splhigh();
808:
809: /* wait for any pending transmission to finish */
810: timo = 500000;
811: while (! (cu->serdatr & (SERDATRF_TBE|SERDATRF_TSRE)) && --timo)
812: ;
813: cu->serdat = (c&0xff) | 0x100;
814: /* wait for this transmission to complete */
815: timo = 15000000;
816: while (! (cu->serdatr & SERDATRF_TBE) && --timo)
817: ;
818: /* clear any interrupts generated by this transmission */
819: cu->intreq = INTF_TBE;
820:
821: for (timo = 0; timo < 30000; timo++) ;
822:
823: splx (s);
824: }
825:
826: int
827: serselect(dev, rw, p)
828: dev_t dev;
829: int rw;
830: struct proc *p;
831: {
832: register struct tty *tp = ser_tty[UNIT(dev)];
833: int nread;
834: int s = spltty();
835: struct proc *selp;
836:
837: switch (rw) {
838:
839: case FREAD:
840: nread = ttnread(tp);
841: if (nread > 0 ||
842: ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0))
843: goto win;
844: selrecord(p, &tp->t_rsel);
845: break;
846:
847: case FWRITE:
848: if (RB_LEN(&tp->t_out) <= tp->t_lowat)
849: goto win;
850: selrecord(p, &tp->t_wsel);
851: break;
852: }
853: splx(s);
854: return (0);
855: win:
856: splx(s);
857: return (1);
858: }
859:
860: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.