Annotation of sys/dev/sbus/spif.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: spif.c,v 1.13 2006/03/04 13:00:55 miod Exp $ */
2:
3: /*
4: * Copyright (c) 1999-2002 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: * Effort sponsored in part by the Defense Advanced Research Projects
29: * Agency (DARPA) and Air Force Research Laboratory, Air Force
30: * Materiel Command, USAF, under agreement number F30602-01-2-0537.
31: *
32: */
33:
34: /*
35: * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board
36: * based heavily on Iain Hibbert's driver for the MAGMA cards
37: */
38:
39: #include <sys/param.h>
40: #include <sys/systm.h>
41: #include <sys/proc.h>
42: #include <sys/device.h>
43: #include <sys/kernel.h>
44: #include <sys/file.h>
45: #include <sys/errno.h>
46: #include <sys/ioctl.h>
47: #include <sys/mbuf.h>
48: #include <sys/socket.h>
49: #include <sys/syslog.h>
50: #include <sys/malloc.h>
51: #include <sys/tty.h>
52: #include <sys/conf.h>
53:
54: #include <machine/autoconf.h>
55: #include <dev/sbus/sbusvar.h>
56: #include <dev/sbus/spifreg.h>
57: #include <dev/sbus/spifvar.h>
58:
59: int spifmatch(struct device *, void *, void *);
60: void spifattach(struct device *, struct device *, void *);
61:
62: int sttymatch(struct device *, void *, void *);
63: void sttyattach(struct device *, struct device *, void *);
64: int sttyopen(dev_t, int, int, struct proc *);
65: int sttyclose(dev_t, int, int, struct proc *);
66: int sttyread(dev_t, struct uio *, int);
67: int sttywrite(dev_t, struct uio *, int);
68: int sttyioctl(dev_t, u_long, caddr_t, int, struct proc *);
69: int sttystop(struct tty *, int);
70:
71: int spifstcintr(void *);
72: int spifstcintr_mx(struct spif_softc *, int *);
73: int spifstcintr_tx(struct spif_softc *, int *);
74: int spifstcintr_rx(struct spif_softc *, int *);
75: int spifstcintr_rxexception(struct spif_softc *, int *);
76: void spifsoftintr(void *);
77:
78: int stty_param(struct tty *, struct termios *);
79: struct tty *sttytty(dev_t);
80: int stty_modem_control(struct stty_port *, int, int);
81: void stty_write_ccr(struct spif_softc *, u_int8_t);
82: int stty_compute_baud(speed_t, int, u_int8_t *, u_int8_t *);
83: void stty_start(struct tty *);
84:
85: int sbppmatch(struct device *, void *, void *);
86: void sbppattach(struct device *, struct device *, void *);
87: int sbppopen(dev_t, int, int, struct proc *);
88: int sbppclose(dev_t, int, int, struct proc *);
89: int sbppread(dev_t, struct uio *, int);
90: int sbppwrite(dev_t, struct uio *, int);
91: int sbpp_rw(dev_t, struct uio *);
92: int spifppcintr(void *);
93: int sbpppoll(dev_t, int, struct proc *);
94: int sbppioctl(dev_t, u_long, caddr_t, int, struct proc *);
95:
96: struct cfattach spif_ca = {
97: sizeof (struct spif_softc), spifmatch, spifattach
98: };
99:
100: struct cfdriver spif_cd = {
101: NULL, "spif", DV_DULL
102: };
103:
104: struct cfattach stty_ca = {
105: sizeof(struct stty_softc), sttymatch, sttyattach
106: };
107:
108: struct cfdriver stty_cd = {
109: NULL, "stty", DV_TTY
110: };
111:
112: struct cfattach sbpp_ca = {
113: sizeof(struct sbpp_softc), sbppmatch, sbppattach
114: };
115:
116: struct cfdriver sbpp_cd = {
117: NULL, "sbpp", DV_DULL
118: };
119:
120: /* normal STC access */
121: #define STC_WRITE(sc,r,v) \
122: bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v))
123: #define STC_READ(sc,r) \
124: bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r))
125:
126: /* IACK STC access */
127: #define ISTC_WRITE(sc,r,v) \
128: bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v))
129: #define ISTC_READ(sc,r) \
130: bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r))
131:
132: /* PPC access */
133: #define PPC_WRITE(sc,r,v) \
134: bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v))
135: #define PPC_READ(sc,r) \
136: bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r))
137:
138: #define DTR_WRITE(sc,port,v) \
139: do { \
140: sc->sc_ttys->sc_port[(port)].sp_dtr = v; \
141: bus_space_write_1((sc)->sc_bustag, \
142: sc->sc_dtrh, port, (v == 0) ? 1 : 0); \
143: } while (0)
144:
145: #define DTR_READ(sc,port) ((sc)->sc_ttys->sc_port[(port)].sp_dtr)
146:
147: int
148: spifmatch(parent, vcf, aux)
149: struct device *parent;
150: void *vcf, *aux;
151: {
152: struct cfdata *cf = vcf;
153: struct sbus_attach_args *sa = aux;
154:
155: if (strcmp(cf->cf_driver->cd_name, sa->sa_name) &&
156: strcmp("SUNW,spif", sa->sa_name))
157: return (0);
158: return (1);
159: }
160:
161: void
162: spifattach(parent, self, aux)
163: struct device *parent, *self;
164: void *aux;
165: {
166: struct spif_softc *sc = (struct spif_softc *)self;
167: struct sbus_attach_args *sa = aux;
168:
169: if (sa->sa_nintr != 2) {
170: printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr);
171: return;
172: }
173:
174: if (sa->sa_nreg != 1) {
175: printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
176: return;
177: }
178:
179: sc->sc_bustag = sa->sa_bustag;
180: if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
181: sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
182: 0, 0, &sc->sc_regh) != 0) {
183: printf(": can't map registers\n");
184: return;
185: }
186:
187: if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
188: DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) {
189: printf(": can't map dtr regs\n");
190: goto fail_unmapregs;
191: }
192:
193: if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
194: STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) {
195: printf(": can't map dtr regs\n");
196: goto fail_unmapregs;
197: }
198:
199: if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
200: ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) {
201: printf(": can't map dtr regs\n");
202: goto fail_unmapregs;
203: }
204:
205: if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
206: PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) {
207: printf(": can't map dtr regs\n");
208: goto fail_unmapregs;
209: }
210:
211: sc->sc_ppcih = bus_intr_establish(sa->sa_bustag,
212: sa->sa_intr[PARALLEL_INTR].sbi_pri, IPL_TTY, 0, spifppcintr, sc,
213: self->dv_xname);
214: if (sc->sc_ppcih == NULL) {
215: printf(": failed to establish ppc interrupt\n");
216: goto fail_unmapregs;
217: }
218:
219: sc->sc_stcih = bus_intr_establish(sa->sa_bustag,
220: sa->sa_intr[SERIAL_INTR].sbi_pri, IPL_TTY, 0, spifstcintr, sc,
221: self->dv_xname);
222: if (sc->sc_stcih == NULL) {
223: printf(": failed to establish stc interrupt\n");
224: goto fail_unmapregs;
225: }
226:
227: sc->sc_softih = softintr_establish(IPL_TTY, spifsoftintr, sc);
228: if (sc->sc_softih == NULL) {
229: printf(": can't get soft intr\n");
230: goto fail_unmapregs;
231: }
232:
233: sc->sc_node = sa->sa_node;
234:
235: sc->sc_rev = getpropint(sc->sc_node, "revlev", 0);
236:
237: sc->sc_osc = getpropint(sc->sc_node, "verosc", 0);
238: switch (sc->sc_osc) {
239: case SPIF_OSC10:
240: sc->sc_osc = 10000000;
241: break;
242: case SPIF_OSC9:
243: default:
244: sc->sc_osc = 9830400;
245: break;
246: }
247:
248: sc->sc_nser = 8;
249: sc->sc_npar = 1;
250:
251: sc->sc_rev2 = STC_READ(sc, STC_GFRCR);
252: STC_WRITE(sc, STC_GSVR, 0);
253:
254: stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL);
255: while (STC_READ(sc, STC_GSVR) != 0xff);
256: while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2);
257:
258: STC_WRITE(sc, STC_PPRH, CD180_PPRH);
259: STC_WRITE(sc, STC_PPRL, CD180_PPRL);
260: STC_WRITE(sc, STC_MSMR, SPIF_MSMR);
261: STC_WRITE(sc, STC_TSMR, SPIF_TSMR);
262: STC_WRITE(sc, STC_RSMR, SPIF_RSMR);
263: STC_WRITE(sc, STC_GSVR, 0);
264: STC_WRITE(sc, STC_GSCR1, 0);
265: STC_WRITE(sc, STC_GSCR2, 0);
266: STC_WRITE(sc, STC_GSCR3, 0);
267:
268: printf(": rev %x chiprev %x osc %sMHz\n",
269: sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc));
270:
271: (void)config_found(self, sttymatch, NULL);
272: (void)config_found(self, sbppmatch, NULL);
273:
274: return;
275:
276: fail_unmapregs:
277: bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_reg[0].sbr_size);
278: }
279:
280: int
281: sttymatch(parent, vcf, aux)
282: struct device *parent;
283: void *vcf, *aux;
284: {
285: struct spif_softc *sc = (struct spif_softc *)parent;
286:
287: return (aux == sttymatch && sc->sc_ttys == NULL);
288: }
289:
290: void
291: sttyattach(parent, dev, aux)
292: struct device *parent, *dev;
293: void *aux;
294: {
295: struct spif_softc *sc = (struct spif_softc *)parent;
296: struct stty_softc *ssc = (struct stty_softc *)dev;
297: int port;
298:
299: sc->sc_ttys = ssc;
300:
301: for (port = 0; port < sc->sc_nser; port++) {
302: struct stty_port *sp = &ssc->sc_port[port];
303: struct tty *tp;
304:
305: DTR_WRITE(sc, port, 0);
306:
307: tp = ttymalloc();
308:
309: tp->t_oproc = stty_start;
310: tp->t_param = stty_param;
311:
312: sp->sp_tty = tp;
313: sp->sp_sc = sc;
314: sp->sp_channel = port;
315:
316: sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT);
317: if(sp->sp_rbuf == NULL)
318: break;
319:
320: sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE;
321: }
322:
323: ssc->sc_nports = port;
324:
325: printf(": %d tty%s\n", port, port == 1 ? "" : "s");
326: }
327:
328: int
329: sttyopen(dev, flags, mode, p)
330: dev_t dev;
331: int flags;
332: int mode;
333: struct proc *p;
334: {
335: struct spif_softc *csc;
336: struct stty_softc *sc;
337: struct stty_port *sp;
338: struct tty *tp;
339: int card = SPIF_CARD(dev);
340: int port = SPIF_PORT(dev);
341: int s;
342:
343: if (card >= stty_cd.cd_ndevs || card >= spif_cd.cd_ndevs)
344: return (ENXIO);
345:
346: sc = stty_cd.cd_devs[card];
347: csc = spif_cd.cd_devs[card];
348: if (sc == NULL || csc == NULL)
349: return (ENXIO);
350:
351: if (port >= sc->sc_nports)
352: return (ENXIO);
353:
354: sp = &sc->sc_port[port];
355: tp = sp->sp_tty;
356: tp->t_dev = dev;
357:
358: if (!ISSET(tp->t_state, TS_ISOPEN)) {
359: SET(tp->t_state, TS_WOPEN);
360:
361: ttychars(tp);
362: tp->t_iflag = TTYDEF_IFLAG;
363: tp->t_oflag = TTYDEF_OFLAG;
364: tp->t_cflag = TTYDEF_CFLAG;
365: if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL))
366: SET(tp->t_cflag, CLOCAL);
367: if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS))
368: SET(tp->t_cflag, CRTSCTS);
369: if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF))
370: SET(tp->t_cflag, MDMBUF);
371: tp->t_lflag = TTYDEF_LFLAG;
372: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
373:
374: sp->sp_rput = sp->sp_rget = sp->sp_rbuf;
375:
376: s = spltty();
377:
378: STC_WRITE(csc, STC_CAR, sp->sp_channel);
379: stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
380: STC_WRITE(csc, STC_CAR, sp->sp_channel);
381:
382: stty_param(tp, &tp->t_termios);
383:
384: ttsetwater(tp);
385:
386: STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD);
387:
388: if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier)
389: SET(tp->t_state, TS_CARR_ON);
390: else
391: CLR(tp->t_state, TS_CARR_ON);
392: }
393: else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) {
394: return (EBUSY);
395: } else {
396: s = spltty();
397: }
398:
399: if (!ISSET(flags, O_NONBLOCK)) {
400: while (!ISSET(tp->t_cflag, CLOCAL) &&
401: !ISSET(tp->t_state, TS_CARR_ON)) {
402: int error;
403:
404: SET(tp->t_state, TS_WOPEN);
405: error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
406: "sttycd", 0);
407: if (error != 0) {
408: splx(s);
409: CLR(tp->t_state, TS_WOPEN);
410: return (error);
411: }
412: }
413: }
414:
415: splx(s);
416:
417: return ((*linesw[tp->t_line].l_open)(dev, tp));
418: }
419:
420: int
421: sttyclose(dev, flags, mode, p)
422: dev_t dev;
423: int flags;
424: int mode;
425: struct proc *p;
426: {
427: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
428: struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
429: struct spif_softc *csc = sp->sp_sc;
430: struct tty *tp = sp->sp_tty;
431: int port = SPIF_PORT(dev);
432: int s;
433:
434: (*linesw[tp->t_line].l_close)(tp, flags);
435: s = spltty();
436:
437: if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
438: stty_modem_control(sp, 0, DMSET);
439: STC_WRITE(csc, STC_CAR, port);
440: STC_WRITE(csc, STC_CCR,
441: CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
442: }
443:
444: splx(s);
445: ttyclose(tp);
446: return (0);
447: }
448:
449: int
450: sttyioctl(dev, cmd, data, flags, p)
451: dev_t dev;
452: u_long cmd;
453: caddr_t data;
454: int flags;
455: struct proc *p;
456: {
457: struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)];
458: struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
459: struct spif_softc *sc = sp->sp_sc;
460: struct tty *tp = sp->sp_tty;
461: int error;
462:
463: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p);
464: if (error >= 0)
465: return (error);
466:
467: error = ttioctl(tp, cmd, data, flags, p);
468: if (error >= 0)
469: return (error);
470:
471: error = 0;
472:
473: switch (cmd) {
474: case TIOCSBRK:
475: SET(sp->sp_flags, STTYF_SET_BREAK);
476: STC_WRITE(sc, STC_CAR, sp->sp_channel);
477: STC_WRITE(sc, STC_SRER,
478: STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
479: break;
480: case TIOCCBRK:
481: SET(sp->sp_flags, STTYF_CLR_BREAK);
482: STC_WRITE(sc, STC_CAR, sp->sp_channel);
483: STC_WRITE(sc, STC_SRER,
484: STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
485: break;
486: case TIOCSDTR:
487: stty_modem_control(sp, TIOCM_DTR, DMBIS);
488: break;
489: case TIOCCDTR:
490: stty_modem_control(sp, TIOCM_DTR, DMBIC);
491: break;
492: case TIOCMBIS:
493: stty_modem_control(sp, *((int *)data), DMBIS);
494: break;
495: case TIOCMBIC:
496: stty_modem_control(sp, *((int *)data), DMBIC);
497: break;
498: case TIOCMGET:
499: *((int *)data) = stty_modem_control(sp, 0, DMGET);
500: break;
501: case TIOCMSET:
502: stty_modem_control(sp, *((int *)data), DMSET);
503: break;
504: case TIOCGFLAGS:
505: *((int *)data) = sp->sp_openflags;
506: break;
507: case TIOCSFLAGS:
508: if (suser(p, 0))
509: error = EPERM;
510: else
511: sp->sp_openflags = *((int *)data) &
512: (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
513: TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
514: break;
515: default:
516: error = ENOTTY;
517: }
518:
519: return (error);
520: }
521:
522: int
523: stty_modem_control(sp, bits, how)
524: struct stty_port *sp;
525: int bits, how;
526: {
527: struct spif_softc *csc = sp->sp_sc;
528: struct tty *tp = sp->sp_tty;
529: int s, msvr;
530:
531: s = spltty();
532: STC_WRITE(csc, STC_CAR, sp->sp_channel);
533:
534: switch (how) {
535: case DMGET:
536: bits = TIOCM_LE;
537: if (DTR_READ(csc, sp->sp_channel))
538: bits |= TIOCM_DTR;
539: msvr = STC_READ(csc, STC_MSVR);
540: if (ISSET(msvr, CD180_MSVR_DSR))
541: bits |= TIOCM_DSR;
542: if (ISSET(msvr, CD180_MSVR_CD))
543: bits |= TIOCM_CD;
544: if (ISSET(msvr, CD180_MSVR_CTS))
545: bits |= TIOCM_CTS;
546: if (ISSET(msvr, CD180_MSVR_RTS))
547: bits |= TIOCM_RTS;
548: break;
549: case DMSET:
550: DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0);
551: if (ISSET(bits, TIOCM_RTS))
552: STC_WRITE(csc, STC_MSVR,
553: STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
554: else
555: STC_WRITE(csc, STC_MSVR,
556: STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
557: break;
558: case DMBIS:
559: if (ISSET(bits, TIOCM_DTR))
560: DTR_WRITE(csc, sp->sp_channel, 1);
561: if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS))
562: STC_WRITE(csc, STC_MSVR,
563: STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
564: break;
565: case DMBIC:
566: if (ISSET(bits, TIOCM_DTR))
567: DTR_WRITE(csc, sp->sp_channel, 0);
568: if (ISSET(bits, TIOCM_RTS))
569: STC_WRITE(csc, STC_MSVR,
570: STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
571: break;
572: }
573:
574: splx(s);
575: return (bits);
576: }
577:
578: int
579: stty_param(tp, t)
580: struct tty *tp;
581: struct termios *t;
582: {
583: struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
584: struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)];
585: struct spif_softc *sc = sp->sp_sc;
586: u_int8_t rbprl, rbprh, tbprl, tbprh;
587: int s, opt;
588:
589: if (t->c_ospeed &&
590: stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh))
591: return (EINVAL);
592:
593: if (t->c_ispeed &&
594: stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh))
595: return (EINVAL);
596:
597: s = spltty();
598:
599: /* hang up line if ospeed is zero, otherwise raise DTR */
600: stty_modem_control(sp, TIOCM_DTR,
601: (t->c_ospeed == 0 ? DMBIC : DMBIS));
602:
603: STC_WRITE(sc, STC_CAR, sp->sp_channel);
604:
605: opt = 0;
606: if (ISSET(t->c_cflag, PARENB)) {
607: opt |= CD180_COR1_PARMODE_NORMAL;
608: opt |= (ISSET(t->c_cflag, PARODD) ?
609: CD180_COR1_ODDPAR :
610: CD180_COR1_EVENPAR);
611: }
612: else
613: opt |= CD180_COR1_PARMODE_NO;
614:
615: if (!ISSET(t->c_iflag, INPCK))
616: opt |= CD180_COR1_IGNPAR;
617:
618: if (ISSET(t->c_cflag, CSTOPB))
619: opt |= CD180_COR1_STOP2;
620:
621: switch (t->c_cflag & CSIZE) {
622: case CS5:
623: opt |= CD180_COR1_CS5;
624: break;
625: case CS6:
626: opt |= CD180_COR1_CS6;
627: break;
628: case CS7:
629: opt |= CD180_COR1_CS7;
630: break;
631: default:
632: opt |= CD180_COR1_CS8;
633: break;
634: }
635: STC_WRITE(sc, STC_COR1, opt);
636: stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1);
637:
638: opt = CD180_COR2_ETC;
639: if (ISSET(t->c_cflag, CRTSCTS))
640: opt |= CD180_COR2_CTSAE;
641: STC_WRITE(sc, STC_COR2, opt);
642: stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2);
643:
644: STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD);
645: stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3);
646:
647: STC_WRITE(sc, STC_SCHR1, 0x11);
648: STC_WRITE(sc, STC_SCHR2, 0x13);
649: STC_WRITE(sc, STC_SCHR3, 0x11);
650: STC_WRITE(sc, STC_SCHR4, 0x13);
651: STC_WRITE(sc, STC_RTPR, 0x12);
652:
653: STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD);
654: STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD);
655: STC_WRITE(sc, STC_MCR, 0);
656:
657: if (t->c_ospeed) {
658: STC_WRITE(sc, STC_TBPRH, tbprh);
659: STC_WRITE(sc, STC_TBPRL, tbprl);
660: }
661:
662: if (t->c_ispeed) {
663: STC_WRITE(sc, STC_RBPRH, rbprh);
664: STC_WRITE(sc, STC_RBPRL, rbprl);
665: }
666:
667: stty_write_ccr(sc, CD180_CCR_CMD_CHAN |
668: CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN);
669:
670: sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD;
671:
672: splx(s);
673: return (0);
674: }
675:
676: int
677: sttyread(dev, uio, flags)
678: dev_t dev;
679: struct uio *uio;
680: int flags;
681: {
682: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
683: struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
684: struct tty *tp = sp->sp_tty;
685:
686: return ((*linesw[tp->t_line].l_read)(tp, uio, flags));
687: }
688:
689: int
690: sttywrite(dev, uio, flags)
691: dev_t dev;
692: struct uio *uio;
693: int flags;
694: {
695: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
696: struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
697: struct tty *tp = sp->sp_tty;
698:
699: return ((*linesw[tp->t_line].l_write)(tp, uio, flags));
700: }
701:
702: struct tty *
703: sttytty(dev)
704: dev_t dev;
705: {
706: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
707: struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
708:
709: return (sp->sp_tty);
710: }
711:
712: int
713: sttystop(tp, flags)
714: struct tty *tp;
715: int flags;
716: {
717: struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
718: struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)];
719: int s;
720:
721: s = spltty();
722: if (ISSET(tp->t_state, TS_BUSY)) {
723: if (!ISSET(tp->t_state, TS_TTSTOP))
724: SET(tp->t_state, TS_FLUSH);
725: SET(sp->sp_flags, STTYF_STOP);
726: }
727: splx(s);
728: return (0);
729: }
730:
731: void
732: stty_start(tp)
733: struct tty *tp;
734: {
735: struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
736: struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)];
737: struct spif_softc *sc = sp->sp_sc;
738: int s;
739:
740: s = spltty();
741:
742: if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
743: if (tp->t_outq.c_cc <= tp->t_lowat) {
744: if (ISSET(tp->t_state, TS_ASLEEP)) {
745: CLR(tp->t_state, TS_ASLEEP);
746: wakeup(&tp->t_outq);
747: }
748: selwakeup(&tp->t_wsel);
749: }
750: if (tp->t_outq.c_cc) {
751: sp->sp_txc = ndqb(&tp->t_outq, 0);
752: sp->sp_txp = tp->t_outq.c_cf;
753: SET(tp->t_state, TS_BUSY);
754: STC_WRITE(sc, STC_CAR, sp->sp_channel);
755: STC_WRITE(sc, STC_SRER,
756: STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
757: }
758: }
759:
760: splx(s);
761: }
762:
763: int
764: spifstcintr_rxexception(sc, needsoftp)
765: struct spif_softc *sc;
766: int *needsoftp;
767: {
768: struct stty_port *sp;
769: u_int8_t channel, *ptr;
770:
771: channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
772: sp = &sc->sc_ttys->sc_port[channel];
773: ptr = sp->sp_rput;
774: *ptr++ = STC_READ(sc, STC_RCSR);
775: *ptr++ = STC_READ(sc, STC_RDR);
776: if (ptr == sp->sp_rend)
777: ptr = sp->sp_rbuf;
778: if (ptr == sp->sp_rget) {
779: if (ptr == sp->sp_rbuf)
780: ptr = sp->sp_rend;
781: ptr -= 2;
782: SET(sp->sp_flags, STTYF_RING_OVERFLOW);
783: }
784: STC_WRITE(sc, STC_EOSRR, 0);
785: *needsoftp = 1;
786: sp->sp_rput = ptr;
787: return (1);
788: }
789:
790: int
791: spifstcintr_rx(sc, needsoftp)
792: struct spif_softc *sc;
793: int *needsoftp;
794: {
795: struct stty_port *sp;
796: u_int8_t channel, *ptr, cnt, rcsr;
797: int i;
798:
799: channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
800: sp = &sc->sc_ttys->sc_port[channel];
801: ptr = sp->sp_rput;
802: cnt = STC_READ(sc, STC_RDCR);
803: for (i = 0; i < cnt; i++) {
804: *ptr++ = 0;
805: rcsr = STC_READ(sc, STC_RCSR);
806: *ptr++ = STC_READ(sc, STC_RDR);
807: if (ptr == sp->sp_rend)
808: ptr = sp->sp_rbuf;
809: if (ptr == sp->sp_rget) {
810: if (ptr == sp->sp_rbuf)
811: ptr = sp->sp_rend;
812: ptr -= 2;
813: SET(sp->sp_flags, STTYF_RING_OVERFLOW);
814: break;
815: }
816: }
817: STC_WRITE(sc, STC_EOSRR, 0);
818: if (cnt) {
819: *needsoftp = 1;
820: sp->sp_rput = ptr;
821: }
822: return (1);
823: }
824:
825: int
826: spifstcintr_tx(sc, needsoftp)
827: struct spif_softc *sc;
828: int *needsoftp;
829: {
830: struct stty_port *sp;
831: u_int8_t channel, ch;
832: int cnt = 0;
833:
834: channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
835: sp = &sc->sc_ttys->sc_port[channel];
836: if (!ISSET(sp->sp_flags, STTYF_STOP)) {
837: if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) {
838: STC_WRITE(sc, STC_TDR, 0);
839: STC_WRITE(sc, STC_TDR, 0x81);
840: CLR(sp->sp_flags, STTYF_SET_BREAK);
841: cnt += 2;
842: }
843: if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) {
844: STC_WRITE(sc, STC_TDR, 0);
845: STC_WRITE(sc, STC_TDR, 0x83);
846: CLR(sp->sp_flags, STTYF_CLR_BREAK);
847: cnt += 2;
848: }
849:
850: while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) {
851: ch = *sp->sp_txp;
852: sp->sp_txc--;
853: sp->sp_txp++;
854:
855: if (ch == 0) {
856: STC_WRITE(sc, STC_TDR, ch);
857: cnt++;
858: }
859: STC_WRITE(sc, STC_TDR, ch);
860: cnt++;
861: }
862: }
863:
864: if (sp->sp_txc == 0 ||
865: ISSET(sp->sp_flags, STTYF_STOP)) {
866: STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) &
867: (~CD180_SRER_TXD));
868: CLR(sp->sp_flags, STTYF_STOP);
869: SET(sp->sp_flags, STTYF_DONE);
870: *needsoftp = 1;
871: }
872:
873: STC_WRITE(sc, STC_EOSRR, 0);
874:
875: return (1);
876: }
877:
878: int
879: spifstcintr_mx(sc, needsoftp)
880: struct spif_softc *sc;
881: int *needsoftp;
882: {
883: struct stty_port *sp;
884: u_int8_t channel, mcr;
885:
886: channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
887: sp = &sc->sc_ttys->sc_port[channel];
888: mcr = STC_READ(sc, STC_MCR);
889: if (mcr & CD180_MCR_CD) {
890: SET(sp->sp_flags, STTYF_CDCHG);
891: *needsoftp = 1;
892: }
893: STC_WRITE(sc, STC_MCR, 0);
894: STC_WRITE(sc, STC_EOSRR, 0);
895: return (1);
896: }
897:
898: int
899: spifstcintr(vsc)
900: void *vsc;
901: {
902: struct spif_softc *sc = (struct spif_softc *)vsc;
903: int needsoft = 0, r = 0, i;
904: u_int8_t ar;
905:
906: for (i = 0; i < 8; i++) {
907: ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK;
908: if (ar == CD180_GSVR_RXGOOD)
909: r |= spifstcintr_rx(sc, &needsoft);
910: else if (ar == CD180_GSVR_RXEXCEPTION)
911: r |= spifstcintr_rxexception(sc, &needsoft);
912: }
913:
914: for (i = 0; i < 8; i++) {
915: ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK;
916: if (ar == CD180_GSVR_TXDATA)
917: r |= spifstcintr_tx(sc, &needsoft);
918: }
919:
920: for (i = 0; i < 8; i++) {
921: ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK;
922: if (ar == CD180_GSVR_STATCHG)
923: r |= spifstcintr_mx(sc, &needsoft);
924: }
925:
926: if (needsoft)
927: softintr_schedule(sc->sc_softih);
928: return (r);
929: }
930:
931: void
932: spifsoftintr(vsc)
933: void *vsc;
934: {
935: struct spif_softc *sc = (struct spif_softc *)vsc;
936: struct stty_softc *stc = sc->sc_ttys;
937: int r = 0, i, data, s, flags;
938: u_int8_t stat, msvr;
939: struct stty_port *sp;
940: struct tty *tp;
941:
942: if (stc != NULL) {
943: for (i = 0; i < stc->sc_nports; i++) {
944: sp = &stc->sc_port[i];
945: tp = sp->sp_tty;
946:
947: if (!ISSET(tp->t_state, TS_ISOPEN))
948: continue;
949:
950: while (sp->sp_rget != sp->sp_rput) {
951: stat = sp->sp_rget[0];
952: data = sp->sp_rget[1];
953: sp->sp_rget += 2;
954: if (sp->sp_rget == sp->sp_rend)
955: sp->sp_rget = sp->sp_rbuf;
956:
957: if (stat & (CD180_RCSR_BE | CD180_RCSR_FE))
958: data |= TTY_FE;
959:
960: if (stat & CD180_RCSR_PE)
961: data |= TTY_PE;
962:
963: (*linesw[tp->t_line].l_rint)(data, tp);
964: r = 1;
965: }
966:
967: s = splhigh();
968: flags = sp->sp_flags;
969: CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG |
970: STTYF_RING_OVERFLOW);
971: splx(s);
972:
973: if (ISSET(flags, STTYF_CDCHG)) {
974: s = spltty();
975: STC_WRITE(sc, STC_CAR, i);
976: msvr = STC_READ(sc, STC_MSVR);
977: splx(s);
978:
979: sp->sp_carrier = msvr & CD180_MSVR_CD;
980: (*linesw[tp->t_line].l_modem)(tp,
981: sp->sp_carrier);
982: r = 1;
983: }
984:
985: if (ISSET(flags, STTYF_RING_OVERFLOW)) {
986: log(LOG_WARNING, "%s-%x: ring overflow\n",
987: stc->sc_dev.dv_xname, i);
988: r = 1;
989: }
990:
991: if (ISSET(flags, STTYF_DONE)) {
992: ndflush(&tp->t_outq,
993: sp->sp_txp - tp->t_outq.c_cf);
994: CLR(tp->t_state, TS_BUSY);
995: (*linesw[tp->t_line].l_start)(tp);
996: r = 1;
997: }
998: }
999: }
1000: }
1001:
1002: void
1003: stty_write_ccr(sc, val)
1004: struct spif_softc *sc;
1005: u_int8_t val;
1006: {
1007: int tries = 100000;
1008:
1009: while (STC_READ(sc, STC_CCR) && tries--)
1010: /*EMPTY*/;
1011: if (tries == 0)
1012: printf("%s: ccr timeout\n", sc->sc_dev.dv_xname);
1013: STC_WRITE(sc, STC_CCR, val);
1014: }
1015:
1016: int
1017: stty_compute_baud(speed, clock, bprlp, bprhp)
1018: speed_t speed;
1019: int clock;
1020: u_int8_t *bprlp, *bprhp;
1021: {
1022: u_int32_t rate;
1023:
1024: rate = (2 * clock) / (16 * speed);
1025: if (rate & 1)
1026: rate = (rate >> 1) + 1;
1027: else
1028: rate = rate >> 1;
1029:
1030: if (rate > 0xffff || rate == 0)
1031: return (1);
1032:
1033: *bprlp = rate & 0xff;
1034: *bprhp = (rate >> 8) & 0xff;
1035: return (0);
1036: }
1037:
1038: int
1039: sbppmatch(parent, vcf, aux)
1040: struct device *parent;
1041: void *vcf, *aux;
1042: {
1043: struct spif_softc *sc = (struct spif_softc *)parent;
1044:
1045: return (aux == sbppmatch && sc->sc_bpps == NULL);
1046: }
1047:
1048: void
1049: sbppattach(parent, dev, aux)
1050: struct device *parent, *dev;
1051: void *aux;
1052: {
1053: struct spif_softc *sc = (struct spif_softc *)parent;
1054: struct sbpp_softc *psc = (struct sbpp_softc *)dev;
1055: int port;
1056:
1057: sc->sc_bpps = psc;
1058:
1059: for (port = 0; port < sc->sc_npar; port++) {
1060: }
1061:
1062: psc->sc_nports = port;
1063: printf(": %d port%s\n", port, port == 1 ? "" : "s");
1064: }
1065:
1066: int
1067: sbppopen(dev, flags, mode, p)
1068: dev_t dev;
1069: int flags;
1070: int mode;
1071: struct proc *p;
1072: {
1073: return (ENXIO);
1074: }
1075:
1076: int
1077: sbppclose(dev, flags, mode, p)
1078: dev_t dev;
1079: int flags;
1080: int mode;
1081: struct proc *p;
1082: {
1083: return (ENXIO);
1084: }
1085:
1086: int
1087: spifppcintr(v)
1088: void *v;
1089: {
1090: return (0);
1091: }
1092:
1093: int
1094: sbppread(dev, uio, flags)
1095: dev_t dev;
1096: struct uio *uio;
1097: int flags;
1098: {
1099: return (sbpp_rw(dev, uio));
1100: }
1101:
1102: int
1103: sbppwrite(dev, uio, flags)
1104: dev_t dev;
1105: struct uio *uio;
1106: int flags;
1107: {
1108: return (sbpp_rw(dev, uio));
1109: }
1110:
1111: int
1112: sbpp_rw(dev, uio)
1113: dev_t dev;
1114: struct uio *uio;
1115: {
1116: return (ENXIO);
1117: }
1118:
1119: int
1120: sbpppoll(dev, events, p)
1121: dev_t dev;
1122: int events;
1123: struct proc *p;
1124: {
1125: return (seltrue(dev, events, p));
1126: }
1127:
1128: int
1129: sbppioctl(dev, cmd, data, flags, p)
1130: dev_t dev;
1131: u_long cmd;
1132: caddr_t data;
1133: int flags;
1134: struct proc *p;
1135: {
1136: int error;
1137:
1138: error = ENOTTY;
1139:
1140: return (error);
1141: }
CVSweb