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