Annotation of sys/arch/sparc/dev/spif.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: spif.c,v 1.20 2006/06/02 20:00:54 miod Exp $ */
2:
3: /*
4: * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26: * POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: /*
30: * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board
31: * based heavily on Iain Hibbert's driver for the MAGMA cards
32: */
33:
34: #include <sys/param.h>
35: #include <sys/systm.h>
36: #include <sys/proc.h>
37: #include <sys/device.h>
38: #include <sys/kernel.h>
39: #include <sys/file.h>
40: #include <sys/errno.h>
41: #include <sys/ioctl.h>
42: #include <sys/mbuf.h>
43: #include <sys/socket.h>
44: #include <sys/syslog.h>
45: #include <sys/malloc.h>
46: #include <sys/tty.h>
47: #include <sys/conf.h>
48:
49: #include <machine/autoconf.h>
50: #include <sparc/cpu.h>
51: #include <sparc/sparc/cpuvar.h>
52: #include <sparc/dev/sbusvar.h>
53: #include <sparc/dev/spifreg.h>
54: #include <sparc/dev/spifvar.h>
55:
56: #if IPL_TTY == 1
57: # define IE_MSOFT IE_L1
58: #elif IPL_TTY == 4
59: # define IE_MSOFT IE_L4
60: #elif IPL_TTY == 6
61: # define IE_MSOFT IE_L6
62: #else
63: # error "no suitable software interrupt bit"
64: #endif
65:
66: int spifmatch(struct device *, void *, void *);
67: void spifattach(struct device *, struct device *, void *);
68:
69: int sttymatch(struct device *, void *, void *);
70: void sttyattach(struct device *, struct device *, void *);
71: int sttyopen(dev_t, int, int, struct proc *);
72: int sttyclose(dev_t, int, int, struct proc *);
73: int sttyread(dev_t, struct uio *, int);
74: int sttywrite(dev_t, struct uio *, int);
75: int sttyioctl(dev_t, u_long, caddr_t, int, struct proc *);
76: int sttystop(struct tty *, int);
77:
78: int spifstcintr(void *);
79: int spifstcintr_mx(struct spif_softc *, int *);
80: int spifstcintr_tx(struct spif_softc *, int *);
81: int spifstcintr_rx(struct spif_softc *, int *);
82: int spifstcintr_rxexception(struct spif_softc *, int *);
83: int spifsoftintr(void *);
84:
85: int stty_param(struct tty *, struct termios *);
86: struct tty *sttytty(dev_t);
87: int stty_modem_control(struct stty_port *, int, int);
88: static __inline void stty_write_ccr(struct stcregs *, u_int8_t);
89: int stty_compute_baud(speed_t, int, u_int8_t *, u_int8_t *);
90: void stty_start(struct tty *);
91:
92: int sbppmatch(struct device *, void *, void *);
93: void sbppattach(struct device *, struct device *, void *);
94: int sbppopen(dev_t, int, int, struct proc *);
95: int sbppclose(dev_t, int, int, struct proc *);
96: int sbppread(dev_t, struct uio *, int);
97: int sbppwrite(dev_t, struct uio *, int);
98: int sbpp_rw(dev_t, struct uio *);
99: int spifppcintr(void *);
100: int sbpppoll(dev_t, int, struct proc *);
101: int sbppioctl(dev_t, u_long, caddr_t, int, struct proc *);
102:
103: struct cfattach spif_ca = {
104: sizeof (struct spif_softc), spifmatch, spifattach
105: };
106:
107: struct cfdriver spif_cd = {
108: NULL, "spif", DV_DULL
109: };
110:
111: struct cfattach stty_ca = {
112: sizeof(struct stty_softc), sttymatch, sttyattach
113: };
114:
115: struct cfdriver stty_cd = {
116: NULL, "stty", DV_TTY
117: };
118:
119: struct cfattach sbpp_ca = {
120: sizeof(struct sbpp_softc), sbppmatch, sbppattach
121: };
122:
123: struct cfdriver sbpp_cd = {
124: NULL, "sbpp", DV_DULL
125: };
126:
127: int
128: spifmatch(parent, vcf, aux)
129: struct device *parent;
130: void *vcf, *aux;
131: {
132: struct cfdata *cf = vcf;
133: struct confargs *ca = aux;
134: register struct romaux *ra = &ca->ca_ra;
135:
136: if (strcmp(cf->cf_driver->cd_name, ra->ra_name) &&
137: strcmp("SUNW,spif", ra->ra_name))
138: return (0);
139: return (1);
140: }
141:
142: void
143: spifattach(parent, self, aux)
144: struct device *parent, *self;
145: void *aux;
146: {
147: struct spif_softc *sc = (struct spif_softc *)self;
148: struct confargs *ca = aux;
149: int stcpri, ppcpri;
150:
151: if (ca->ca_ra.ra_nintr != 2) {
152: printf(": expected 2 interrupts, got %d\n",
153: ca->ca_ra.ra_nintr);
154: return;
155: }
156: stcpri = ca->ca_ra.ra_intr[SERIAL_INTR].int_pri;
157: ppcpri = ca->ca_ra.ra_intr[PARALLEL_INTR].int_pri;
158:
159: if (ca->ca_ra.ra_nreg != 1) {
160: printf(": expected %d registers, got %d\n",
161: 1, ca->ca_ra.ra_nreg);
162: return;
163: }
164: sc->sc_regs = mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len);
165:
166: sc->sc_node = ca->ca_ra.ra_node;
167:
168: sc->sc_rev = getpropint(sc->sc_node, "revlev", 0);
169:
170: sc->sc_osc = getpropint(sc->sc_node, "verosc", 0);
171: switch (sc->sc_osc) {
172: case SPIF_OSC10:
173: sc->sc_osc = 10000000;
174: break;
175: case SPIF_OSC9:
176: default:
177: sc->sc_osc = 9830400;
178: break;
179: }
180:
181: sc->sc_nser = 8;
182: sc->sc_npar = 1;
183:
184: sc->sc_rev2 = sc->sc_regs->stc.gfrcr;
185: sc->sc_regs->stc.gsvr = 0;
186:
187: stty_write_ccr(&sc->sc_regs->stc,
188: CD180_CCR_CMD_RESET | CD180_CCR_RESETALL);
189: while (sc->sc_regs->stc.gsvr != 0xff);
190: while (sc->sc_regs->stc.gfrcr != sc->sc_rev2);
191:
192: sc->sc_regs->stc.pprh = CD180_PPRH;
193: sc->sc_regs->stc.pprl = CD180_PPRL;
194: sc->sc_regs->stc.msmr = SPIF_MSMR;
195: sc->sc_regs->stc.tsmr = SPIF_TSMR;
196: sc->sc_regs->stc.rsmr = SPIF_RSMR;
197: sc->sc_regs->stc.gsvr = 0;
198: sc->sc_regs->stc.gscr1 = 0;
199: sc->sc_regs->stc.gscr2 = 0;
200: sc->sc_regs->stc.gscr3 = 0;
201: printf(": rev %x chiprev %x osc %sMHz stcpri %d ppcpri %d softpri %d\n",
202: sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc),
203: stcpri, ppcpri, IPL_TTY);
204:
205: (void)config_found(self, sttymatch, NULL);
206: (void)config_found(self, sbppmatch, NULL);
207:
208: sc->sc_ppcih.ih_fun = spifppcintr;
209: sc->sc_ppcih.ih_arg = sc;
210: intr_establish(ppcpri, &sc->sc_ppcih, -1, self->dv_xname);
211:
212: sc->sc_stcih.ih_fun = spifstcintr;
213: sc->sc_stcih.ih_arg = sc;
214: intr_establish(stcpri, &sc->sc_stcih, -1, self->dv_xname);
215:
216: sc->sc_softih.ih_fun = spifsoftintr;
217: sc->sc_softih.ih_arg = sc;
218: intr_establish(IPL_TTY, &sc->sc_softih, IPL_TTY, self->dv_xname);
219: }
220:
221: int
222: sttymatch(parent, vcf, aux)
223: struct device *parent;
224: void *vcf, *aux;
225: {
226: struct spif_softc *sc = (struct spif_softc *)parent;
227:
228: return (aux == sttymatch && sc->sc_ttys == NULL);
229: }
230:
231: void
232: sttyattach(parent, dev, aux)
233: struct device *parent, *dev;
234: void *aux;
235: {
236: struct spif_softc *sc = (struct spif_softc *)parent;
237: struct stty_softc *ssc = (struct stty_softc *)dev;
238: int port;
239:
240: sc->sc_ttys = ssc;
241:
242: for (port = 0; port < sc->sc_nser; port++) {
243: struct stty_port *sp = &ssc->sc_port[port];
244: struct tty *tp;
245:
246: sp->sp_dtr = 0;
247: sc->sc_regs->dtrlatch[port] = 1;
248:
249: tp = ttymalloc();
250:
251: tp->t_oproc = stty_start;
252: tp->t_param = stty_param;
253:
254: sp->sp_tty = tp;
255: sp->sp_sc = sc;
256: sp->sp_channel = port;
257:
258: sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT);
259: if(sp->sp_rbuf == NULL)
260: break;
261:
262: sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE;
263: }
264:
265: ssc->sc_nports = port;
266:
267: printf(": %d tty%s\n", port, port == 1 ? "" : "s");
268: }
269:
270: int
271: sttyopen(dev, flags, mode, p)
272: dev_t dev;
273: int flags;
274: int mode;
275: struct proc *p;
276: {
277: struct spif_softc *csc;
278: struct stty_softc *sc;
279: struct stty_port *sp;
280: struct tty *tp;
281: int card = SPIF_CARD(dev);
282: int port = SPIF_PORT(dev);
283: int s;
284:
285: if (card >= stty_cd.cd_ndevs || card >= spif_cd.cd_ndevs)
286: return (ENXIO);
287:
288: sc = stty_cd.cd_devs[card];
289: csc = spif_cd.cd_devs[card];
290: if (sc == NULL)
291: return (ENXIO);
292:
293: if (port >= sc->sc_nports)
294: return (ENXIO);
295:
296: sp = &sc->sc_port[port];
297: tp = sp->sp_tty;
298: tp->t_dev = dev;
299:
300: if (!ISSET(tp->t_state, TS_ISOPEN)) {
301: SET(tp->t_state, TS_WOPEN);
302:
303: ttychars(tp);
304: tp->t_iflag = TTYDEF_IFLAG;
305: tp->t_oflag = TTYDEF_OFLAG;
306: tp->t_cflag = TTYDEF_CFLAG;
307: if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL))
308: SET(tp->t_cflag, CLOCAL);
309: if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS))
310: SET(tp->t_cflag, CRTSCTS);
311: if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF))
312: SET(tp->t_cflag, MDMBUF);
313: tp->t_lflag = TTYDEF_LFLAG;
314: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
315:
316: sp->sp_rput = sp->sp_rget = sp->sp_rbuf;
317:
318: s = spltty();
319:
320: csc->sc_regs->stc.car = sp->sp_channel;
321: stty_write_ccr(&csc->sc_regs->stc,
322: CD180_CCR_CMD_RESET | CD180_CCR_RESETCHAN);
323: csc->sc_regs->stc.car = sp->sp_channel;
324:
325: stty_param(tp, &tp->t_termios);
326:
327: ttsetwater(tp);
328:
329: csc->sc_regs->stc.srer = CD180_SRER_CD | CD180_SRER_RXD;
330:
331: if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier)
332: SET(tp->t_state, TS_CARR_ON);
333: else
334: CLR(tp->t_state, TS_CARR_ON);
335: }
336: else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) {
337: return (EBUSY);
338: } else {
339: s = spltty();
340: }
341:
342: if (!ISSET(flags, O_NONBLOCK)) {
343: while (!ISSET(tp->t_cflag, CLOCAL) &&
344: !ISSET(tp->t_state, TS_CARR_ON)) {
345: int error;
346:
347: SET(tp->t_state, TS_WOPEN);
348: error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
349: "sttycd", 0);
350: if (error != 0) {
351: splx(s);
352: CLR(tp->t_state, TS_WOPEN);
353: return (error);
354: }
355: }
356: }
357:
358: splx(s);
359:
360: return ((*linesw[tp->t_line].l_open)(dev, tp));
361: }
362:
363: int
364: sttyclose(dev, flags, mode, p)
365: dev_t dev;
366: int flags;
367: int mode;
368: struct proc *p;
369: {
370: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
371: struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
372: struct spif_softc *csc = sp->sp_sc;
373: struct tty *tp = sp->sp_tty;
374: int port = SPIF_PORT(dev);
375: int s;
376:
377: (*linesw[tp->t_line].l_close)(tp, flags);
378: s = spltty();
379:
380: if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
381: stty_modem_control(sp, 0, DMSET);
382: csc->sc_regs->stc.car = port;
383: csc->sc_regs->stc.ccr =
384: CD180_CCR_CMD_RESET | CD180_CCR_RESETCHAN;
385: }
386:
387: splx(s);
388: ttyclose(tp);
389: return (0);
390: }
391:
392: int
393: sttyioctl(dev, cmd, data, flags, p)
394: dev_t dev;
395: u_long cmd;
396: caddr_t data;
397: int flags;
398: struct proc *p;
399: {
400: struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)];
401: struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
402: struct spif_softc *sc = sp->sp_sc;
403: struct tty *tp = sp->sp_tty;
404: int error;
405:
406: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p);
407: if (error >= 0)
408: return (error);
409:
410: error = ttioctl(tp, cmd, data, flags, p);
411: if (error >= 0)
412: return (error);
413:
414: error = 0;
415:
416: switch (cmd) {
417: case TIOCSBRK:
418: SET(sp->sp_flags, STTYF_SET_BREAK);
419: sc->sc_regs->stc.car = sp->sp_channel;
420: sc->sc_regs->stc.srer |= CD180_SRER_TXD;
421: break;
422: case TIOCCBRK:
423: SET(sp->sp_flags, STTYF_CLR_BREAK);
424: sc->sc_regs->stc.car = sp->sp_channel;
425: sc->sc_regs->stc.srer |= CD180_SRER_TXD;
426: break;
427: case TIOCSDTR:
428: stty_modem_control(sp, TIOCM_DTR, DMBIS);
429: break;
430: case TIOCCDTR:
431: stty_modem_control(sp, TIOCM_DTR, DMBIC);
432: break;
433: case TIOCMBIS:
434: stty_modem_control(sp, *((int *)data), DMBIS);
435: break;
436: case TIOCMBIC:
437: stty_modem_control(sp, *((int *)data), DMBIC);
438: break;
439: case TIOCMGET:
440: *((int *)data) = stty_modem_control(sp, 0, DMGET);
441: break;
442: case TIOCMSET:
443: stty_modem_control(sp, *((int *)data), DMSET);
444: break;
445: case TIOCGFLAGS:
446: *((int *)data) = sp->sp_openflags;
447: break;
448: case TIOCSFLAGS:
449: if (suser(p, 0))
450: error = EPERM;
451: else
452: sp->sp_openflags = *((int *)data) &
453: (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
454: TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
455: break;
456: default:
457: error = ENOTTY;
458: }
459:
460: return (error);
461: }
462:
463: int
464: stty_modem_control(sp, bits, how)
465: struct stty_port *sp;
466: int bits, how;
467: {
468: struct spif_softc *csc = sp->sp_sc;
469: struct tty *tp = sp->sp_tty;
470: int s, msvr;
471:
472: s = spltty();
473: csc->sc_regs->stc.car = sp->sp_channel;
474:
475: switch (how) {
476: case DMGET:
477: bits = TIOCM_LE;
478: if (sp->sp_dtr)
479: bits |= TIOCM_DTR;
480: msvr = csc->sc_regs->stc.msvr;
481: if (ISSET(msvr, CD180_MSVR_DSR))
482: bits |= TIOCM_DSR;
483: if (ISSET(msvr, CD180_MSVR_CD))
484: bits |= TIOCM_CD;
485: if (ISSET(msvr, CD180_MSVR_CTS))
486: bits |= TIOCM_CTS;
487: if (ISSET(msvr, CD180_MSVR_RTS))
488: bits |= TIOCM_RTS;
489: break;
490: case DMSET:
491: if (ISSET(bits, TIOCM_DTR)) {
492: sp->sp_dtr = 1;
493: csc->sc_regs->dtrlatch[sp->sp_channel] = 0;
494: }
495: else {
496: sp->sp_dtr = 0;
497: csc->sc_regs->dtrlatch[sp->sp_channel] = 1;
498: }
499: if (ISSET(bits, TIOCM_RTS))
500: csc->sc_regs->stc.msvr &= ~CD180_MSVR_RTS;
501: else
502: csc->sc_regs->stc.msvr |= CD180_MSVR_RTS;
503: break;
504: case DMBIS:
505: if (ISSET(bits, TIOCM_DTR)) {
506: sp->sp_dtr = 1;
507: csc->sc_regs->dtrlatch[sp->sp_channel] = 0;
508: }
509: if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS))
510: csc->sc_regs->stc.msvr &= ~CD180_MSVR_RTS;
511: break;
512: case DMBIC:
513: if (ISSET(bits, TIOCM_DTR)) {
514: sp->sp_dtr = 0;
515: csc->sc_regs->dtrlatch[sp->sp_channel] = 1;
516: }
517: if (ISSET(bits, TIOCM_RTS))
518: csc->sc_regs->stc.msvr |= CD180_MSVR_RTS;
519: break;
520: }
521:
522: splx(s);
523: return (bits);
524: }
525:
526: int
527: stty_param(tp, t)
528: struct tty *tp;
529: struct termios *t;
530: {
531: struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
532: struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)];
533: struct spif_softc *sc = sp->sp_sc;
534: u_int8_t rbprl, rbprh, tbprl, tbprh;
535: int s, opt;
536:
537: if (t->c_ospeed &&
538: stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh))
539: return (EINVAL);
540:
541: if (t->c_ispeed &&
542: stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh))
543: return (EINVAL);
544:
545: s = spltty();
546:
547: /* hang up line if ospeed is zero, otherwise raise DTR */
548: stty_modem_control(sp, TIOCM_DTR,
549: (t->c_ospeed == 0 ? DMBIC : DMBIS));
550:
551: sc->sc_regs->stc.car = sp->sp_channel;
552:
553: opt = 0;
554: if (ISSET(t->c_cflag, PARENB)) {
555: opt |= CD180_COR1_PARMODE_NORMAL;
556: opt |= (ISSET(t->c_cflag, PARODD) ?
557: CD180_COR1_ODDPAR :
558: CD180_COR1_EVENPAR);
559: }
560: else
561: opt |= CD180_COR1_PARMODE_NO;
562:
563: if (!ISSET(t->c_iflag, INPCK))
564: opt |= CD180_COR1_IGNPAR;
565:
566: if (ISSET(t->c_cflag, CSTOPB))
567: opt |= CD180_COR1_STOP2;
568:
569: switch (t->c_cflag & CSIZE) {
570: case CS5:
571: opt |= CD180_COR1_CS5;
572: break;
573: case CS6:
574: opt |= CD180_COR1_CS6;
575: break;
576: case CS7:
577: opt |= CD180_COR1_CS7;
578: break;
579: default:
580: opt |= CD180_COR1_CS8;
581: break;
582: }
583: sc->sc_regs->stc.cor1 = opt;
584: stty_write_ccr(&sc->sc_regs->stc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1);
585:
586: opt = CD180_COR2_ETC;
587: if (ISSET(t->c_cflag, CRTSCTS))
588: opt |= CD180_COR2_CTSAE;
589: sc->sc_regs->stc.cor2 = opt;
590: stty_write_ccr(&sc->sc_regs->stc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2);
591:
592: sc->sc_regs->stc.cor3 = STTY_RX_FIFO_THRESHOLD;
593: stty_write_ccr(&sc->sc_regs->stc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3);
594:
595: sc->sc_regs->stc.schr1 = 0x11;
596: sc->sc_regs->stc.schr2 = 0x13;
597: sc->sc_regs->stc.schr3 = 0x11;
598: sc->sc_regs->stc.schr4 = 0x13;
599: sc->sc_regs->stc.rtpr = 0x12;
600:
601: sc->sc_regs->stc.mcor1 = CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD;
602: sc->sc_regs->stc.mcor2 = CD180_MCOR2_CDOD;
603: sc->sc_regs->stc.mcr = 0;
604:
605: if (t->c_ospeed) {
606: sc->sc_regs->stc.tbprh = tbprh;
607: sc->sc_regs->stc.tbprl = tbprl;
608: }
609:
610: if (t->c_ispeed) {
611: sc->sc_regs->stc.rbprh = rbprh;
612: sc->sc_regs->stc.rbprl = rbprl;
613: }
614:
615: stty_write_ccr(&sc->sc_regs->stc, CD180_CCR_CMD_CHAN |
616: CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN);
617:
618: sp->sp_carrier = sc->sc_regs->stc.msvr & CD180_MSVR_CD;
619:
620: splx(s);
621: return (0);
622: }
623:
624: int
625: sttyread(dev, uio, flags)
626: dev_t dev;
627: struct uio *uio;
628: int flags;
629: {
630: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
631: struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
632: struct tty *tp = sp->sp_tty;
633:
634: return ((*linesw[tp->t_line].l_read)(tp, uio, flags));
635: }
636:
637: int
638: sttywrite(dev, uio, flags)
639: dev_t dev;
640: struct uio *uio;
641: int flags;
642: {
643: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
644: struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
645: struct tty *tp = sp->sp_tty;
646:
647: return ((*linesw[tp->t_line].l_write)(tp, uio, flags));
648: }
649:
650: struct tty *
651: sttytty(dev)
652: dev_t dev;
653: {
654: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
655: struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
656:
657: return (sp->sp_tty);
658: }
659:
660: int
661: sttystop(tp, flags)
662: struct tty *tp;
663: int flags;
664: {
665: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
666: struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)];
667: int s;
668:
669: s = spltty();
670: if (ISSET(tp->t_state, TS_BUSY)) {
671: if (!ISSET(tp->t_state, TS_TTSTOP))
672: SET(tp->t_state, TS_FLUSH);
673: SET(sp->sp_flags, STTYF_STOP);
674: }
675: splx(s);
676: return (0);
677: }
678:
679: void
680: stty_start(tp)
681: struct tty *tp;
682: {
683: struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
684: struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)];
685: struct spif_softc *sc = sp->sp_sc;
686: int s;
687:
688: s = spltty();
689:
690: if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
691: if (tp->t_outq.c_cc <= tp->t_lowat) {
692: if (ISSET(tp->t_state, TS_ASLEEP)) {
693: CLR(tp->t_state, TS_ASLEEP);
694: wakeup(&tp->t_outq);
695: }
696: selwakeup(&tp->t_wsel);
697: }
698: if (tp->t_outq.c_cc) {
699: sp->sp_txc = ndqb(&tp->t_outq, 0);
700: sp->sp_txp = tp->t_outq.c_cf;
701: SET(tp->t_state, TS_BUSY);
702: sc->sc_regs->stc.car = sp->sp_channel;
703: sc->sc_regs->stc.srer |= CD180_SRER_TXD;
704: }
705: }
706:
707: splx(s);
708: }
709:
710: int
711: spifstcintr_rxexception(sc, needsoftp)
712: struct spif_softc *sc;
713: int *needsoftp;
714: {
715: struct stty_port *sp;
716: u_int8_t channel, *ptr;
717:
718: channel = CD180_GSCR_CHANNEL(sc->sc_regs->stc.gscr1);
719: sp = &sc->sc_ttys->sc_port[channel];
720: ptr = sp->sp_rput;
721: *ptr++ = sc->sc_regs->stc.rcsr;
722: *ptr++ = sc->sc_regs->stc.rdr;
723: if (ptr == sp->sp_rend)
724: ptr = sp->sp_rbuf;
725: if (ptr == sp->sp_rget) {
726: if (ptr == sp->sp_rbuf)
727: ptr = sp->sp_rend;
728: ptr -= 2;
729: SET(sp->sp_flags, STTYF_RING_OVERFLOW);
730: }
731: sc->sc_regs->stc.eosrr = 0;
732: *needsoftp = 1;
733: sp->sp_rput = ptr;
734: return (1);
735: }
736:
737: int
738: spifstcintr_rx(sc, needsoftp)
739: struct spif_softc *sc;
740: int *needsoftp;
741: {
742: struct stty_port *sp;
743: u_int8_t channel, *ptr, cnt, rcsr;
744: int i;
745:
746: channel = CD180_GSCR_CHANNEL(sc->sc_regs->stc.gscr1);
747: sp = &sc->sc_ttys->sc_port[channel];
748: ptr = sp->sp_rput;
749: cnt = sc->sc_regs->stc.rdcr;
750: for (i = 0; i < cnt; i++) {
751: *ptr++ = 0;
752: rcsr = sc->sc_regs->stc.rcsr;
753: *ptr++ = sc->sc_regs->stc.rdr;
754: if (ptr == sp->sp_rend)
755: ptr = sp->sp_rbuf;
756: if (ptr == sp->sp_rget) {
757: if (ptr == sp->sp_rbuf)
758: ptr = sp->sp_rend;
759: ptr -= 2;
760: SET(sp->sp_flags, STTYF_RING_OVERFLOW);
761: break;
762: }
763: }
764: sc->sc_regs->stc.eosrr = 0;
765: if (cnt) {
766: *needsoftp = 1;
767: sp->sp_rput = ptr;
768: }
769: return (1);
770: }
771:
772: int
773: spifstcintr_tx(sc, needsoftp)
774: struct spif_softc *sc;
775: int *needsoftp;
776: {
777: struct stty_port *sp;
778: u_int8_t channel, ch;
779: int cnt = 0;
780:
781: channel = CD180_GSCR_CHANNEL(sc->sc_regs->stc.gscr1);
782: sp = &sc->sc_ttys->sc_port[channel];
783: if (!ISSET(sp->sp_flags, STTYF_STOP)) {
784: if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) {
785: sc->sc_regs->stc.tdr = 0;
786: sc->sc_regs->stc.tdr = 0x81;
787: CLR(sp->sp_flags, STTYF_SET_BREAK);
788: cnt += 2;
789: }
790: if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) {
791: sc->sc_regs->stc.tdr = 0;
792: sc->sc_regs->stc.tdr = 0x83;
793: CLR(sp->sp_flags, STTYF_CLR_BREAK);
794: cnt += 2;
795: }
796:
797: while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) {
798: ch = *sp->sp_txp;
799: sp->sp_txc--;
800: sp->sp_txp++;
801:
802: if (ch == 0) {
803: sc->sc_regs->stc.tdr = ch;
804: cnt++;
805: }
806: sc->sc_regs->stc.tdr = ch;
807: cnt++;
808: }
809: }
810:
811: if (sp->sp_txc == 0 ||
812: ISSET(sp->sp_flags, STTYF_STOP)) {
813: sc->sc_regs->stc.srer &= ~CD180_SRER_TXD;
814: CLR(sp->sp_flags, STTYF_STOP);
815: SET(sp->sp_flags, STTYF_DONE);
816: *needsoftp = 1;
817: }
818:
819: sc->sc_regs->stc.eosrr = 0;
820:
821: return (1);
822: }
823:
824: int
825: spifstcintr_mx(sc, needsoftp)
826: struct spif_softc *sc;
827: int *needsoftp;
828: {
829: struct stty_port *sp;
830: u_int8_t channel, mcr;
831:
832: channel = CD180_GSCR_CHANNEL(sc->sc_regs->stc.gscr1);
833: sp = &sc->sc_ttys->sc_port[channel];
834: mcr = sc->sc_regs->stc.mcr;
835: if (mcr & CD180_MCR_CD) {
836: SET(sp->sp_flags, STTYF_CDCHG);
837: *needsoftp = 1;
838: }
839: sc->sc_regs->stc.mcr = 0;
840: sc->sc_regs->stc.eosrr = 0;
841: return (1);
842: }
843:
844: int
845: spifstcintr(vsc)
846: void *vsc;
847: {
848: struct spif_softc *sc = (struct spif_softc *)vsc;
849: int needsoft = 0, r = 0, i;
850: u_int8_t ar;
851:
852: for (i = 0; i < 8; i++) {
853: ar = sc->sc_regs->istc.rrar & CD180_GSVR_IMASK;
854: if (ar == CD180_GSVR_RXGOOD)
855: r |= spifstcintr_rx(sc, &needsoft);
856: else if (ar == CD180_GSVR_RXEXCEPTION)
857: r |= spifstcintr_rxexception(sc, &needsoft);
858: }
859:
860: for (i = 0; i < 8; i++) {
861: ar = sc->sc_regs->istc.trar & CD180_GSVR_IMASK;
862: if (ar == CD180_GSVR_TXDATA)
863: r |= spifstcintr_tx(sc, &needsoft);
864: }
865:
866: for (i = 0; i < 8; i++) {
867: ar = sc->sc_regs->istc.mrar & CD180_GSVR_IMASK;
868: if (ar == CD180_GSVR_STATCHG)
869: r |= spifstcintr_mx(sc, &needsoft);
870: }
871:
872: if (needsoft) {
873: #if defined(SUN4M)
874: if (CPU_ISSUN4M)
875: raise(0, IPL_TTY);
876: else
877: #endif
878: ienab_bis(IE_MSOFT);
879: }
880: return (r);
881: }
882:
883: int
884: spifsoftintr(vsc)
885: void *vsc;
886: {
887: struct spif_softc *sc = (struct spif_softc *)vsc;
888: struct stty_softc *stc = sc->sc_ttys;
889: int r = 0, i, data, s, flags;
890: u_int8_t stat, msvr;
891: struct stty_port *sp;
892: struct tty *tp;
893:
894: if (stc != NULL) {
895: for (i = 0; i < stc->sc_nports; i++) {
896: sp = &stc->sc_port[i];
897: tp = sp->sp_tty;
898:
899: if (!ISSET(tp->t_state, TS_ISOPEN))
900: continue;
901:
902: while (sp->sp_rget != sp->sp_rput) {
903: stat = sp->sp_rget[0];
904: data = sp->sp_rget[1];
905: sp->sp_rget += 2;
906: if (sp->sp_rget == sp->sp_rend)
907: sp->sp_rget = sp->sp_rbuf;
908:
909: if (stat & (CD180_RCSR_BE | CD180_RCSR_FE))
910: data |= TTY_FE;
911:
912: if (stat & CD180_RCSR_PE)
913: data |= TTY_PE;
914:
915: (*linesw[tp->t_line].l_rint)(data, tp);
916: r = 1;
917: }
918:
919: s = splhigh();
920: flags = sp->sp_flags;
921: CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG |
922: STTYF_RING_OVERFLOW);
923: splx(s);
924:
925: if (ISSET(flags, STTYF_CDCHG)) {
926: s = spltty();
927: sc->sc_regs->stc.car = i;
928: msvr = sc->sc_regs->stc.msvr;
929: splx(s);
930:
931: sp->sp_carrier = msvr & CD180_MSVR_CD;
932: (*linesw[tp->t_line].l_modem)(tp,
933: sp->sp_carrier);
934: r = 1;
935: }
936:
937: if (ISSET(flags, STTYF_RING_OVERFLOW)) {
938: log(LOG_WARNING, "%s-%x: ring overflow\n",
939: stc->sc_dev.dv_xname, i);
940: r = 1;
941: }
942:
943: if (ISSET(flags, STTYF_DONE)) {
944: ndflush(&tp->t_outq,
945: sp->sp_txp - tp->t_outq.c_cf);
946: CLR(tp->t_state, TS_BUSY);
947: (*linesw[tp->t_line].l_start)(tp);
948: r = 1;
949: }
950: }
951: }
952:
953: return (r);
954: }
955:
956: static __inline void
957: stty_write_ccr(stc, val)
958: struct stcregs *stc;
959: u_int8_t val;
960: {
961: int tries = 100000;
962:
963: while (stc->ccr && tries--);
964: if (tries == 0)
965: printf("CCR: timeout\n");
966: stc->ccr = val;
967: }
968:
969: int
970: stty_compute_baud(speed, clock, bprlp, bprhp)
971: speed_t speed;
972: int clock;
973: u_int8_t *bprlp, *bprhp;
974: {
975: u_int32_t rate;
976:
977: rate = (2 * clock) / (16 * speed);
978: if (rate & 1)
979: rate = (rate >> 1) + 1;
980: else
981: rate = rate >> 1;
982:
983: if (rate > 0xffff || rate == 0)
984: return (1);
985:
986: *bprlp = rate & 0xff;
987: *bprhp = (rate >> 8) & 0xff;
988: return (0);
989: }
990:
991: int
992: sbppmatch(parent, vcf, aux)
993: struct device *parent;
994: void *vcf, *aux;
995: {
996: struct spif_softc *sc = (struct spif_softc *)parent;
997:
998: return (aux == sbppmatch && sc->sc_bpps == NULL);
999: }
1000:
1001: void
1002: sbppattach(parent, dev, aux)
1003: struct device *parent, *dev;
1004: void *aux;
1005: {
1006: struct spif_softc *sc = (struct spif_softc *)parent;
1007: struct sbpp_softc *psc = (struct sbpp_softc *)dev;
1008: int port;
1009:
1010: sc->sc_bpps = psc;
1011:
1012: for (port = 0; port < sc->sc_npar; port++) {
1013: }
1014:
1015: psc->sc_nports = port;
1016: printf(": %d port%s\n", port, port == 1 ? "" : "s");
1017: }
1018:
1019: int
1020: sbppopen(dev, flags, mode, p)
1021: dev_t dev;
1022: int flags;
1023: int mode;
1024: struct proc *p;
1025: {
1026: return (ENXIO);
1027: }
1028:
1029: int
1030: sbppclose(dev, flags, mode, p)
1031: dev_t dev;
1032: int flags;
1033: int mode;
1034: struct proc *p;
1035: {
1036: return (ENXIO);
1037: }
1038:
1039: int
1040: spifppcintr(v)
1041: void *v;
1042: {
1043: return (0);
1044: }
1045:
1046: int
1047: sbppread(dev, uio, flags)
1048: dev_t dev;
1049: struct uio *uio;
1050: int flags;
1051: {
1052: return (sbpp_rw(dev, uio));
1053: }
1054:
1055: int
1056: sbppwrite(dev, uio, flags)
1057: dev_t dev;
1058: struct uio *uio;
1059: int flags;
1060: {
1061: return (sbpp_rw(dev, uio));
1062: }
1063:
1064: int
1065: sbpp_rw(dev, uio)
1066: dev_t dev;
1067: struct uio *uio;
1068: {
1069: return (ENXIO);
1070: }
1071:
1072: int
1073: sbpppoll(dev, events, p)
1074: dev_t dev;
1075: int events;
1076: struct proc *p;
1077: {
1078: return (seltrue(dev, events, p));
1079: }
1080:
1081: int
1082: sbppioctl(dev, cmd, data, flags, p)
1083: dev_t dev;
1084: u_long cmd;
1085: caddr_t data;
1086: int flags;
1087: struct proc *p;
1088: {
1089: int error;
1090:
1091: error = ENOTTY;
1092:
1093: return (error);
1094: }
CVSweb