spif.c revision 1.31 1 /* $NetBSD: spif.c,v 1.31 2014/07/25 08:10:38 dholland 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.31 2014/07/25 08:10:38 dholland 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 #include <sys/intr.h>
64
65 #include <sys/bus.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 #include "ioconf.h"
75
76 /* Autoconfig stuff */
77
78 CFATTACH_DECL_NEW(spif, sizeof(struct spif_softc),
79 spif_match, spif_attach, NULL, NULL);
80
81 CFATTACH_DECL_NEW(stty, sizeof(struct stty_softc),
82 stty_match, stty_attach, NULL, NULL);
83
84 CFATTACH_DECL_NEW(sbpp, sizeof(struct sbpp_softc),
85 sbpp_match, sbpp_attach, NULL, NULL);
86
87 dev_type_open(stty_open);
88 dev_type_close(stty_close);
89 dev_type_read(stty_read);
90 dev_type_write(stty_write);
91 dev_type_ioctl(stty_ioctl);
92 dev_type_stop(stty_stop);
93 dev_type_tty(stty_tty);
94 dev_type_poll(stty_poll);
95
96 const struct cdevsw stty_cdevsw = {
97 .d_open = stty_open,
98 .d_close = stty_close,
99 .d_read = stty_read,
100 .d_write = stty_write,
101 .d_ioctl = stty_ioctl,
102 .d_stop = stty_stop,
103 .d_tty = stty_tty,
104 .d_poll = stty_poll,
105 .d_mmap = nommap,
106 .d_kqfilter = ttykqfilter,
107 .d_discard = nodiscard,
108 .d_flag = D_TTY
109 };
110
111 dev_type_open(sbpp_open);
112 dev_type_close(sbpp_close);
113 dev_type_read(sbpp_read);
114 dev_type_write(sbpp_write);
115 dev_type_ioctl(sbpp_ioctl);
116 dev_type_poll(sbpp_poll);
117
118 const struct cdevsw sbpp_cdevsw = {
119 .d_open = sbpp_open,
120 .d_close = sbpp_close,
121 .d_read = sbpp_read,
122 .d_write = sbpp_write,
123 .d_ioctl = sbpp_ioctl,
124 .d_stop = nostop,
125 .d_tty = notty,
126 .d_poll = sbpp_poll,
127 .d_mmap = nommap,
128 .d_kqfilter = nokqfilter,
129 .d_discard = nodiscard,
130 .d_flag = D_OTHER
131 };
132
133
134 /* normal STC access */
135 #define STC_WRITE(sc,r,v) \
136 bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v))
137 #define STC_READ(sc,r) \
138 bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r))
139
140 /* IACK STC access */
141 #define ISTC_WRITE(sc,r,v) \
142 bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v))
143 #define ISTC_READ(sc,r) \
144 bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r))
145
146 /* PPC access */
147 #define PPC_WRITE(sc,r,v) \
148 bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v))
149 #define PPC_READ(sc,r) \
150 bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r))
151
152 #define DTR_WRITE(sc,port,v) \
153 do { \
154 sc->sc_ttys->sc_port[(port)].sp_dtr = v; \
155 bus_space_write_1((sc)->sc_bustag, \
156 sc->sc_dtrh, port, (v == 0) ? 1 : 0); \
157 } while (0)
158
159 #define DTR_READ(sc,port) ((sc)->sc_ttys->sc_port[(port)].sp_dtr)
160
161
162 int
163 spif_match(device_t parent, cfdata_t vcf, void *aux)
164 {
165 struct sbus_attach_args *sa = aux;
166
167 if (strcmp(vcf->cf_name, sa->sa_name) &&
168 strcmp("SUNW,spif", sa->sa_name))
169 return (0);
170 return (1);
171 }
172
173 void
174 spif_attach(device_t parent, device_t self, void *aux)
175 {
176 struct spif_softc *sc = device_private(self);
177 struct sbus_attach_args *sa = aux;
178
179 sc->sc_dev = self;
180
181 if (sa->sa_nintr != 2) {
182 printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr);
183 return;
184 }
185
186 if (sa->sa_nreg != 1) {
187 printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
188 return;
189 }
190
191 sc->sc_bustag = sa->sa_bustag;
192 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
193 sa->sa_offset, sa->sa_size,
194 0, &sc->sc_regh) != 0) {
195 printf(": can't map registers\n");
196 return;
197 }
198
199 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
200 DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 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 STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) {
207 printf(": can't map dtr regs\n");
208 goto fail_unmapregs;
209 }
210
211 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
212 ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) {
213 printf(": can't map dtr regs\n");
214 goto fail_unmapregs;
215 }
216
217 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
218 PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) {
219 printf(": can't map dtr regs\n");
220 goto fail_unmapregs;
221 }
222
223 sc->sc_ppcih = bus_intr_establish(sa->sa_bustag,
224 sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc);
225 if (sc->sc_ppcih == NULL) {
226 printf(": failed to establish ppc interrupt\n");
227 goto fail_unmapregs;
228 }
229
230 sc->sc_stcih = bus_intr_establish(sa->sa_bustag,
231 sa->sa_intr[SERIAL_INTR].oi_pri, IPL_SERIAL, spif_stcintr, sc);
232 if (sc->sc_stcih == NULL) {
233 printf(": failed to establish stc interrupt\n");
234 goto fail_unmapregs;
235 }
236
237 sc->sc_softih = softint_establish(SOFTINT_SERIAL, spif_softintr, sc);
238 if (sc->sc_softih == NULL) {
239 printf(": can't get soft intr\n");
240 goto fail_unmapregs;
241 }
242
243 sc->sc_node = sa->sa_node;
244
245 sc->sc_rev = prom_getpropint(sc->sc_node, "revlev", 0);
246
247 sc->sc_osc = prom_getpropint(sc->sc_node, "verosc", 0);
248 switch (sc->sc_osc) {
249 case SPIF_OSC10:
250 sc->sc_osc = 10000000;
251 break;
252 case SPIF_OSC9:
253 default:
254 sc->sc_osc = 9830400;
255 break;
256 }
257
258 sc->sc_nser = 8;
259 sc->sc_npar = 1;
260
261 sc->sc_rev2 = STC_READ(sc, STC_GFRCR);
262 STC_WRITE(sc, STC_GSVR, 0);
263
264 stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL);
265 while (STC_READ(sc, STC_GSVR) != 0xff);
266 while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2);
267
268 STC_WRITE(sc, STC_PPRH, CD180_PPRH);
269 STC_WRITE(sc, STC_PPRL, CD180_PPRL);
270 STC_WRITE(sc, STC_MSMR, SPIF_MSMR);
271 STC_WRITE(sc, STC_TSMR, SPIF_TSMR);
272 STC_WRITE(sc, STC_RSMR, SPIF_RSMR);
273 STC_WRITE(sc, STC_GSVR, 0);
274 STC_WRITE(sc, STC_GSCR1, 0);
275 STC_WRITE(sc, STC_GSCR2, 0);
276 STC_WRITE(sc, STC_GSCR3, 0);
277
278 printf(": rev %x chiprev %x osc %sMHz\n",
279 sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc));
280
281 (void)config_found(self, stty_match, NULL);
282 (void)config_found(self, sbpp_match, NULL);
283
284 return;
285
286 fail_unmapregs:
287 bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size);
288 }
289
290 int
291 stty_match(device_t parent, cfdata_t vcf, void *aux)
292 {
293 struct spif_softc *sc = device_private(parent);
294
295 return (aux == stty_match && sc->sc_ttys == NULL);
296 }
297
298 void
299 stty_attach(device_t parent, device_t dev, void *aux)
300 {
301 struct spif_softc *sc = device_private(parent);
302 struct stty_softc *ssc = device_private(dev);
303 int port;
304
305 sc->sc_dev = dev;
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 = tty_alloc();
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
336 stty_open(dev_t dev, int flags, int mode, struct lwp *l)
337 {
338 struct spif_softc *csc;
339 struct stty_softc *sc;
340 struct stty_port *sp;
341 struct tty *tp;
342 int card = SPIF_CARD(dev);
343 int port = SPIF_PORT(dev);
344
345 sc = device_lookup_private(&stty_cd, card);
346 csc = device_lookup_private(&spif_cd, card);
347 if (sc == NULL || csc == NULL)
348 return (ENXIO);
349
350 if (port >= sc->sc_nports)
351 return (ENXIO);
352
353 sp = &sc->sc_port[port];
354 tp = sp->sp_tty;
355 tp->t_dev = dev;
356
357 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
358 return (EBUSY);
359
360 mutex_spin_enter(&tty_lock);
361 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
362 ttychars(tp);
363 tp->t_iflag = TTYDEF_IFLAG;
364 tp->t_oflag = TTYDEF_OFLAG;
365 tp->t_cflag = TTYDEF_CFLAG;
366 if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL))
367 SET(tp->t_cflag, CLOCAL);
368 if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS))
369 SET(tp->t_cflag, CRTSCTS);
370 if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF))
371 SET(tp->t_cflag, MDMBUF);
372 tp->t_lflag = TTYDEF_LFLAG;
373 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
374
375 sp->sp_rput = sp->sp_rget = sp->sp_rbuf;
376
377 STC_WRITE(csc, STC_CAR, sp->sp_channel);
378 stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
379 STC_WRITE(csc, STC_CAR, sp->sp_channel);
380
381 stty_param(tp, &tp->t_termios);
382
383 ttsetwater(tp);
384
385 STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD);
386
387 if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier)
388 SET(tp->t_state, TS_CARR_ON);
389 else
390 CLR(tp->t_state, TS_CARR_ON);
391 }
392
393 if (!ISSET(flags, O_NONBLOCK)) {
394 while (!ISSET(tp->t_cflag, CLOCAL) &&
395 !ISSET(tp->t_state, TS_CARR_ON)) {
396 int error;
397 error = ttysleep(tp, &tp->t_rawcv, true, 0);
398 if (error != 0) {
399 mutex_spin_exit(&tty_lock);
400 return (error);
401 }
402 }
403 }
404 mutex_spin_exit(&tty_lock);
405
406 return ((*tp->t_linesw->l_open)(dev, tp));
407 }
408
409 int
410 stty_close(dev_t dev, int flags, int mode, struct lwp *l)
411 {
412 struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev));
413 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
414 struct spif_softc *csc = sp->sp_sc;
415 struct tty *tp = sp->sp_tty;
416 int port = SPIF_PORT(dev);
417 int s;
418
419 (*tp->t_linesw->l_close)(tp, flags);
420 s = spltty();
421
422 if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
423 stty_modem_control(sp, 0, DMSET);
424 STC_WRITE(csc, STC_CAR, port);
425 STC_WRITE(csc, STC_CCR,
426 CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
427 }
428
429 splx(s);
430 ttyclose(tp);
431 return (0);
432 }
433
434 int
435 stty_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
436 {
437 struct stty_softc *stc = device_lookup_private(&stty_cd,
438 SPIF_CARD(dev));
439 struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
440 struct spif_softc *sc = sp->sp_sc;
441 struct tty *tp = sp->sp_tty;
442 int error;
443
444 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l);
445 if (error >= 0)
446 return (error);
447
448 error = ttioctl(tp, cmd, data, flags, l);
449 if (error >= 0)
450 return (error);
451
452 error = 0;
453
454 switch (cmd) {
455 case TIOCSBRK:
456 SET(sp->sp_flags, STTYF_SET_BREAK);
457 STC_WRITE(sc, STC_CAR, sp->sp_channel);
458 STC_WRITE(sc, STC_SRER,
459 STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
460 break;
461 case TIOCCBRK:
462 SET(sp->sp_flags, STTYF_CLR_BREAK);
463 STC_WRITE(sc, STC_CAR, sp->sp_channel);
464 STC_WRITE(sc, STC_SRER,
465 STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
466 break;
467 case TIOCSDTR:
468 stty_modem_control(sp, TIOCM_DTR, DMBIS);
469 break;
470 case TIOCCDTR:
471 stty_modem_control(sp, TIOCM_DTR, DMBIC);
472 break;
473 case TIOCMBIS:
474 stty_modem_control(sp, *((int *)data), DMBIS);
475 break;
476 case TIOCMBIC:
477 stty_modem_control(sp, *((int *)data), DMBIC);
478 break;
479 case TIOCMGET:
480 *((int *)data) = stty_modem_control(sp, 0, DMGET);
481 break;
482 case TIOCMSET:
483 stty_modem_control(sp, *((int *)data), DMSET);
484 break;
485 case TIOCGFLAGS:
486 *((int *)data) = sp->sp_openflags;
487 break;
488 case TIOCSFLAGS:
489 if (kauth_authorize_device_tty(l->l_cred,
490 KAUTH_DEVICE_TTY_PRIVSET, tp))
491 error = EPERM;
492 else
493 sp->sp_openflags = *((int *)data) &
494 (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
495 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
496 break;
497 default:
498 error = ENOTTY;
499 }
500
501 return (error);
502 }
503
504 int
505 stty_modem_control(struct stty_port *sp, int bits, int how)
506 {
507 struct spif_softc *csc = sp->sp_sc;
508 struct tty *tp = sp->sp_tty;
509 int s, msvr;
510
511 s = spltty();
512 STC_WRITE(csc, STC_CAR, sp->sp_channel);
513
514 switch (how) {
515 case DMGET:
516 bits = TIOCM_LE;
517 if (DTR_READ(csc, sp->sp_channel))
518 bits |= TIOCM_DTR;
519 msvr = STC_READ(csc, STC_MSVR);
520 if (ISSET(msvr, CD180_MSVR_DSR))
521 bits |= TIOCM_DSR;
522 if (ISSET(msvr, CD180_MSVR_CD))
523 bits |= TIOCM_CD;
524 if (ISSET(msvr, CD180_MSVR_CTS))
525 bits |= TIOCM_CTS;
526 if (ISSET(msvr, CD180_MSVR_RTS))
527 bits |= TIOCM_RTS;
528 break;
529 case DMSET:
530 DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0);
531 if (ISSET(bits, TIOCM_RTS))
532 STC_WRITE(csc, STC_MSVR,
533 STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
534 else
535 STC_WRITE(csc, STC_MSVR,
536 STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
537 break;
538 case DMBIS:
539 if (ISSET(bits, TIOCM_DTR))
540 DTR_WRITE(csc, sp->sp_channel, 1);
541 if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS))
542 STC_WRITE(csc, STC_MSVR,
543 STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
544 break;
545 case DMBIC:
546 if (ISSET(bits, TIOCM_DTR))
547 DTR_WRITE(csc, sp->sp_channel, 0);
548 if (ISSET(bits, TIOCM_RTS))
549 STC_WRITE(csc, STC_MSVR,
550 STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
551 break;
552 }
553
554 splx(s);
555 return (bits);
556 }
557
558 int
559 stty_param(struct tty *tp, struct termios *t)
560 {
561 struct stty_softc *st = device_lookup_private(&stty_cd,
562 SPIF_CARD(tp->t_dev));
563 struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)];
564 struct spif_softc *sc = sp->sp_sc;
565 uint8_t rbprl = 0, rbprh = 0, tbprl = 0, tbprh = 0;
566 int s, opt;
567
568 if (t->c_ospeed &&
569 stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh))
570 return (EINVAL);
571
572 if (t->c_ispeed &&
573 stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh))
574 return (EINVAL);
575
576 s = spltty();
577
578 /* hang up line if ospeed is zero, otherwise raise DTR */
579 stty_modem_control(sp, TIOCM_DTR,
580 (t->c_ospeed == 0 ? DMBIC : DMBIS));
581
582 STC_WRITE(sc, STC_CAR, sp->sp_channel);
583
584 opt = 0;
585 if (ISSET(t->c_cflag, PARENB)) {
586 opt |= CD180_COR1_PARMODE_NORMAL;
587 opt |= (ISSET(t->c_cflag, PARODD) ?
588 CD180_COR1_ODDPAR :
589 CD180_COR1_EVENPAR);
590 }
591 else
592 opt |= CD180_COR1_PARMODE_NO;
593
594 if (!ISSET(t->c_iflag, INPCK))
595 opt |= CD180_COR1_IGNPAR;
596
597 if (ISSET(t->c_cflag, CSTOPB))
598 opt |= CD180_COR1_STOP2;
599
600 switch (t->c_cflag & CSIZE) {
601 case CS5:
602 opt |= CD180_COR1_CS5;
603 break;
604 case CS6:
605 opt |= CD180_COR1_CS6;
606 break;
607 case CS7:
608 opt |= CD180_COR1_CS7;
609 break;
610 default:
611 opt |= CD180_COR1_CS8;
612 break;
613 }
614 STC_WRITE(sc, STC_COR1, opt);
615 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1);
616
617 opt = CD180_COR2_ETC;
618 if (ISSET(t->c_cflag, CRTSCTS))
619 opt |= CD180_COR2_CTSAE;
620 STC_WRITE(sc, STC_COR2, opt);
621 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2);
622
623 STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD);
624 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3);
625
626 STC_WRITE(sc, STC_SCHR1, 0x11);
627 STC_WRITE(sc, STC_SCHR2, 0x13);
628 STC_WRITE(sc, STC_SCHR3, 0x11);
629 STC_WRITE(sc, STC_SCHR4, 0x13);
630 STC_WRITE(sc, STC_RTPR, 0x12);
631
632 STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD);
633 STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD);
634 STC_WRITE(sc, STC_MCR, 0);
635
636 if (t->c_ospeed) {
637 STC_WRITE(sc, STC_TBPRH, tbprh);
638 STC_WRITE(sc, STC_TBPRL, tbprl);
639 }
640
641 if (t->c_ispeed) {
642 STC_WRITE(sc, STC_RBPRH, rbprh);
643 STC_WRITE(sc, STC_RBPRL, rbprl);
644 }
645
646 stty_write_ccr(sc, CD180_CCR_CMD_CHAN |
647 CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN);
648
649 sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD;
650
651 splx(s);
652 return (0);
653 }
654
655 int
656 stty_read(dev_t dev, struct uio *uio, int flags)
657 {
658 struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev));
659 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
660 struct tty *tp = sp->sp_tty;
661
662 return ((*tp->t_linesw->l_read)(tp, uio, flags));
663 }
664
665 int
666 stty_write(dev_t dev, struct uio *uio, int flags)
667 {
668 struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev));
669 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
670 struct tty *tp = sp->sp_tty;
671
672 return ((*tp->t_linesw->l_write)(tp, uio, flags));
673 }
674
675 int
676 stty_poll(dev_t dev, int events, struct lwp *l)
677 {
678 struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev));
679 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
680 struct tty *tp = sp->sp_tty;
681
682 return ((*tp->t_linesw->l_poll)(tp, events, l));
683 }
684
685 struct tty *
686 stty_tty(dev_t dev)
687 {
688 struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev));
689 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
690
691 return (sp->sp_tty);
692 }
693
694 void
695 stty_stop(struct tty *tp, int flags)
696 {
697 struct stty_softc *sc = device_lookup_private(&stty_cd,
698 SPIF_CARD(tp->t_dev));
699 struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)];
700 int s;
701
702 s = spltty();
703 if (ISSET(tp->t_state, TS_BUSY)) {
704 if (!ISSET(tp->t_state, TS_TTSTOP))
705 SET(tp->t_state, TS_FLUSH);
706 SET(sp->sp_flags, STTYF_STOP);
707 }
708 splx(s);
709 }
710
711 void
712 stty_start(struct tty *tp)
713 {
714 struct stty_softc *stc = device_lookup_private(&stty_cd,
715 SPIF_CARD(tp->t_dev));
716 struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)];
717 struct spif_softc *sc = sp->sp_sc;
718 int s;
719
720 s = spltty();
721
722 if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
723 if (ttypull(tp)) {
724 sp->sp_txc = ndqb(&tp->t_outq, 0);
725 sp->sp_txp = tp->t_outq.c_cf;
726 SET(tp->t_state, TS_BUSY);
727 STC_WRITE(sc, STC_CAR, sp->sp_channel);
728 STC_WRITE(sc, STC_SRER,
729 STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
730 }
731 }
732
733 splx(s);
734 }
735
736 int
737 spif_stcintr_rxexception(struct spif_softc *sc, int *needsoftp)
738 {
739 struct stty_port *sp;
740 uint8_t channel, *ptr;
741
742 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
743 sp = &sc->sc_ttys->sc_port[channel];
744 ptr = sp->sp_rput;
745 *ptr++ = STC_READ(sc, STC_RCSR);
746 *ptr++ = STC_READ(sc, STC_RDR);
747 if (ptr == sp->sp_rend)
748 ptr = sp->sp_rbuf;
749 if (ptr == sp->sp_rget) {
750 if (ptr == sp->sp_rbuf)
751 ptr = sp->sp_rend;
752 ptr -= 2;
753 SET(sp->sp_flags, STTYF_RING_OVERFLOW);
754 }
755 STC_WRITE(sc, STC_EOSRR, 0);
756 *needsoftp = 1;
757 sp->sp_rput = ptr;
758 return (1);
759 }
760
761 int
762 spif_stcintr_rx(struct spif_softc *sc, int *needsoftp)
763 {
764 struct stty_port *sp;
765 uint8_t channel, *ptr, cnt;
766 int i;
767
768 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
769 sp = &sc->sc_ttys->sc_port[channel];
770 ptr = sp->sp_rput;
771 cnt = STC_READ(sc, STC_RDCR);
772 for (i = 0; i < cnt; i++) {
773 *ptr++ = 0;
774 (void)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 break;
784 }
785 }
786 STC_WRITE(sc, STC_EOSRR, 0);
787 if (cnt) {
788 *needsoftp = 1;
789 sp->sp_rput = ptr;
790 }
791 return (1);
792 }
793
794 int
795 spif_stcintr_tx(struct spif_softc *sc, int *needsoftp)
796 {
797 struct stty_port *sp;
798 uint8_t channel, ch;
799 int cnt = 0;
800
801 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
802 sp = &sc->sc_ttys->sc_port[channel];
803 if (!ISSET(sp->sp_flags, STTYF_STOP)) {
804 if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) {
805 STC_WRITE(sc, STC_TDR, 0);
806 STC_WRITE(sc, STC_TDR, 0x81);
807 CLR(sp->sp_flags, STTYF_SET_BREAK);
808 cnt += 2;
809 }
810 if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) {
811 STC_WRITE(sc, STC_TDR, 0);
812 STC_WRITE(sc, STC_TDR, 0x83);
813 CLR(sp->sp_flags, STTYF_CLR_BREAK);
814 cnt += 2;
815 }
816
817 while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) {
818 ch = *sp->sp_txp;
819 sp->sp_txc--;
820 sp->sp_txp++;
821
822 if (ch == 0) {
823 STC_WRITE(sc, STC_TDR, ch);
824 cnt++;
825 }
826 STC_WRITE(sc, STC_TDR, ch);
827 cnt++;
828 }
829 }
830
831 if (sp->sp_txc == 0 ||
832 ISSET(sp->sp_flags, STTYF_STOP)) {
833 STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) &
834 (~CD180_SRER_TXD));
835 CLR(sp->sp_flags, STTYF_STOP);
836 SET(sp->sp_flags, STTYF_DONE);
837 *needsoftp = 1;
838 }
839
840 STC_WRITE(sc, STC_EOSRR, 0);
841
842 return (1);
843 }
844
845 int
846 spif_stcintr_mx(struct spif_softc *sc, int *needsoftp)
847 {
848 struct stty_port *sp;
849 uint8_t channel, mcr;
850
851 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
852 sp = &sc->sc_ttys->sc_port[channel];
853 mcr = STC_READ(sc, STC_MCR);
854 if (mcr & CD180_MCR_CD) {
855 SET(sp->sp_flags, STTYF_CDCHG);
856 *needsoftp = 1;
857 }
858 STC_WRITE(sc, STC_MCR, 0);
859 STC_WRITE(sc, STC_EOSRR, 0);
860 return (1);
861 }
862
863 int
864 spif_stcintr(void *vsc)
865 {
866 struct spif_softc *sc = (struct spif_softc *)vsc;
867 int needsoft = 0, r = 0, i;
868 uint8_t ar;
869
870 for (i = 0; i < 8; i++) {
871 ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK;
872 if (ar == CD180_GSVR_RXGOOD)
873 r |= spif_stcintr_rx(sc, &needsoft);
874 else if (ar == CD180_GSVR_RXEXCEPTION)
875 r |= spif_stcintr_rxexception(sc, &needsoft);
876 }
877
878 for (i = 0; i < 8; i++) {
879 ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK;
880 if (ar == CD180_GSVR_TXDATA)
881 r |= spif_stcintr_tx(sc, &needsoft);
882 }
883
884 for (i = 0; i < 8; i++) {
885 ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK;
886 if (ar == CD180_GSVR_STATCHG)
887 r |= spif_stcintr_mx(sc, &needsoft);
888 }
889
890 if (needsoft)
891 softint_schedule(sc->sc_softih);
892 return (r);
893 }
894
895 void
896 spif_softintr(void *vsc)
897 {
898 struct spif_softc *sc = (struct spif_softc *)vsc;
899 struct stty_softc *stc = sc->sc_ttys;
900 int i, data, s, flags;
901 uint8_t stat, msvr;
902 struct stty_port *sp;
903 struct tty *tp;
904
905 if (stc != NULL) {
906 for (i = 0; i < stc->sc_nports; i++) {
907 sp = &stc->sc_port[i];
908 tp = sp->sp_tty;
909
910 if (!ISSET(tp->t_state, TS_ISOPEN))
911 continue;
912
913 while (sp->sp_rget != sp->sp_rput) {
914 stat = sp->sp_rget[0];
915 data = sp->sp_rget[1];
916 sp->sp_rget += 2;
917 if (sp->sp_rget == sp->sp_rend)
918 sp->sp_rget = sp->sp_rbuf;
919
920 if (stat & (CD180_RCSR_BE | CD180_RCSR_FE))
921 data |= TTY_FE;
922
923 if (stat & CD180_RCSR_PE)
924 data |= TTY_PE;
925
926 (*tp->t_linesw->l_rint)(data, tp);
927 }
928
929 s = splhigh();
930 flags = sp->sp_flags;
931 CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG |
932 STTYF_RING_OVERFLOW);
933 splx(s);
934
935 if (ISSET(flags, STTYF_CDCHG)) {
936 s = spltty();
937 STC_WRITE(sc, STC_CAR, i);
938 msvr = STC_READ(sc, STC_MSVR);
939 splx(s);
940
941 sp->sp_carrier = msvr & CD180_MSVR_CD;
942 (*tp->t_linesw->l_modem)(tp,
943 sp->sp_carrier);
944 }
945
946 if (ISSET(flags, STTYF_RING_OVERFLOW)) {
947 log(LOG_WARNING, "%s-%x: ring overflow\n",
948 device_xname(stc->sc_dev), i);
949 }
950
951 if (ISSET(flags, STTYF_DONE)) {
952 ndflush(&tp->t_outq,
953 sp->sp_txp - tp->t_outq.c_cf);
954 CLR(tp->t_state, TS_BUSY);
955 (*tp->t_linesw->l_start)(tp);
956 }
957 }
958 }
959 }
960
961 void
962 stty_write_ccr(struct spif_softc *sc, uint8_t val)
963 {
964 int tries = 100000;
965
966 while (STC_READ(sc, STC_CCR) && tries--)
967 /*EMPTY*/;
968 if (tries == 0)
969 aprint_error_dev(sc->sc_dev, "ccr timeout\n");
970 STC_WRITE(sc, STC_CCR, val);
971 }
972
973 int
974 stty_compute_baud(speed_t speed, int clock, uint8_t *bprlp, uint8_t *bprhp)
975 {
976 uint32_t rate;
977
978 rate = (2 * clock) / (16 * speed);
979 if (rate & 1)
980 rate = (rate >> 1) + 1;
981 else
982 rate = rate >> 1;
983
984 if (rate > 0xffff || rate == 0)
985 return (1);
986
987 *bprlp = rate & 0xff;
988 *bprhp = (rate >> 8) & 0xff;
989 return (0);
990 }
991
992 int
993 sbpp_match(device_t parent, cfdata_t vcf, void *aux)
994 {
995 struct spif_softc *sc = device_private(parent);
996
997 return (aux == sbpp_match && sc->sc_bpps == NULL);
998 }
999
1000 void
1001 sbpp_attach(device_t parent, device_t dev, void *aux)
1002 {
1003 struct spif_softc *sc = device_private(parent);
1004 struct sbpp_softc *psc = device_private(dev);
1005 int port;
1006
1007 sc->sc_bpps = psc;
1008
1009 for (port = 0; port < sc->sc_npar; port++) {
1010 }
1011
1012 psc->sc_nports = port;
1013 printf(": %d port%s\n", port, port == 1 ? "" : "s");
1014 }
1015
1016 int
1017 sbpp_open(dev_t dev, int flags, int mode, struct lwp *l)
1018 {
1019 return (ENXIO);
1020 }
1021
1022 int
1023 sbpp_close(dev_t dev, int flags, int mode, struct lwp *l)
1024 {
1025 return (ENXIO);
1026 }
1027
1028 int
1029 spif_ppcintr(void *v)
1030 {
1031 return (0);
1032 }
1033
1034 int
1035 sbpp_read(dev_t dev, struct uio *uio, int flags)
1036 {
1037 return (sbpp_rw(dev, uio));
1038 }
1039
1040 int
1041 sbpp_write(dev_t dev, struct uio *uio, int flags)
1042 {
1043 return (sbpp_rw(dev, uio));
1044 }
1045
1046 int
1047 sbpp_rw(dev_t dev, struct uio *uio)
1048 {
1049 return (ENXIO);
1050 }
1051
1052 int
1053 sbpp_poll(dev_t dev, int events, struct lwp *l)
1054 {
1055 return (seltrue(dev, events, l));
1056 }
1057
1058 int
1059 sbpp_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
1060 {
1061 int error;
1062
1063 error = ENOTTY;
1064
1065 return (error);
1066 }
1067
1068 #endif /* NSPIF */
1069