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