spif.c revision 1.7 1 /* $NetBSD: spif.c,v 1.7 2006/07/21 16:48:52 ad Exp $ */
2 /* $OpenBSD: spif.c,v 1.12 2003/10/03 16:44:51 miod Exp $ */
3
4 /*
5 * Copyright (c) 1999-2002 Jason L. Wright (jason (at) thought.net)
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Effort sponsored in part by the Defense Advanced Research Projects
30 * Agency (DARPA) and Air Force Research Laboratory, Air Force
31 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
32 *
33 */
34
35 /*
36 * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board
37 * based heavily on Iain Hibbert's driver for the MAGMA cards
38 */
39
40 /* Ported to NetBSD 2.0 by Hauke Fath */
41
42
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: spif.c,v 1.7 2006/07/21 16:48:52 ad Exp $");
45
46 #include "spif.h"
47 #if NSPIF > 0
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/proc.h>
52 #include <sys/device.h>
53 #include <sys/file.h>
54 #include <sys/ioctl.h>
55 #include <sys/malloc.h>
56 #include <sys/tty.h>
57 #include <sys/time.h>
58 #include <sys/kernel.h>
59 #include <sys/syslog.h>
60 #include <sys/conf.h>
61 #include <sys/errno.h>
62 #include <sys/kauth.h>
63
64 #include <machine/bus.h>
65 #include <machine/intr.h>
66 #include <machine/autoconf.h>
67 #include <machine/promlib.h>
68
69 #include <dev/sbus/sbusvar.h>
70
71 #include <dev/sbus/spifvar.h>
72 #include <dev/sbus/spifreg.h>
73
74
75 /* Autoconfig stuff */
76
77 CFATTACH_DECL(spif, sizeof(struct spif_softc),
78 spif_match, spif_attach, NULL, NULL);
79
80 CFATTACH_DECL(stty, sizeof(struct stty_softc),
81 stty_match, stty_attach, NULL, NULL);
82
83 CFATTACH_DECL(sbpp, sizeof(struct sbpp_softc),
84 sbpp_match, sbpp_attach, NULL, NULL);
85
86 extern struct cfdriver spif_cd;
87 extern struct cfdriver stty_cd;
88 extern struct cfdriver sbpp_cd;
89
90 dev_type_open(stty_open);
91 dev_type_close(stty_close);
92 dev_type_read(stty_read);
93 dev_type_write(stty_write);
94 dev_type_ioctl(stty_ioctl);
95 dev_type_stop(stty_stop);
96 dev_type_tty(stty_tty);
97 dev_type_poll(stty_poll);
98
99 const struct cdevsw stty_cdevsw = {
100 stty_open, stty_close, stty_read, stty_write, stty_ioctl,
101 stty_stop, stty_tty, stty_poll, nommap, ttykqfilter, D_TTY
102 };
103
104 dev_type_open(sbpp_open);
105 dev_type_close(sbpp_close);
106 dev_type_read(sbpp_read);
107 dev_type_write(sbpp_write);
108 dev_type_ioctl(sbpp_ioctl);
109 dev_type_poll(sbpp_poll);
110
111 const struct cdevsw sbpp_cdevsw = {
112 sbpp_open, sbpp_close, sbpp_read, sbpp_write, sbpp_ioctl,
113 nostop, notty, sbpp_poll, nommap, nokqfilter,
114 };
115
116
117 /* normal STC access */
118 #define STC_WRITE(sc,r,v) \
119 bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v))
120 #define STC_READ(sc,r) \
121 bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r))
122
123 /* IACK STC access */
124 #define ISTC_WRITE(sc,r,v) \
125 bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v))
126 #define ISTC_READ(sc,r) \
127 bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r))
128
129 /* PPC access */
130 #define PPC_WRITE(sc,r,v) \
131 bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v))
132 #define PPC_READ(sc,r) \
133 bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r))
134
135 #define DTR_WRITE(sc,port,v) \
136 do { \
137 sc->sc_ttys->sc_port[(port)].sp_dtr = v; \
138 bus_space_write_1((sc)->sc_bustag, \
139 sc->sc_dtrh, port, (v == 0) ? 1 : 0); \
140 } while (0)
141
142 #define DTR_READ(sc,port) ((sc)->sc_ttys->sc_port[(port)].sp_dtr)
143
144
145 int
146 spif_match(parent, vcf, aux)
147 struct device *parent;
148 struct cfdata *vcf;
149 void *aux;
150 {
151 struct sbus_attach_args *sa = aux;
152
153 if (strcmp(vcf->cf_name, sa->sa_name) &&
154 strcmp("SUNW,spif", sa->sa_name))
155 return (0);
156 return (1);
157 }
158
159 void
160 spif_attach(parent, self, aux)
161 struct device *parent, *self;
162 void *aux;
163 {
164 struct spif_softc *sc = (struct spif_softc *)self;
165 struct sbus_attach_args *sa = aux;
166
167 if (sa->sa_nintr != 2) {
168 printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr);
169 return;
170 }
171
172 if (sa->sa_nreg != 1) {
173 printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
174 return;
175 }
176
177 sc->sc_bustag = sa->sa_bustag;
178 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
179 sa->sa_offset, sa->sa_size,
180 0, &sc->sc_regh) != 0) {
181 printf(": can't map registers\n");
182 return;
183 }
184
185 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
186 DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) {
187 printf(": can't map dtr regs\n");
188 goto fail_unmapregs;
189 }
190
191 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
192 STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) {
193 printf(": can't map dtr regs\n");
194 goto fail_unmapregs;
195 }
196
197 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
198 ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) {
199 printf(": can't map dtr regs\n");
200 goto fail_unmapregs;
201 }
202
203 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
204 PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) {
205 printf(": can't map dtr regs\n");
206 goto fail_unmapregs;
207 }
208
209 sc->sc_ppcih = bus_intr_establish(sa->sa_bustag,
210 sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc);
211 if (sc->sc_ppcih == NULL) {
212 printf(": failed to establish ppc interrupt\n");
213 goto fail_unmapregs;
214 }
215
216 sc->sc_stcih = bus_intr_establish(sa->sa_bustag,
217 sa->sa_intr[SERIAL_INTR].oi_pri, IPL_SERIAL, spif_stcintr, sc);
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, spif_softintr, 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 = prom_getpropint(sc->sc_node, "revlev", 0);
232
233 sc->sc_osc = prom_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, stty_match, NULL);
268 (void)config_found(self, sbpp_match, NULL);
269
270 return;
271
272 fail_unmapregs:
273 bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size);
274 }
275
276 int
277 stty_match(parent, vcf, aux)
278 struct device *parent;
279 struct cfdata *vcf;
280 void *aux;
281 {
282 struct spif_softc *sc = (struct spif_softc *)parent;
283
284 return (aux == stty_match && sc->sc_ttys == NULL);
285 }
286
287 void
288 stty_attach(parent, dev, aux)
289 struct device *parent, *dev;
290 void *aux;
291 {
292 struct spif_softc *sc = (struct spif_softc *)parent;
293 struct stty_softc *ssc = (struct stty_softc *)dev;
294 int port;
295
296 sc->sc_ttys = ssc;
297
298 for (port = 0; port < sc->sc_nser; port++) {
299 struct stty_port *sp = &ssc->sc_port[port];
300 struct tty *tp;
301
302 DTR_WRITE(sc, port, 0);
303
304 tp = ttymalloc();
305
306 tp->t_oproc = stty_start;
307 tp->t_param = stty_param;
308
309 sp->sp_tty = tp;
310 sp->sp_sc = sc;
311 sp->sp_channel = port;
312
313 sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT);
314 if(sp->sp_rbuf == NULL)
315 break;
316
317 sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE;
318 }
319
320 ssc->sc_nports = port;
321
322 printf(": %d tty%s\n", port, port == 1 ? "" : "s");
323 }
324
325 int
326 stty_open(dev, flags, mode, l)
327 dev_t dev;
328 int flags;
329 int mode;
330 struct lwp *l;
331 {
332 struct spif_softc *csc;
333 struct stty_softc *sc;
334 struct stty_port *sp;
335 struct tty *tp;
336 int card = SPIF_CARD(dev);
337 int port = SPIF_PORT(dev);
338 int s;
339
340 if (card >= stty_cd.cd_ndevs || card >= spif_cd.cd_ndevs)
341 return (ENXIO);
342
343 sc = stty_cd.cd_devs[card];
344 csc = spif_cd.cd_devs[card];
345 if (sc == NULL || csc == NULL)
346 return (ENXIO);
347
348 if (port >= sc->sc_nports)
349 return (ENXIO);
350
351 sp = &sc->sc_port[port];
352 tp = sp->sp_tty;
353 tp->t_dev = dev;
354
355 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
356 ttychars(tp);
357 tp->t_iflag = TTYDEF_IFLAG;
358 tp->t_oflag = TTYDEF_OFLAG;
359 tp->t_cflag = TTYDEF_CFLAG;
360 if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL))
361 SET(tp->t_cflag, CLOCAL);
362 if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS))
363 SET(tp->t_cflag, CRTSCTS);
364 if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF))
365 SET(tp->t_cflag, MDMBUF);
366 tp->t_lflag = TTYDEF_LFLAG;
367 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
368
369 sp->sp_rput = sp->sp_rget = sp->sp_rbuf;
370
371 s = spltty();
372
373 STC_WRITE(csc, STC_CAR, sp->sp_channel);
374 stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
375 STC_WRITE(csc, STC_CAR, sp->sp_channel);
376
377 stty_param(tp, &tp->t_termios);
378
379 ttsetwater(tp);
380
381 STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD);
382
383 if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier)
384 SET(tp->t_state, TS_CARR_ON);
385 else
386 CLR(tp->t_state, TS_CARR_ON);
387 }
388 else if (ISSET(tp->t_state, TS_XCLUDE) &&
389 kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
390 &l->l_acflag) != 0) {
391 return (EBUSY);
392 } else {
393 s = spltty();
394 }
395
396 if (!ISSET(flags, O_NONBLOCK)) {
397 while (!ISSET(tp->t_cflag, CLOCAL) &&
398 !ISSET(tp->t_state, TS_CARR_ON)) {
399 int error;
400 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
401 "sttycd", 0);
402 if (error != 0) {
403 splx(s);
404 return (error);
405 }
406 }
407 }
408
409 splx(s);
410
411 return ((*tp->t_linesw->l_open)(dev, tp));
412 }
413
414 int
415 stty_close(dev, flags, mode, l)
416 dev_t dev;
417 int flags;
418 int mode;
419 struct lwp *l;
420 {
421 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
422 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
423 struct spif_softc *csc = sp->sp_sc;
424 struct tty *tp = sp->sp_tty;
425 int port = SPIF_PORT(dev);
426 int s;
427
428 (*tp->t_linesw->l_close)(tp, flags);
429 s = spltty();
430
431 if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
432 stty_modem_control(sp, 0, DMSET);
433 STC_WRITE(csc, STC_CAR, port);
434 STC_WRITE(csc, STC_CCR,
435 CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
436 }
437
438 splx(s);
439 ttyclose(tp);
440 return (0);
441 }
442
443 int
444 stty_ioctl(dev, cmd, data, flags, l)
445 dev_t dev;
446 u_long cmd;
447 caddr_t data;
448 int flags;
449 struct lwp *l;
450 {
451 struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)];
452 struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
453 struct spif_softc *sc = sp->sp_sc;
454 struct tty *tp = sp->sp_tty;
455 int error;
456
457 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l);
458 if (error >= 0)
459 return (error);
460
461 error = ttioctl(tp, cmd, data, flags, l);
462 if (error >= 0)
463 return (error);
464
465 error = 0;
466
467 switch (cmd) {
468 case TIOCSBRK:
469 SET(sp->sp_flags, STTYF_SET_BREAK);
470 STC_WRITE(sc, STC_CAR, sp->sp_channel);
471 STC_WRITE(sc, STC_SRER,
472 STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
473 break;
474 case TIOCCBRK:
475 SET(sp->sp_flags, STTYF_CLR_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 TIOCSDTR:
481 stty_modem_control(sp, TIOCM_DTR, DMBIS);
482 break;
483 case TIOCCDTR:
484 stty_modem_control(sp, TIOCM_DTR, DMBIC);
485 break;
486 case TIOCMBIS:
487 stty_modem_control(sp, *((int *)data), DMBIS);
488 break;
489 case TIOCMBIC:
490 stty_modem_control(sp, *((int *)data), DMBIC);
491 break;
492 case TIOCMGET:
493 *((int *)data) = stty_modem_control(sp, 0, DMGET);
494 break;
495 case TIOCMSET:
496 stty_modem_control(sp, *((int *)data), DMSET);
497 break;
498 case TIOCGFLAGS:
499 *((int *)data) = sp->sp_openflags;
500 break;
501 case TIOCSFLAGS:
502 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
503 &l->l_acflag) )
504 error = EPERM;
505 else
506 sp->sp_openflags = *((int *)data) &
507 (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
508 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
509 break;
510 default:
511 error = ENOTTY;
512 }
513
514 return (error);
515 }
516
517 int
518 stty_modem_control(sp, bits, how)
519 struct stty_port *sp;
520 int bits, how;
521 {
522 struct spif_softc *csc = sp->sp_sc;
523 struct tty *tp = sp->sp_tty;
524 int s, msvr;
525
526 s = spltty();
527 STC_WRITE(csc, STC_CAR, sp->sp_channel);
528
529 switch (how) {
530 case DMGET:
531 bits = TIOCM_LE;
532 if (DTR_READ(csc, sp->sp_channel))
533 bits |= TIOCM_DTR;
534 msvr = STC_READ(csc, STC_MSVR);
535 if (ISSET(msvr, CD180_MSVR_DSR))
536 bits |= TIOCM_DSR;
537 if (ISSET(msvr, CD180_MSVR_CD))
538 bits |= TIOCM_CD;
539 if (ISSET(msvr, CD180_MSVR_CTS))
540 bits |= TIOCM_CTS;
541 if (ISSET(msvr, CD180_MSVR_RTS))
542 bits |= TIOCM_RTS;
543 break;
544 case DMSET:
545 DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0);
546 if (ISSET(bits, TIOCM_RTS))
547 STC_WRITE(csc, STC_MSVR,
548 STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
549 else
550 STC_WRITE(csc, STC_MSVR,
551 STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
552 break;
553 case DMBIS:
554 if (ISSET(bits, TIOCM_DTR))
555 DTR_WRITE(csc, sp->sp_channel, 1);
556 if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS))
557 STC_WRITE(csc, STC_MSVR,
558 STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
559 break;
560 case DMBIC:
561 if (ISSET(bits, TIOCM_DTR))
562 DTR_WRITE(csc, sp->sp_channel, 0);
563 if (ISSET(bits, TIOCM_RTS))
564 STC_WRITE(csc, STC_MSVR,
565 STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
566 break;
567 }
568
569 splx(s);
570 return (bits);
571 }
572
573 int
574 stty_param(tp, t)
575 struct tty *tp;
576 struct termios *t;
577 {
578 struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
579 struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)];
580 struct spif_softc *sc = sp->sp_sc;
581 u_int8_t rbprl, rbprh, tbprl, tbprh;
582 int s, opt;
583
584 if (t->c_ospeed &&
585 stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh))
586 return (EINVAL);
587
588 if (t->c_ispeed &&
589 stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh))
590 return (EINVAL);
591
592 s = spltty();
593
594 /* hang up line if ospeed is zero, otherwise raise DTR */
595 stty_modem_control(sp, TIOCM_DTR,
596 (t->c_ospeed == 0 ? DMBIC : DMBIS));
597
598 STC_WRITE(sc, STC_CAR, sp->sp_channel);
599
600 opt = 0;
601 if (ISSET(t->c_cflag, PARENB)) {
602 opt |= CD180_COR1_PARMODE_NORMAL;
603 opt |= (ISSET(t->c_cflag, PARODD) ?
604 CD180_COR1_ODDPAR :
605 CD180_COR1_EVENPAR);
606 }
607 else
608 opt |= CD180_COR1_PARMODE_NO;
609
610 if (!ISSET(t->c_iflag, INPCK))
611 opt |= CD180_COR1_IGNPAR;
612
613 if (ISSET(t->c_cflag, CSTOPB))
614 opt |= CD180_COR1_STOP2;
615
616 switch (t->c_cflag & CSIZE) {
617 case CS5:
618 opt |= CD180_COR1_CS5;
619 break;
620 case CS6:
621 opt |= CD180_COR1_CS6;
622 break;
623 case CS7:
624 opt |= CD180_COR1_CS7;
625 break;
626 default:
627 opt |= CD180_COR1_CS8;
628 break;
629 }
630 STC_WRITE(sc, STC_COR1, opt);
631 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1);
632
633 opt = CD180_COR2_ETC;
634 if (ISSET(t->c_cflag, CRTSCTS))
635 opt |= CD180_COR2_CTSAE;
636 STC_WRITE(sc, STC_COR2, opt);
637 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2);
638
639 STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD);
640 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3);
641
642 STC_WRITE(sc, STC_SCHR1, 0x11);
643 STC_WRITE(sc, STC_SCHR2, 0x13);
644 STC_WRITE(sc, STC_SCHR3, 0x11);
645 STC_WRITE(sc, STC_SCHR4, 0x13);
646 STC_WRITE(sc, STC_RTPR, 0x12);
647
648 STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD);
649 STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD);
650 STC_WRITE(sc, STC_MCR, 0);
651
652 if (t->c_ospeed) {
653 STC_WRITE(sc, STC_TBPRH, tbprh);
654 STC_WRITE(sc, STC_TBPRL, tbprl);
655 }
656
657 if (t->c_ispeed) {
658 STC_WRITE(sc, STC_RBPRH, rbprh);
659 STC_WRITE(sc, STC_RBPRL, rbprl);
660 }
661
662 stty_write_ccr(sc, CD180_CCR_CMD_CHAN |
663 CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN);
664
665 sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD;
666
667 splx(s);
668 return (0);
669 }
670
671 int
672 stty_read(dev, uio, flags)
673 dev_t dev;
674 struct uio *uio;
675 int flags;
676 {
677 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
678 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
679 struct tty *tp = sp->sp_tty;
680
681 return ((*tp->t_linesw->l_read)(tp, uio, flags));
682 }
683
684 int
685 stty_write(dev, uio, flags)
686 dev_t dev;
687 struct uio *uio;
688 int flags;
689 {
690 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
691 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
692 struct tty *tp = sp->sp_tty;
693
694 return ((*tp->t_linesw->l_write)(tp, uio, flags));
695 }
696
697 int
698 stty_poll(dev, events, l)
699 dev_t dev;
700 int events;
701 struct lwp *l;
702 {
703 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
704 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
705 struct tty *tp = sp->sp_tty;
706
707 return ((*tp->t_linesw->l_poll)(tp, events, l));
708 }
709
710 struct tty *
711 stty_tty(dev)
712 dev_t dev;
713 {
714 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
715 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
716
717 return (sp->sp_tty);
718 }
719
720 void
721 stty_stop(tp, flags)
722 struct tty *tp;
723 int flags;
724 {
725 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
726 struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)];
727 int s;
728
729 s = spltty();
730 if (ISSET(tp->t_state, TS_BUSY)) {
731 if (!ISSET(tp->t_state, TS_TTSTOP))
732 SET(tp->t_state, TS_FLUSH);
733 SET(sp->sp_flags, STTYF_STOP);
734 }
735 splx(s);
736 }
737
738 void
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
771 spif_stcintr_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
798 spif_stcintr_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
833 spif_stcintr_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
886 spif_stcintr_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
906 spif_stcintr(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 |= spif_stcintr_rx(sc, &needsoft);
917 else if (ar == CD180_GSVR_RXEXCEPTION)
918 r |= spif_stcintr_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 |= spif_stcintr_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 |= spif_stcintr_mx(sc, &needsoft);
931 }
932
933 if (needsoft)
934 softintr_schedule(sc->sc_softih);
935 return (r);
936 }
937
938 void
939 spif_softintr(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 (*tp->t_linesw->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 (*tp->t_linesw->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 (*tp->t_linesw->l_start)(tp);
1003 r = 1;
1004 }
1005 }
1006 }
1007 }
1008
1009 void
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
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
1046 sbpp_match(parent, vcf, aux)
1047 struct device *parent;
1048 struct cfdata *vcf;
1049 void *aux;
1050 {
1051 struct spif_softc *sc = (struct spif_softc *)parent;
1052
1053 return (aux == sbpp_match && sc->sc_bpps == NULL);
1054 }
1055
1056 void
1057 sbpp_attach(parent, dev, aux)
1058 struct device *parent, *dev;
1059 void *aux;
1060 {
1061 struct spif_softc *sc = (struct spif_softc *)parent;
1062 struct sbpp_softc *psc = (struct sbpp_softc *)dev;
1063 int port;
1064
1065 sc->sc_bpps = psc;
1066
1067 for (port = 0; port < sc->sc_npar; port++) {
1068 }
1069
1070 psc->sc_nports = port;
1071 printf(": %d port%s\n", port, port == 1 ? "" : "s");
1072 }
1073
1074 int
1075 sbpp_open(dev, flags, mode, l)
1076 dev_t dev;
1077 int flags;
1078 int mode;
1079 struct lwp *l;
1080 {
1081 return (ENXIO);
1082 }
1083
1084 int
1085 sbpp_close(dev, flags, mode, l)
1086 dev_t dev;
1087 int flags;
1088 int mode;
1089 struct lwp *l;
1090 {
1091 return (ENXIO);
1092 }
1093
1094 int
1095 spif_ppcintr(v)
1096 void *v;
1097 {
1098 return (0);
1099 }
1100
1101 int
1102 sbpp_read(dev, uio, flags)
1103 dev_t dev;
1104 struct uio *uio;
1105 int flags;
1106 {
1107 return (sbpp_rw(dev, uio));
1108 }
1109
1110 int
1111 sbpp_write(dev, uio, flags)
1112 dev_t dev;
1113 struct uio *uio;
1114 int flags;
1115 {
1116 return (sbpp_rw(dev, uio));
1117 }
1118
1119 int
1120 sbpp_rw(dev, uio)
1121 dev_t dev;
1122 struct uio *uio;
1123 {
1124 return (ENXIO);
1125 }
1126
1127 int
1128 sbpp_poll(dev, events, l)
1129 dev_t dev;
1130 int events;
1131 struct lwp *l;
1132 {
1133 return (seltrue(dev, events, l));
1134 }
1135
1136 int
1137 sbpp_ioctl(dev, cmd, data, flags, l)
1138 dev_t dev;
1139 u_long cmd;
1140 caddr_t data;
1141 int flags;
1142 struct lwp *l;
1143 {
1144 int error;
1145
1146 error = ENOTTY;
1147
1148 return (error);
1149 }
1150
1151 #endif /* NSPIF */
1152