kernel: Remove the COMPAT_43 kernel option along with all related code.
[dragonfly.git] / sys / dev / serial / si / si_drv.c
blob0129a23218b5d8b785b0f3ca02cec1f2a4a089d0
1 /*
2 * (MPSAFE)
4 * Device driver for Specialix range (SI/XIO) of serial line multiplexors.
6 * Copyright (C) 1990, 1992, 1998 Specialix International,
7 * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk>
8 * Copyright (C) 2000, Peter Wemm <peter@netplex.com.au>
10 * Originally derived from: SunOS 4.x version
11 * Ported from BSDI version to FreeBSD by Peter Wemm.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notices, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notices, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by Andy Rutter of
24 * Advanced Methods and Tools Ltd. based on original information
25 * from Specialix International.
26 * 4. Neither the name of Advanced Methods and Tools, nor Specialix
27 * International may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
31 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
33 * NO EVENT SHALL THE AUTHORS BE LIABLE.
35 * $FreeBSD: src/sys/dev/si/si.c,v 1.101.2.1 2001/02/26 04:23:06 jlemon Exp $
38 #ifndef lint
39 static const char si_copyright1[] = "@(#) Copyright (C) Specialix International, 1990,1992,1998",
40 si_copyright2[] = "@(#) Copyright (C) Andy Rutter 1993",
41 si_copyright3[] = "@(#) Copyright (C) Peter Wemm 2000";
42 #endif /* not lint */
44 #include "opt_debug_si.h"
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/tty.h>
49 #include <sys/proc.h>
50 #include <sys/priv.h>
51 #include <sys/conf.h>
52 #include <sys/fcntl.h>
53 #include <sys/dkstat.h>
54 #include <sys/kernel.h>
55 #include <sys/malloc.h>
56 #include <sys/sysctl.h>
57 #include <sys/bus.h>
58 #include <sys/rman.h>
59 #include <sys/thread2.h>
61 #include <machine/clock.h>
63 #include <vm/vm.h>
64 #include <vm/pmap.h>
66 #include <machine/stdarg.h>
68 #include "sireg.h"
69 #include "sivar.h"
70 #include "si.h"
73 * This device driver is designed to interface the Specialix International
74 * SI, XIO and SX range of serial multiplexor cards to FreeBSD on an ISA,
75 * EISA or PCI bus machine.
77 * The controller is interfaced to the host via dual port RAM
78 * and an interrupt.
80 * The code for the Host 1 (very old ISA cards) has not been tested.
83 #define POLL /* turn on poller to scan for lost interrupts */
84 #define REALPOLL /* on each poll, scan for work regardless */
85 #define POLLHZ (hz/10) /* 10 times per second */
86 #define SI_I_HIGH_WATER (TTYHOG - 2 * SI_BUFFERSIZE)
87 #define INT_COUNT 25000 /* max of 125 ints per second */
88 #define JET_INT_COUNT 100 /* max of 100 ints per second */
89 #define RXINT_COUNT 1 /* one rxint per 10 milliseconds */
91 enum si_mctl { GET, SET, BIS, BIC };
93 static void si_command(struct si_port *, int, int);
94 static int si_modem(struct si_port *, enum si_mctl, int);
95 static void si_write_enable(struct si_port *, int);
96 static int si_Sioctl(cdev_t, u_long, caddr_t, int, struct ucred *);
97 static void si_start(struct tty *);
98 static void si_stop(struct tty *, int);
99 static timeout_t si_lstart;
100 static void si_disc_optim(struct tty *tp, struct termios *t,struct si_port *pp);
101 static void sihardclose(struct si_port *pp);
102 static void sidtrwakeup(void *chan);
104 #ifdef SI_DEBUG
105 static char *si_mctl2str(enum si_mctl cmd);
106 #endif
108 static int siparam(struct tty *, struct termios *);
110 static void si_modem_state(struct si_port *pp, struct tty *tp, int hi_ip);
111 static char * si_modulename(int host_type, int uart_type);
113 static d_open_t siopen;
114 static d_close_t siclose;
115 static d_write_t siwrite;
116 static d_ioctl_t siioctl;
118 static struct dev_ops si_ops = {
119 { "si", 0, D_TTY },
120 .d_open = siopen,
121 .d_close = siclose,
122 .d_read = ttyread,
123 .d_write = siwrite,
124 .d_ioctl = siioctl,
125 .d_kqfilter = ttykqfilter,
126 .d_revoke = ttyrevoke
129 static int si_Nports;
130 static int si_Nmodules;
131 static int si_debug = 0; /* data, not bss, so it's patchable */
133 SYSCTL_INT(_machdep, OID_AUTO, si_debug, CTLFLAG_RW, &si_debug, 0, "");
135 static struct tty *si__tty;
137 static int si_numunits;
138 static struct callout poll_ch;
140 devclass_t si_devclass;
142 #ifndef B2000 /* not standard, but the hardware knows it. */
143 # define B2000 2000
144 #endif
145 static struct speedtab bdrates[] = {
146 { B75, CLK75, }, /* 0x0 */
147 { B110, CLK110, }, /* 0x1 */
148 { B150, CLK150, }, /* 0x3 */
149 { B300, CLK300, }, /* 0x4 */
150 { B600, CLK600, }, /* 0x5 */
151 { B1200, CLK1200, }, /* 0x6 */
152 { B2000, CLK2000, }, /* 0x7 */
153 { B2400, CLK2400, }, /* 0x8 */
154 { B4800, CLK4800, }, /* 0x9 */
155 { B9600, CLK9600, }, /* 0xb */
156 { B19200, CLK19200, }, /* 0xc */
157 { B38400, CLK38400, }, /* 0x2 (out of order!) */
158 { B57600, CLK57600, }, /* 0xd */
159 { B115200, CLK110, }, /* 0x1 (dupe!, 110 baud on "si") */
160 { -1, -1 },
164 /* populated with approx character/sec rates - translated at card
165 * initialisation time to chars per tick of the clock */
166 static int done_chartimes = 0;
167 static struct speedtab chartimes[] = {
168 { B75, 8, },
169 { B110, 11, },
170 { B150, 15, },
171 { B300, 30, },
172 { B600, 60, },
173 { B1200, 120, },
174 { B2000, 200, },
175 { B2400, 240, },
176 { B4800, 480, },
177 { B9600, 960, },
178 { B19200, 1920, },
179 { B38400, 3840, },
180 { B57600, 5760, },
181 { B115200, 11520, },
182 { -1, -1 },
184 static volatile int in_intr = 0; /* Inside interrupt handler? */
186 #ifdef POLL
187 static int si_pollrate; /* in addition to irq */
188 static int si_realpoll = 0; /* poll HW on timer */
190 SYSCTL_INT(_machdep, OID_AUTO, si_pollrate, CTLFLAG_RW, &si_pollrate, 0, "");
191 SYSCTL_INT(_machdep, OID_AUTO, si_realpoll, CTLFLAG_RW, &si_realpoll, 0, "");
193 static int init_finished = 0;
194 static void si_poll(void *);
195 #endif
198 * Array of adapter types and the corresponding RAM size. The order of
199 * entries here MUST match the ordinal of the adapter type.
201 static char *si_type[] = {
202 "EMPTY",
203 "SIHOST",
204 "SIMCA", /* FreeBSD does not support Microchannel */
205 "SIHOST2",
206 "SIEISA",
207 "SIPCI",
208 "SXPCI",
209 "SXISA",
213 * We have to make an 8 bit version of bcopy, since some cards can't
214 * deal with 32 bit I/O
216 static __inline void
217 si_bcopy(const void *src, void *dst, size_t len)
219 const uint8_t *src_byte = (const uint8_t *)src;
220 uint8_t *dst_byte = (uint8_t *)dst;
222 while (len--)
223 *dst_byte++ = *src_byte++;
226 static __inline void
227 si_vbcopy(const volatile void *src, void *dst, size_t len)
229 volatile const uint8_t *src_byte = (volatile const uint8_t *)src;
230 uint8_t *dst_byte = (uint8_t *)dst;
232 while (len--)
233 *dst_byte++ = *src_byte++;
236 static __inline void
237 si_bcopyv(const void *src, volatile void *dst, size_t len)
239 const uint8_t *src_byte = (const uint8_t *)src;
240 volatile uint8_t *dst_byte = (volatile uint8_t *)dst;
242 while (len--)
243 *dst_byte++ = *src_byte++;
247 * Attach the device. Initialize the card.
250 siattach(device_t dev)
252 int unit;
253 struct si_softc *sc;
254 struct si_port *pp;
255 volatile struct si_channel *ccbp;
256 volatile struct si_reg *regp;
257 volatile caddr_t maddr;
258 struct si_module *modp;
259 struct tty *tp;
260 struct speedtab *spt;
261 int nmodule, nport, x, y;
262 int uart_type;
263 int n;
265 if ((poll_ch.c_flags & CALLOUT_DID_INIT) == 0)
266 callout_init_mp(&poll_ch);
268 lwkt_gettoken(&tty_token);
269 sc = device_get_softc(dev);
270 unit = device_get_unit(dev);
272 sc->sc_typename = si_type[sc->sc_type];
273 if (si_numunits < unit + 1)
274 si_numunits = unit + 1;
276 DPRINT((0, DBG_AUTOBOOT, "si%d: siattach\n", unit));
278 #ifdef POLL
279 if (si_pollrate == 0) {
280 si_pollrate = POLLHZ; /* in addition to irq */
281 #ifdef REALPOLL
282 si_realpoll = 1; /* scan always */
283 #endif
285 #endif
287 DPRINT((0, DBG_AUTOBOOT, "si%d: type: %s paddr: %p maddr: %p\n", unit,
288 sc->sc_typename, sc->sc_paddr, sc->sc_maddr));
290 sc->sc_ports = NULL; /* mark as uninitialised */
292 maddr = sc->sc_maddr;
294 /* Stop the CPU first so it won't stomp around while we load */
296 switch (sc->sc_type) {
297 case SIEISA:
298 outb(sc->sc_iobase + 2, sc->sc_irq << 4);
299 break;
300 case SIPCI:
301 *(maddr+SIPCIRESET) = 0;
302 break;
303 case SIJETPCI: /* fall through to JET ISA */
304 case SIJETISA:
305 *(maddr+SIJETCONFIG) = 0;
306 break;
307 case SIHOST2:
308 *(maddr+SIPLRESET) = 0;
309 break;
310 case SIHOST:
311 *(maddr+SIRESET) = 0;
312 break;
313 default: /* this should never happen */
314 kprintf("si%d: unsupported configuration\n", unit);
315 lwkt_reltoken(&tty_token);
316 return EINVAL;
317 break;
320 /* OK, now lets download the download code */
322 if (SI_ISJET(sc->sc_type)) {
323 DPRINT((0, DBG_DOWNLOAD, "si%d: jet_download: nbytes %d\n",
324 unit, si3_t225_dsize));
325 si_bcopy(si3_t225_download, maddr + si3_t225_downloadaddr,
326 si3_t225_dsize);
327 DPRINT((0, DBG_DOWNLOAD,
328 "si%d: jet_bootstrap: nbytes %d -> %x\n",
329 unit, si3_t225_bsize, si3_t225_bootloadaddr));
330 si_bcopy(si3_t225_bootstrap, maddr + si3_t225_bootloadaddr,
331 si3_t225_bsize);
332 } else {
333 DPRINT((0, DBG_DOWNLOAD, "si%d: si_download: nbytes %d\n",
334 unit, si2_z280_dsize));
335 si_bcopy(si2_z280_download, maddr + si2_z280_downloadaddr,
336 si2_z280_dsize);
339 /* Now start the CPU */
341 switch (sc->sc_type) {
342 case SIEISA:
343 /* modify the download code to tell it that it's on an EISA */
344 *(maddr + 0x42) = 1;
345 outb(sc->sc_iobase + 2, (sc->sc_irq << 4) | 4);
346 (void)inb(sc->sc_iobase + 3); /* reset interrupt */
347 break;
348 case SIPCI:
349 /* modify the download code to tell it that it's on a PCI */
350 *(maddr+0x42) = 1;
351 *(maddr+SIPCIRESET) = 1;
352 *(maddr+SIPCIINTCL) = 0;
353 break;
354 case SIJETPCI:
355 *(maddr+SIJETRESET) = 0;
356 *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN;
357 break;
358 case SIJETISA:
359 *(maddr+SIJETRESET) = 0;
360 switch (sc->sc_irq) {
361 case 9:
362 *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0x90;
363 break;
364 case 10:
365 *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xa0;
366 break;
367 case 11:
368 *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xb0;
369 break;
370 case 12:
371 *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xc0;
372 break;
373 case 15:
374 *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xf0;
375 break;
377 break;
378 case SIHOST:
379 *(maddr+SIRESET_CL) = 0;
380 *(maddr+SIINTCL_CL) = 0;
381 break;
382 case SIHOST2:
383 *(maddr+SIPLRESET) = 0x10;
384 switch (sc->sc_irq) {
385 case 11:
386 *(maddr+SIPLIRQ11) = 0x10;
387 break;
388 case 12:
389 *(maddr+SIPLIRQ12) = 0x10;
390 break;
391 case 15:
392 *(maddr+SIPLIRQ15) = 0x10;
393 break;
395 *(maddr+SIPLIRQCLR) = 0x10;
396 break;
397 default: /* this should _REALLY_ never happen */
398 kprintf("si%d: Uh, it was supported a second ago...\n", unit);
399 lwkt_reltoken(&tty_token);
400 return EINVAL;
403 DELAY(1000000); /* wait around for a second */
405 regp = (struct si_reg *)maddr;
406 y = 0;
407 /* wait max of 5 sec for init OK */
408 while (regp->initstat == 0 && y++ < 10) {
409 DELAY(500000);
411 switch (regp->initstat) {
412 case 0:
413 kprintf("si%d: startup timeout - aborting\n", unit);
414 sc->sc_type = SIEMPTY;
415 lwkt_reltoken(&tty_token);
416 return EINVAL;
417 case 1:
418 if (SI_ISJET(sc->sc_type)) {
419 /* set throttle to 100 times per second */
420 regp->int_count = JET_INT_COUNT;
421 /* rx_intr_count is a NOP in Jet */
422 } else {
423 /* set throttle to 125 times per second */
424 regp->int_count = INT_COUNT;
425 /* rx intr max of 25 times per second */
426 regp->rx_int_count = RXINT_COUNT;
428 regp->int_pending = 0; /* no intr pending */
429 regp->int_scounter = 0; /* reset counter */
430 break;
431 case 0xff:
433 * No modules found, so give up on this one.
435 kprintf("si%d: %s - no ports found\n", unit,
436 si_type[sc->sc_type]);
437 lwkt_reltoken(&tty_token);
438 return 0;
439 default:
440 kprintf("si%d: download code version error - initstat %x\n",
441 unit, regp->initstat);
442 lwkt_reltoken(&tty_token);
443 return EINVAL;
447 * First time around the ports just count them in order
448 * to allocate some memory.
450 nport = 0;
451 modp = (struct si_module *)(maddr + 0x80);
452 for (;;) {
453 DPRINT((0, DBG_DOWNLOAD, "si%d: ccb addr %p\n", unit, modp));
454 switch (modp->sm_type) {
455 case TA4:
456 DPRINT((0, DBG_DOWNLOAD,
457 "si%d: Found old TA4 module, 4 ports\n",
458 unit));
459 x = 4;
460 break;
461 case TA8:
462 DPRINT((0, DBG_DOWNLOAD,
463 "si%d: Found old TA8 module, 8 ports\n",
464 unit));
465 x = 8;
466 break;
467 case TA4_ASIC:
468 DPRINT((0, DBG_DOWNLOAD,
469 "si%d: Found ASIC TA4 module, 4 ports\n",
470 unit));
471 x = 4;
472 break;
473 case TA8_ASIC:
474 DPRINT((0, DBG_DOWNLOAD,
475 "si%d: Found ASIC TA8 module, 8 ports\n",
476 unit));
477 x = 8;
478 break;
479 case MTA:
480 DPRINT((0, DBG_DOWNLOAD,
481 "si%d: Found CD1400 module, 8 ports\n",
482 unit));
483 x = 8;
484 break;
485 case SXDC:
486 DPRINT((0, DBG_DOWNLOAD,
487 "si%d: Found SXDC module, 8 ports\n",
488 unit));
489 x = 8;
490 break;
491 default:
492 kprintf("si%d: unknown module type %d\n",
493 unit, modp->sm_type);
494 goto try_next;
497 /* this was limited in firmware and is also a driver issue */
498 if ((nport + x) > SI_MAXPORTPERCARD) {
499 kprintf("si%d: extra ports ignored\n", unit);
500 goto try_next;
503 nport += x;
504 si_Nports += x;
505 si_Nmodules++;
507 try_next:
508 if (modp->sm_next == 0)
509 break;
510 modp = (struct si_module *)
511 (maddr + (unsigned)(modp->sm_next & 0x7fff));
513 sc->sc_ports = kmalloc(sizeof(struct si_port) * nport,
514 M_DEVBUF, M_WAITOK | M_ZERO);
515 sc->sc_nport = nport;
516 for (n = 0; n < nport; ++n) {
517 callout_init_mp(&sc->sc_ports[n].lstart_ch);
518 callout_init_mp(&sc->sc_ports[n].dtr_ch);
522 * allocate tty structures for ports
524 tp = kmalloc(sizeof(*tp) * nport, M_DEVBUF, M_WAITOK | M_ZERO);
525 si__tty = tp;
528 * Scan round the ports again, this time initialising.
530 pp = sc->sc_ports;
531 nmodule = 0;
532 modp = (struct si_module *)(maddr + 0x80);
533 uart_type = 1000; /* arbitary, > uchar_max */
534 for (;;) {
535 switch (modp->sm_type) {
536 case TA4:
537 nport = 4;
538 break;
539 case TA8:
540 nport = 8;
541 break;
542 case TA4_ASIC:
543 nport = 4;
544 break;
545 case TA8_ASIC:
546 nport = 8;
547 break;
548 case MTA:
549 nport = 8;
550 break;
551 case SXDC:
552 nport = 8;
553 break;
554 default:
555 goto try_next2;
557 nmodule++;
558 ccbp = (struct si_channel *)((char *)modp + 0x100);
559 if (uart_type == 1000)
560 uart_type = ccbp->type;
561 else if (uart_type != ccbp->type)
562 kprintf("si%d: Warning: module %d mismatch! (%d%s != %d%s)\n",
563 unit, nmodule,
564 ccbp->type, si_modulename(sc->sc_type, ccbp->type),
565 uart_type, si_modulename(sc->sc_type, uart_type));
567 for (x = 0; x < nport; x++, pp++, ccbp++) {
568 pp->sp_ccb = ccbp; /* save the address */
569 pp->sp_tty = tp++;
570 pp->sp_pend = IDLE_CLOSE;
571 pp->sp_state = 0; /* internal flag */
572 pp->sp_dtr_wait = 3 * hz;
573 pp->sp_iin.c_iflag = TTYDEF_IFLAG;
574 pp->sp_iin.c_oflag = TTYDEF_OFLAG;
575 pp->sp_iin.c_cflag = TTYDEF_CFLAG;
576 pp->sp_iin.c_lflag = TTYDEF_LFLAG;
577 termioschars(&pp->sp_iin);
578 pp->sp_iin.c_ispeed = pp->sp_iin.c_ospeed =
579 TTYDEF_SPEED;
580 pp->sp_iout = pp->sp_iin;
582 try_next2:
583 if (modp->sm_next == 0) {
584 kprintf("si%d: card: %s, ports: %d, modules: %d, type: %d%s\n",
585 unit,
586 sc->sc_typename,
587 sc->sc_nport,
588 nmodule,
589 uart_type,
590 si_modulename(sc->sc_type, uart_type));
591 break;
593 modp = (struct si_module *)
594 (maddr + (unsigned)(modp->sm_next & 0x7fff));
596 if (done_chartimes == 0) {
597 for (spt = chartimes ; spt->sp_speed != -1; spt++) {
598 if ((spt->sp_code /= hz) == 0)
599 spt->sp_code = 1;
601 done_chartimes = 1;
604 for (x = 0; x < sc->sc_nport; x++) {
605 /* sync with the manuals that start at 1 */
606 y = x + 1 + unit * (1 << SI_CARDSHIFT);
607 make_dev(&si_ops, x, 0, 0, 0600, "ttyA%02d", y);
608 make_dev(&si_ops, x + 0x00080, 0, 0, 0600, "cuaA%02d", y);
609 make_dev(&si_ops, x + 0x10000, 0, 0, 0600, "ttyiA%02d", y);
610 make_dev(&si_ops, x + 0x10080, 0, 0, 0600, "cuaiA%02d", y);
611 make_dev(&si_ops, x + 0x20000, 0, 0, 0600, "ttylA%02d", y);
612 make_dev(&si_ops, x + 0x20080, 0, 0, 0600, "cualA%02d", y);
614 make_dev(&si_ops, 0x40000, 0, 0, 0600, "si_control");
615 lwkt_reltoken(&tty_token);
616 return (0);
619 static int
620 siopen(struct dev_open_args *ap)
622 cdev_t dev = ap->a_head.a_dev;
623 int error;
624 int card, port;
625 struct si_softc *sc;
626 struct tty *tp;
627 volatile struct si_channel *ccbp;
628 struct si_port *pp;
629 int mynor = minor(dev);
631 lwkt_gettoken(&tty_token);
632 /* quickly let in /dev/si_control */
633 if (IS_CONTROLDEV(mynor)) {
634 if ((error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0))) {
635 lwkt_reltoken(&tty_token);
636 return(error);
638 lwkt_reltoken(&tty_token);
639 return(0);
642 card = SI_CARD(mynor);
643 sc = devclass_get_softc(si_devclass, card);
644 if (sc == NULL) {
645 lwkt_reltoken(&tty_token);
646 return (ENXIO);
649 if (sc->sc_type == SIEMPTY) {
650 DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: type %s??\n",
651 card, sc->sc_typename));
652 lwkt_reltoken(&tty_token);
653 return(ENXIO);
656 port = SI_PORT(mynor);
657 if (port >= sc->sc_nport) {
658 DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: nports %d\n",
659 card, sc->sc_nport));
660 lwkt_reltoken(&tty_token);
661 return(ENXIO);
664 #ifdef POLL
666 * We've now got a device, so start the poller.
668 if (init_finished == 0) {
669 callout_reset(&poll_ch, si_pollrate, si_poll, NULL);
670 init_finished = 1;
672 #endif
674 /* initial/lock device */
675 if (IS_STATE(mynor)) {
676 lwkt_reltoken(&tty_token);
677 return(0);
680 pp = sc->sc_ports + port;
681 tp = pp->sp_tty; /* the "real" tty */
682 dev->si_tty = tp;
683 ccbp = pp->sp_ccb; /* Find control block */
684 DPRINT((pp, DBG_ENTRY|DBG_OPEN, "siopen(%s,%x,%x)\n",
685 devtoname(dev), ap->a_oflags, ap->a_devtype));
687 crit_enter(); /* Keep others out */
688 error = 0;
690 open_top:
691 while (pp->sp_state & SS_DTR_OFF) {
692 error = tsleep(&pp->sp_dtr_wait, PCATCH, "sidtr", 0);
693 if (error != 0)
694 goto out;
697 if (tp->t_state & TS_ISOPEN) {
699 * The device is open, so everything has been initialised.
700 * handle conflicts.
702 if (IS_CALLOUT(mynor)) {
703 if (!pp->sp_active_out) {
704 error = EBUSY;
705 goto out;
707 } else {
708 if (pp->sp_active_out) {
709 if (ap->a_oflags & O_NONBLOCK) {
710 error = EBUSY;
711 goto out;
713 error = tsleep(&pp->sp_active_out,
714 PCATCH, "sibi", 0);
715 if (error != 0)
716 goto out;
717 goto open_top;
720 if (tp->t_state & TS_XCLUDE &&
721 priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
722 DPRINT((pp, DBG_OPEN|DBG_FAIL,
723 "already open and EXCLUSIVE set\n"));
724 error = EBUSY;
725 goto out;
727 } else {
729 * The device isn't open, so there are no conflicts.
730 * Initialize it. Avoid sleep... :-)
732 DPRINT((pp, DBG_OPEN, "first open\n"));
733 tp->t_oproc = si_start;
734 tp->t_stop = si_stop;
735 tp->t_param = siparam;
736 tp->t_dev = dev;
737 tp->t_termios = mynor & SI_CALLOUT_MASK
738 ? pp->sp_iout : pp->sp_iin;
740 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);
742 ++pp->sp_wopeners; /* in case of sleep in siparam */
744 error = siparam(tp, &tp->t_termios);
746 --pp->sp_wopeners;
747 if (error != 0)
748 goto out;
749 /* XXX: we should goto_top if siparam slept */
751 /* set initial DCD state */
752 pp->sp_last_hi_ip = ccbp->hi_ip;
753 if ((pp->sp_last_hi_ip & IP_DCD) || IS_CALLOUT(mynor)) {
754 (*linesw[tp->t_line].l_modem)(tp, 1);
758 /* whoops! we beat the close! */
759 if (pp->sp_state & SS_CLOSING) {
760 /* try and stop it from proceeding to bash the hardware */
761 pp->sp_state &= ~SS_CLOSING;
765 * Wait for DCD if necessary
767 if (!(tp->t_state & TS_CARR_ON) &&
768 !IS_CALLOUT(mynor) &&
769 !(tp->t_cflag & CLOCAL) &&
770 !(ap->a_oflags & O_NONBLOCK)) {
771 ++pp->sp_wopeners;
772 DPRINT((pp, DBG_OPEN, "sleeping for carrier\n"));
773 error = tsleep(TSA_CARR_ON(tp), PCATCH, "sidcd", 0);
774 --pp->sp_wopeners;
775 if (error != 0)
776 goto out;
777 goto open_top;
780 error = (*linesw[tp->t_line].l_open)(dev, tp);
781 si_disc_optim(tp, &tp->t_termios, pp);
782 if (tp->t_state & TS_ISOPEN && IS_CALLOUT(mynor))
783 pp->sp_active_out = TRUE;
785 pp->sp_state |= SS_OPEN; /* made it! */
787 out:
788 crit_exit();
790 DPRINT((pp, DBG_OPEN, "leaving siopen\n"));
792 if (!(tp->t_state & TS_ISOPEN) && pp->sp_wopeners == 0)
793 sihardclose(pp);
795 lwkt_reltoken(&tty_token);
796 return(error);
799 static int
800 siclose(struct dev_close_args *ap)
802 cdev_t dev = ap->a_head.a_dev;
803 struct si_port *pp;
804 struct tty *tp;
805 int error = 0;
806 int mynor = minor(dev);
808 if (IS_SPECIAL(mynor))
809 return(0);
811 lwkt_gettoken(&tty_token);
812 crit_enter();
814 pp = MINOR2PP(mynor);
815 tp = pp->sp_tty;
817 DPRINT((pp, DBG_ENTRY|DBG_CLOSE, "siclose(%s,%x,%x) sp_state:%x\n",
818 devtoname(dev), ap->a_fflag, ap->a_devtype, pp->sp_state));
820 /* did we sleep and loose a race? */
821 if (pp->sp_state & SS_CLOSING) {
822 /* error = ESOMETING? */
823 goto out;
826 /* begin race detection.. */
827 pp->sp_state |= SS_CLOSING;
829 si_write_enable(pp, 0); /* block writes for ttywait() */
831 /* THIS MAY SLEEP IN TTYWAIT!!! */
832 (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
834 si_write_enable(pp, 1);
836 /* did we sleep and somebody started another open? */
837 if (!(pp->sp_state & SS_CLOSING)) {
838 /* error = ESOMETING? */
839 goto out;
841 /* ok. we are now still on the right track.. nuke the hardware */
843 if (pp->sp_state & SS_LSTART) {
844 callout_stop(&pp->lstart_ch);
845 pp->sp_state &= ~SS_LSTART;
848 si_stop(tp, FREAD | FWRITE);
850 sihardclose(pp);
851 ttyclose(tp);
852 pp->sp_state &= ~SS_OPEN;
854 out:
855 DPRINT((pp, DBG_CLOSE|DBG_EXIT, "close done, returning\n"));
856 crit_exit();
857 lwkt_reltoken(&tty_token);
858 return(error);
861 static void
862 sihardclose(struct si_port *pp)
864 struct tty *tp;
865 volatile struct si_channel *ccbp;
867 crit_enter();
868 lwkt_gettoken(&tty_token);
870 tp = pp->sp_tty;
871 ccbp = pp->sp_ccb; /* Find control block */
872 if (tp->t_cflag & HUPCL ||
873 (!pp->sp_active_out &&
874 !(ccbp->hi_ip & IP_DCD) &&
875 !(pp->sp_iin.c_cflag & CLOCAL)) ||
876 !(tp->t_state & TS_ISOPEN)) {
878 (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);
879 (void) si_command(pp, FCLOSE, SI_NOWAIT);
881 if (pp->sp_dtr_wait != 0) {
882 callout_reset(&pp->dtr_ch, pp->sp_dtr_wait,
883 sidtrwakeup, pp);
884 pp->sp_state |= SS_DTR_OFF;
888 pp->sp_active_out = FALSE;
889 wakeup((caddr_t)&pp->sp_active_out);
890 wakeup(TSA_CARR_ON(tp));
892 lwkt_reltoken(&tty_token);
893 crit_exit();
898 * called at splsoftclock()...
900 static void
901 sidtrwakeup(void *chan)
903 struct si_port *pp;
905 crit_enter();
906 lwkt_gettoken(&tty_token);
908 pp = (struct si_port *)chan;
909 pp->sp_state &= ~SS_DTR_OFF;
910 wakeup(&pp->sp_dtr_wait);
912 lwkt_reltoken(&tty_token);
913 crit_exit();
916 static int
917 siwrite(struct dev_write_args *ap)
919 cdev_t dev = ap->a_head.a_dev;
920 struct si_port *pp;
921 struct tty *tp;
922 int error = 0;
923 int mynor = minor(dev);
925 lwkt_gettoken(&tty_token);
926 if (IS_SPECIAL(mynor)) {
927 DPRINT((0, DBG_ENTRY|DBG_FAIL|DBG_WRITE, "siwrite(CONTROLDEV!!)\n"));
928 lwkt_reltoken(&tty_token);
929 return(ENODEV);
931 pp = MINOR2PP(mynor);
932 tp = pp->sp_tty;
933 DPRINT((pp, DBG_WRITE, "siwrite(%s,%p,%x)\n", devtoname(dev), ap->a_uio, ap->a_ioflag));
935 crit_enter();
937 * If writes are currently blocked, wait on the "real" tty
939 while (pp->sp_state & SS_BLOCKWRITE) {
940 pp->sp_state |= SS_WAITWRITE;
941 DPRINT((pp, DBG_WRITE, "in siwrite, wait for SS_BLOCKWRITE to clear\n"));
942 if ((error = ttysleep(tp, (caddr_t)pp, PCATCH,
943 "siwrite", tp->t_timeout))) {
944 if (error == EWOULDBLOCK)
945 error = EIO;
946 goto out;
950 error = (*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag);
951 out:
952 crit_exit();
953 lwkt_reltoken(&tty_token);
954 return (error);
958 static int
959 siioctl(struct dev_ioctl_args *ap)
961 cdev_t dev = ap->a_head.a_dev;
962 caddr_t data = ap->a_data;
963 u_long cmd = ap->a_cmd;
964 struct si_port *pp;
965 struct tty *tp;
966 int error;
967 int mynor = minor(dev);
968 int blocked = 0;
970 if (IS_SI_IOCTL(cmd))
971 return(si_Sioctl(dev, cmd, data, ap->a_fflag, ap->a_cred));
973 lwkt_gettoken(&tty_token);
974 pp = MINOR2PP(mynor);
975 tp = pp->sp_tty;
977 DPRINT((pp, DBG_ENTRY|DBG_IOCTL, "siioctl(%s,%lx,%p,%x)\n",
978 devtoname(dev), cmd, data, ap->a_fflag));
979 if (IS_STATE(mynor)) {
980 struct termios *ct;
982 switch (mynor & SI_STATE_MASK) {
983 case SI_INIT_STATE_MASK:
984 ct = IS_CALLOUT(mynor) ? &pp->sp_iout : &pp->sp_iin;
985 break;
986 case SI_LOCK_STATE_MASK:
987 ct = IS_CALLOUT(mynor) ? &pp->sp_lout : &pp->sp_lin;
988 break;
989 default:
990 lwkt_reltoken(&tty_token);
991 return (ENODEV);
993 switch (cmd) {
994 case TIOCSETA:
995 error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
996 if (error != 0) {
997 lwkt_reltoken(&tty_token);
998 return (error);
1000 *ct = *(struct termios *)data;
1001 lwkt_reltoken(&tty_token);
1002 return (0);
1003 case TIOCGETA:
1004 *(struct termios *)data = *ct;
1005 lwkt_reltoken(&tty_token);
1006 return (0);
1007 case TIOCGETD:
1008 *(int *)data = TTYDISC;
1009 lwkt_reltoken(&tty_token);
1010 return (0);
1011 case TIOCGWINSZ:
1012 bzero(data, sizeof(struct winsize));
1013 lwkt_reltoken(&tty_token);
1014 return (0);
1015 default:
1016 lwkt_reltoken(&tty_token);
1017 return (ENOTTY);
1021 * Do the initial / lock state business
1023 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
1024 int cc;
1025 struct termios *dt = (struct termios *)data;
1026 struct termios *lt = mynor & SI_CALLOUT_MASK
1027 ? &pp->sp_lout : &pp->sp_lin;
1029 dt->c_iflag = (tp->t_iflag & lt->c_iflag) |
1030 (dt->c_iflag & ~lt->c_iflag);
1031 dt->c_oflag = (tp->t_oflag & lt->c_oflag) |
1032 (dt->c_oflag & ~lt->c_oflag);
1033 dt->c_cflag = (tp->t_cflag & lt->c_cflag) |
1034 (dt->c_cflag & ~lt->c_cflag);
1035 dt->c_lflag = (tp->t_lflag & lt->c_lflag) |
1036 (dt->c_lflag & ~lt->c_lflag);
1037 for (cc = 0; cc < NCCS; ++cc)
1038 if (lt->c_cc[cc] != 0)
1039 dt->c_cc[cc] = tp->t_cc[cc];
1040 if (lt->c_ispeed != 0)
1041 dt->c_ispeed = tp->t_ispeed;
1042 if (lt->c_ospeed != 0)
1043 dt->c_ospeed = tp->t_ospeed;
1047 * Block user-level writes to give the ttywait()
1048 * a chance to completely drain for commands
1049 * that require the port to be in a quiescent state.
1051 switch (cmd) {
1052 case TIOCSETAW:
1053 case TIOCSETAF:
1054 case TIOCDRAIN:
1055 blocked++; /* block writes for ttywait() and siparam() */
1056 si_write_enable(pp, 0);
1059 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data,
1060 ap->a_fflag, ap->a_cred);
1061 if (error != ENOIOCTL)
1062 goto out;
1064 crit_enter();
1066 error = ttioctl(tp, cmd, data, ap->a_fflag);
1067 si_disc_optim(tp, &tp->t_termios, pp);
1068 if (error != ENOIOCTL) {
1069 crit_exit();
1070 goto out;
1073 error = 0;
1074 switch (cmd) {
1075 case TIOCSBRK:
1076 si_command(pp, SBREAK, SI_WAIT);
1077 break;
1078 case TIOCCBRK:
1079 si_command(pp, EBREAK, SI_WAIT);
1080 break;
1081 case TIOCSDTR:
1082 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);
1083 break;
1084 case TIOCCDTR:
1085 (void) si_modem(pp, SET, 0);
1086 break;
1087 case TIOCMSET:
1088 (void) si_modem(pp, SET, *(int *)data);
1089 break;
1090 case TIOCMBIS:
1091 (void) si_modem(pp, BIS, *(int *)data);
1092 break;
1093 case TIOCMBIC:
1094 (void) si_modem(pp, BIC, *(int *)data);
1095 break;
1096 case TIOCMGET:
1097 *(int *)data = si_modem(pp, GET, 0);
1098 break;
1099 case TIOCMSDTRWAIT:
1100 /* must be root since the wait applies to following logins */
1101 error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
1102 if (error == 0)
1103 pp->sp_dtr_wait = *(int *)data * hz / 100;
1104 break;
1105 case TIOCMGDTRWAIT:
1106 *(int *)data = pp->sp_dtr_wait * 100 / hz;
1107 break;
1108 default:
1109 error = ENOTTY;
1111 crit_exit();
1113 out:
1114 DPRINT((pp, DBG_IOCTL|DBG_EXIT, "siioctl ret %d\n", error));
1115 if (blocked)
1116 si_write_enable(pp, 1);
1117 lwkt_reltoken(&tty_token);
1118 return(error);
1122 * Handle the Specialix ioctls. All MUST be called via the CONTROL device
1124 static int
1125 si_Sioctl(cdev_t dev, u_long cmd, caddr_t data, int flag, struct ucred *cred)
1127 struct si_softc *xsc;
1128 struct si_port *xpp;
1129 volatile struct si_reg *regp;
1130 struct si_tcsi *dp;
1131 struct si_pstat *sps;
1132 int *ip, error = 0;
1133 int card, port;
1134 int mynor = minor(dev);
1136 DPRINT((0, DBG_ENTRY|DBG_IOCTL, "si_Sioctl(%s,%lx,%p,%x)\n",
1137 devtoname(dev), cmd, data, flag));
1139 #if 1
1140 DPRINT((0, DBG_IOCTL, "TCSI_PORT=%lx\n", TCSI_PORT));
1141 DPRINT((0, DBG_IOCTL, "TCSI_CCB=%lx\n", TCSI_CCB));
1142 DPRINT((0, DBG_IOCTL, "TCSI_TTY=%lx\n", TCSI_TTY));
1143 #endif
1145 if (!IS_CONTROLDEV(mynor)) {
1146 DPRINT((0, DBG_IOCTL|DBG_FAIL, "not called from control device!\n"));
1147 return(ENODEV);
1150 crit_enter(); /* better safe than sorry */
1151 lwkt_gettoken(&tty_token);
1153 ip = (int *)data;
1155 #define SUCHECK if ((error = priv_check_cred(cred, PRIV_ROOT, 0))) goto out
1157 switch (cmd) {
1158 case TCSIPORTS:
1159 *ip = si_Nports;
1160 goto out;
1161 case TCSIMODULES:
1162 *ip = si_Nmodules;
1163 goto out;
1164 case TCSISDBG_ALL:
1165 SUCHECK;
1166 si_debug = *ip;
1167 goto out;
1168 case TCSIGDBG_ALL:
1169 *ip = si_debug;
1170 goto out;
1171 default:
1173 * Check that a controller for this port exists
1176 /* may also be a struct si_pstat, a superset of si_tcsi */
1178 dp = (struct si_tcsi *)data;
1179 sps = (struct si_pstat *)data;
1180 card = dp->tc_card;
1181 xsc = devclass_get_softc(si_devclass, card); /* check.. */
1182 if (xsc == NULL || xsc->sc_type == SIEMPTY) {
1183 error = ENOENT;
1184 goto out;
1187 * And check that a port exists
1189 port = dp->tc_port;
1190 if (port < 0 || port >= xsc->sc_nport) {
1191 error = ENOENT;
1192 goto out;
1194 xpp = xsc->sc_ports + port;
1195 regp = (struct si_reg *)xsc->sc_maddr;
1198 switch (cmd) {
1199 case TCSIDEBUG:
1200 #ifdef SI_DEBUG
1201 SUCHECK;
1202 if (xpp->sp_debug)
1203 xpp->sp_debug = 0;
1204 else {
1205 xpp->sp_debug = DBG_ALL;
1206 DPRINT((xpp, DBG_IOCTL, "debug toggled %s\n",
1207 (xpp->sp_debug&DBG_ALL)?"ON":"OFF"));
1209 break;
1210 #else
1211 error = ENODEV;
1212 goto out;
1213 #endif
1214 case TCSISDBG_LEVEL:
1215 case TCSIGDBG_LEVEL:
1216 #ifdef SI_DEBUG
1217 if (cmd == TCSIGDBG_LEVEL) {
1218 dp->tc_dbglvl = xpp->sp_debug;
1219 } else {
1220 SUCHECK;
1221 xpp->sp_debug = dp->tc_dbglvl;
1223 break;
1224 #else
1225 error = ENODEV;
1226 goto out;
1227 #endif
1228 case TCSIGRXIT:
1229 dp->tc_int = regp->rx_int_count;
1230 break;
1231 case TCSIRXIT:
1232 SUCHECK;
1233 regp->rx_int_count = dp->tc_int;
1234 break;
1235 case TCSIGIT:
1236 dp->tc_int = regp->int_count;
1237 break;
1238 case TCSIIT:
1239 SUCHECK;
1240 regp->int_count = dp->tc_int;
1241 break;
1242 case TCSISTATE:
1243 dp->tc_int = xpp->sp_ccb->hi_ip;
1244 break;
1245 /* these next three use a different structure */
1246 case TCSI_PORT:
1247 SUCHECK;
1248 si_bcopy(xpp, &sps->tc_siport, sizeof(sps->tc_siport));
1249 break;
1250 case TCSI_CCB:
1251 SUCHECK;
1252 si_vbcopy(xpp->sp_ccb, &sps->tc_ccb, sizeof(sps->tc_ccb));
1253 break;
1254 case TCSI_TTY:
1255 SUCHECK;
1256 si_bcopy(xpp->sp_tty, &sps->tc_tty, sizeof(sps->tc_tty));
1257 break;
1258 default:
1259 error = EINVAL;
1260 goto out;
1262 out:
1263 lwkt_reltoken(&tty_token);
1264 crit_exit();
1265 return(error); /* success */
1269 * siparam() : Configure line params
1270 * called at spltty();
1271 * this may sleep, does not flush, nor wait for drain, nor block writes
1272 * caller must arrange this if it's important..
1274 static int
1275 siparam(struct tty *tp, struct termios *t)
1277 struct si_port *pp = TP2PP(tp);
1278 volatile struct si_channel *ccbp;
1279 int cflag, iflag, oflag, lflag;
1280 int error = 0; /* shutup gcc */
1281 int ispeed = 0; /* shutup gcc */
1282 int ospeed = 0; /* shutup gcc */
1283 BYTE val;
1285 lwkt_gettoken(&tty_token);
1286 DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%p,%p)\n", tp, t));
1287 cflag = t->c_cflag;
1288 iflag = t->c_iflag;
1289 oflag = t->c_oflag;
1290 lflag = t->c_lflag;
1291 DPRINT((pp, DBG_PARAM, "OFLAG 0x%x CFLAG 0x%x IFLAG 0x%x LFLAG 0x%x\n",
1292 oflag, cflag, iflag, lflag));
1294 /* XXX - if Jet host and SXDC module, use extended baud rates */
1296 /* if not hung up.. */
1297 if (t->c_ospeed != 0) {
1298 /* translate baud rate to firmware values */
1299 ospeed = ttspeedtab(t->c_ospeed, bdrates);
1300 ispeed = t->c_ispeed ?
1301 ttspeedtab(t->c_ispeed, bdrates) : ospeed;
1303 /* enforce legit baud rate */
1304 if (ospeed < 0 || ispeed < 0) {
1305 lwkt_reltoken(&tty_token);
1306 return (EINVAL);
1310 crit_enter();
1312 ccbp = pp->sp_ccb;
1314 /* ========== set hi_break ========== */
1315 val = 0;
1316 if (iflag & IGNBRK) /* Breaks */
1317 val |= BR_IGN;
1318 if (iflag & BRKINT) /* Interrupt on break? */
1319 val |= BR_INT;
1320 if (iflag & PARMRK) /* Parity mark? */
1321 val |= BR_PARMRK;
1322 if (iflag & IGNPAR) /* Ignore chars with parity errors? */
1323 val |= BR_PARIGN;
1324 ccbp->hi_break = val;
1326 /* ========== set hi_csr ========== */
1327 /* if not hung up.. */
1328 if (t->c_ospeed != 0) {
1329 /* Set I/O speeds */
1330 val = (ispeed << 4) | ospeed;
1332 ccbp->hi_csr = val;
1334 /* ========== set hi_mr2 ========== */
1335 val = 0;
1336 if (cflag & CSTOPB) /* Stop bits */
1337 val |= MR2_2_STOP;
1338 else
1339 val |= MR2_1_STOP;
1341 * Enable H/W RTS/CTS handshaking. The default TA/MTA is
1342 * a DCE, hence the reverse sense of RTS and CTS
1344 /* Output Flow - RTS must be raised before data can be sent */
1345 if (cflag & CCTS_OFLOW)
1346 val |= MR2_RTSCONT;
1348 ccbp->hi_mr2 = val;
1350 /* ========== set hi_mr1 ========== */
1351 val = 0;
1352 if (!(cflag & PARENB)) /* Parity */
1353 val |= MR1_NONE;
1354 else
1355 val |= MR1_WITH;
1356 if (cflag & PARODD)
1357 val |= MR1_ODD;
1359 if ((cflag & CS8) == CS8) { /* 8 data bits? */
1360 val |= MR1_8_BITS;
1361 } else if ((cflag & CS7) == CS7) { /* 7 data bits? */
1362 val |= MR1_7_BITS;
1363 } else if ((cflag & CS6) == CS6) { /* 6 data bits? */
1364 val |= MR1_6_BITS;
1365 } else { /* Must be 5 */
1366 val |= MR1_5_BITS;
1369 * Enable H/W RTS/CTS handshaking. The default TA/MTA is
1370 * a DCE, hence the reverse sense of RTS and CTS
1372 /* Input Flow - CTS is raised when port is ready to receive data */
1373 if (cflag & CRTS_IFLOW)
1374 val |= MR1_CTSCONT;
1376 ccbp->hi_mr1 = val;
1378 /* ========== set hi_mask ========== */
1379 val = 0xff;
1380 if ((cflag & CS8) == CS8) { /* 8 data bits? */
1381 val &= 0xFF;
1382 } else if ((cflag & CS7) == CS7) { /* 7 data bits? */
1383 val &= 0x7F;
1384 } else if ((cflag & CS6) == CS6) { /* 6 data bits? */
1385 val &= 0x3F;
1386 } else { /* Must be 5 */
1387 val &= 0x1F;
1389 if (iflag & ISTRIP)
1390 val &= 0x7F;
1392 ccbp->hi_mask = val;
1394 /* ========== set hi_prtcl ========== */
1395 val = SP_DCEN; /* Monitor DCD always, or TIOCMGET misses it */
1396 if (iflag & IXANY)
1397 val |= SP_TANY;
1398 if (iflag & IXON)
1399 val |= SP_TXEN;
1400 if (iflag & IXOFF)
1401 val |= SP_RXEN;
1402 if (iflag & INPCK)
1403 val |= SP_PAEN;
1405 ccbp->hi_prtcl = val;
1408 /* ========== set hi_{rx|tx}{on|off} ========== */
1409 /* XXX: the card TOTALLY shields us from the flow control... */
1410 ccbp->hi_txon = t->c_cc[VSTART];
1411 ccbp->hi_txoff = t->c_cc[VSTOP];
1413 ccbp->hi_rxon = t->c_cc[VSTART];
1414 ccbp->hi_rxoff = t->c_cc[VSTOP];
1416 /* ========== send settings to the card ========== */
1417 /* potential sleep here */
1418 if (ccbp->hi_stat == IDLE_CLOSE) /* Not yet open */
1419 si_command(pp, LOPEN, SI_WAIT); /* open it */
1420 else
1421 si_command(pp, CONFIG, SI_WAIT); /* change params */
1423 /* ========== set DTR etc ========== */
1424 /* Hangup if ospeed == 0 */
1425 if (t->c_ospeed == 0) {
1426 (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);
1427 } else {
1429 * If the previous speed was 0, may need to re-enable
1430 * the modem signals
1432 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);
1435 DPRINT((pp, DBG_PARAM, "siparam, complete: MR1 %x MR2 %x HI_MASK %x PRTCL %x HI_BREAK %x\n",
1436 ccbp->hi_mr1, ccbp->hi_mr2, ccbp->hi_mask, ccbp->hi_prtcl, ccbp->hi_break));
1438 crit_exit();
1439 lwkt_reltoken(&tty_token);
1440 return(error);
1444 * Enable or Disable the writes to this channel...
1445 * "state" -> enabled = 1; disabled = 0;
1446 * NOTE: Must be called with tty_token held
1448 static void
1449 si_write_enable(struct si_port *pp, int state)
1452 ASSERT_LWKT_TOKEN_HELD(&tty_token);
1453 crit_enter();
1455 if (state) {
1456 pp->sp_state &= ~SS_BLOCKWRITE;
1457 if (pp->sp_state & SS_WAITWRITE) {
1458 pp->sp_state &= ~SS_WAITWRITE;
1459 /* thunder away! */
1460 wakeup((caddr_t)pp);
1462 } else {
1463 pp->sp_state |= SS_BLOCKWRITE;
1466 crit_exit();
1470 * Set/Get state of modem control lines.
1471 * Due to DCE-like behaviour of the adapter, some signals need translation:
1472 * TIOCM_DTR DSR
1473 * TIOCM_RTS CTS
1474 * NOTE: Must be called with tty_token held
1476 static int
1477 si_modem(struct si_port *pp, enum si_mctl cmd, int bits)
1479 volatile struct si_channel *ccbp;
1480 int x;
1482 ASSERT_LWKT_TOKEN_HELD(&tty_token);
1483 DPRINT((pp, DBG_ENTRY|DBG_MODEM, "si_modem(%p,%s,%x)\n", pp, si_mctl2str(cmd), bits));
1484 ccbp = pp->sp_ccb; /* Find channel address */
1485 switch (cmd) {
1486 case GET:
1487 x = ccbp->hi_ip;
1488 bits = TIOCM_LE;
1489 if (x & IP_DCD) bits |= TIOCM_CAR;
1490 if (x & IP_DTR) bits |= TIOCM_DTR;
1491 if (x & IP_RTS) bits |= TIOCM_RTS;
1492 if (x & IP_RI) bits |= TIOCM_RI;
1493 return(bits);
1494 case SET:
1495 ccbp->hi_op &= ~(OP_DSR|OP_CTS);
1496 /* fall through */
1497 case BIS:
1498 x = 0;
1499 if (bits & TIOCM_DTR)
1500 x |= OP_DSR;
1501 if (bits & TIOCM_RTS)
1502 x |= OP_CTS;
1503 ccbp->hi_op |= x;
1504 break;
1505 case BIC:
1506 if (bits & TIOCM_DTR)
1507 ccbp->hi_op &= ~OP_DSR;
1508 if (bits & TIOCM_RTS)
1509 ccbp->hi_op &= ~OP_CTS;
1511 return 0;
1515 * Handle change of modem state
1516 * NOTE: Must be called with tty_token held
1518 static void
1519 si_modem_state(struct si_port *pp, struct tty *tp, int hi_ip)
1521 ASSERT_LWKT_TOKEN_HELD(&tty_token);
1522 /* if a modem dev */
1523 if (hi_ip & IP_DCD) {
1524 if (!(pp->sp_last_hi_ip & IP_DCD)) {
1525 DPRINT((pp, DBG_INTR, "modem carr on t_line %d\n",
1526 tp->t_line));
1527 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1529 } else {
1530 if (pp->sp_last_hi_ip & IP_DCD) {
1531 DPRINT((pp, DBG_INTR, "modem carr off\n"));
1532 if ((*linesw[tp->t_line].l_modem)(tp, 0))
1533 (void) si_modem(pp, SET, 0);
1536 pp->sp_last_hi_ip = hi_ip;
1541 * Poller to catch missed interrupts.
1543 * Note that the SYSV Specialix drivers poll at 100 times per second to get
1544 * better response. We could really use a "periodic" version timeout(). :-)
1546 #ifdef POLL
1547 static void
1548 si_poll(void *nothing)
1550 struct si_softc *sc;
1551 int i;
1552 volatile struct si_reg *regp;
1553 struct si_port *pp;
1554 int lost, port;
1556 DPRINT((0, DBG_POLL, "si_poll()\n"));
1557 crit_enter();
1558 lwkt_gettoken(&tty_token);
1559 if (in_intr)
1560 goto out;
1561 lost = 0;
1562 for (i = 0; i < si_numunits; i++) {
1563 sc = devclass_get_softc(si_devclass, i);
1564 if (sc == NULL || sc->sc_type == SIEMPTY)
1565 continue;
1566 regp = (struct si_reg *)sc->sc_maddr;
1569 * See if there has been a pending interrupt for 2 seconds
1570 * or so. The test (int_scounter >= 200) won't correspond
1571 * to 2 seconds if int_count gets changed.
1573 if (regp->int_pending != 0) {
1574 if (regp->int_scounter >= 200 &&
1575 regp->initstat == 1) {
1576 kprintf("si%d: lost intr\n", i);
1577 lost++;
1579 } else {
1580 regp->int_scounter = 0;
1584 * gripe about no input flow control..
1586 pp = sc->sc_ports;
1587 for (port = 0; port < sc->sc_nport; pp++, port++) {
1588 if (pp->sp_delta_overflows > 0) {
1589 kprintf("si%d: %d tty level buffer overflows\n",
1590 i, pp->sp_delta_overflows);
1591 pp->sp_delta_overflows = 0;
1595 if (lost || si_realpoll)
1596 si_intr(NULL); /* call intr with fake vector */
1597 out:
1598 lwkt_reltoken(&tty_token);
1599 crit_exit();
1601 callout_reset(&poll_ch, si_pollrate, si_poll, NULL);
1603 #endif /* ifdef POLL */
1606 * The interrupt handler polls ALL ports on ALL adapters each time
1607 * it is called.
1610 static BYTE si_rxbuf[SI_BUFFERSIZE]; /* input staging area */
1611 static BYTE si_txbuf[SI_BUFFERSIZE]; /* output staging area */
1613 void
1614 si_intr(void *arg)
1616 struct si_softc *sc;
1617 struct si_port *pp;
1618 volatile struct si_channel *ccbp;
1619 struct tty *tp;
1620 volatile caddr_t maddr;
1621 BYTE op, ip;
1622 int x, card, port, n, i, isopen;
1623 volatile BYTE *z;
1624 BYTE c;
1626 sc = arg;
1628 DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "si_intr\n"));
1629 if (in_intr)
1630 return;
1631 in_intr = 1;
1633 lwkt_gettoken(&tty_token);
1636 * When we get an int we poll all the channels and do ALL pending
1637 * work, not just the first one we find. This allows all cards to
1638 * share the same vector.
1640 * XXX - But if we're sharing the vector with something that's NOT
1641 * a SI/XIO/SX card, we may be making more work for ourselves.
1643 for (card = 0; card < si_numunits; card++) {
1644 sc = devclass_get_softc(si_devclass, card);
1645 if (sc == NULL || sc->sc_type == SIEMPTY)
1646 continue;
1649 * First, clear the interrupt
1651 switch(sc->sc_type) {
1652 case SIHOST:
1653 maddr = sc->sc_maddr;
1654 ((volatile struct si_reg *)maddr)->int_pending = 0;
1655 /* flag nothing pending */
1656 *(maddr+SIINTCL) = 0x00; /* Set IRQ clear */
1657 *(maddr+SIINTCL_CL) = 0x00; /* Clear IRQ clear */
1658 break;
1659 case SIHOST2:
1660 maddr = sc->sc_maddr;
1661 ((volatile struct si_reg *)maddr)->int_pending = 0;
1662 *(maddr+SIPLIRQCLR) = 0x00;
1663 *(maddr+SIPLIRQCLR) = 0x10;
1664 break;
1665 case SIPCI:
1666 maddr = sc->sc_maddr;
1667 ((volatile struct si_reg *)maddr)->int_pending = 0;
1668 *(maddr+SIPCIINTCL) = 0x0;
1669 break;
1670 case SIJETPCI: /* fall through to JETISA case */
1671 case SIJETISA:
1672 maddr = sc->sc_maddr;
1673 ((volatile struct si_reg *)maddr)->int_pending = 0;
1674 *(maddr+SIJETINTCL) = 0x0;
1675 break;
1676 case SIEISA:
1677 maddr = sc->sc_maddr;
1678 ((volatile struct si_reg *)maddr)->int_pending = 0;
1679 (void)inb(sc->sc_iobase + 3);
1680 break;
1681 case SIEMPTY:
1682 default:
1683 continue;
1685 ((volatile struct si_reg *)maddr)->int_scounter = 0;
1688 * check each port
1690 for (pp = sc->sc_ports, port = 0; port < sc->sc_nport;
1691 pp++, port++) {
1692 ccbp = pp->sp_ccb;
1693 tp = pp->sp_tty;
1696 * See if a command has completed ?
1698 if (ccbp->hi_stat != pp->sp_pend) {
1699 DPRINT((pp, DBG_INTR,
1700 "si_intr hi_stat = 0x%x, pend = %d\n",
1701 ccbp->hi_stat, pp->sp_pend));
1702 switch(pp->sp_pend) {
1703 case LOPEN:
1704 case MPEND:
1705 case MOPEN:
1706 case CONFIG:
1707 case SBREAK:
1708 case EBREAK:
1709 pp->sp_pend = ccbp->hi_stat;
1710 /* sleeping in si_command */
1711 wakeup(&pp->sp_state);
1712 break;
1713 default:
1714 pp->sp_pend = ccbp->hi_stat;
1719 * Continue on if it's closed
1721 if (ccbp->hi_stat == IDLE_CLOSE) {
1722 continue;
1726 * Do modem state change if not a local device
1728 si_modem_state(pp, tp, ccbp->hi_ip);
1731 * Check to see if we should 'receive' characters.
1733 if (tp->t_state & TS_CONNECTED &&
1734 tp->t_state & TS_ISOPEN)
1735 isopen = 1;
1736 else
1737 isopen = 0;
1740 * Do input break processing
1742 if (ccbp->hi_state & ST_BREAK) {
1743 if (isopen) {
1744 (*linesw[tp->t_line].l_rint)(TTY_BI, tp);
1746 ccbp->hi_state &= ~ST_BREAK; /* A Bit iffy this */
1747 DPRINT((pp, DBG_INTR, "si_intr break\n"));
1751 * Do RX stuff - if not open then dump any characters.
1752 * XXX: This is VERY messy and needs to be cleaned up.
1754 * XXX: can we leave data in the host adapter buffer
1755 * when the clists are full? That may be dangerous
1756 * if the user cannot get an interrupt signal through.
1759 more_rx: /* XXX Sorry. the nesting was driving me bats! :-( */
1761 if (!isopen) {
1762 ccbp->hi_rxopos = ccbp->hi_rxipos;
1763 goto end_rx;
1767 * If the tty input buffers are blocked, stop emptying
1768 * the incoming buffers and let the auto flow control
1769 * assert..
1771 if (tp->t_state & TS_TBLOCK) {
1772 goto end_rx;
1776 * Process read characters if not skipped above
1778 op = ccbp->hi_rxopos;
1779 ip = ccbp->hi_rxipos;
1780 c = ip - op;
1781 if (c == 0) {
1782 goto end_rx;
1785 n = c & 0xff;
1786 if (n > 250)
1787 n = 250;
1789 DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
1790 n, op, ip));
1793 * Suck characters out of host card buffer into the
1794 * "input staging buffer" - so that we dont leave the
1795 * host card in limbo while we're possibly echoing
1796 * characters and possibly flushing input inside the
1797 * ldisc l_rint() routine.
1799 if (n <= SI_BUFFERSIZE - op) {
1801 DPRINT((pp, DBG_INTR, "\tsingle copy\n"));
1802 z = ccbp->hi_rxbuf + op;
1803 si_vbcopy(z, si_rxbuf, n);
1805 op += n;
1806 } else {
1807 x = SI_BUFFERSIZE - op;
1809 DPRINT((pp, DBG_INTR, "\tdouble part 1 %d\n", x));
1810 z = ccbp->hi_rxbuf + op;
1811 si_vbcopy(z, si_rxbuf, x);
1813 DPRINT((pp, DBG_INTR, "\tdouble part 2 %d\n",
1814 n - x));
1815 z = ccbp->hi_rxbuf;
1816 si_vbcopy(z, si_rxbuf + x, n - x);
1818 op += n;
1821 /* clear collected characters from buffer */
1822 ccbp->hi_rxopos = op;
1824 DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
1825 n, op, ip));
1828 * at this point...
1829 * n = number of chars placed in si_rxbuf
1833 * Avoid the grotesquely inefficient lineswitch
1834 * routine (ttyinput) in "raw" mode. It usually
1835 * takes about 450 instructions (that's without
1836 * canonical processing or echo!). slinput is
1837 * reasonably fast (usually 40 instructions
1838 * plus call overhead).
1840 if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1842 /* block if the driver supports it */
1843 if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER &&
1844 (tp->t_cflag & CRTS_IFLOW ||
1845 tp->t_iflag & IXOFF) &&
1846 !(tp->t_state & TS_TBLOCK))
1847 ttyblock(tp);
1849 tk_nin += n;
1850 tk_rawcc += n;
1851 tp->t_rawcc += n;
1853 pp->sp_delta_overflows +=
1854 b_to_q((char *)si_rxbuf, n, &tp->t_rawq);
1856 ttwakeup(tp);
1857 if (tp->t_state & TS_TTSTOP &&
1858 (tp->t_iflag & IXANY ||
1859 tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1860 tp->t_state &= ~TS_TTSTOP;
1861 tp->t_lflag &= ~FLUSHO;
1862 si_start(tp);
1864 } else {
1866 * It'd be nice to not have to go through the
1867 * function call overhead for each char here.
1868 * It'd be nice to block input it, saving a
1869 * loop here and the call/return overhead.
1871 for(x = 0; x < n; x++) {
1872 i = si_rxbuf[x];
1873 if ((*linesw[tp->t_line].l_rint)(i, tp)
1874 == -1) {
1875 pp->sp_delta_overflows++;
1878 * doesn't seem to be much point doing
1879 * this here.. this driver has no
1880 * softtty processing! ??
1882 if (pp->sp_hotchar && i == pp->sp_hotchar) {
1883 setsofttty();
1887 goto more_rx; /* try for more until RXbuf is empty */
1889 end_rx: /* XXX: Again, sorry about the gotos.. :-) */
1892 * Do TX stuff
1894 (*linesw[tp->t_line].l_start)(tp);
1896 } /* end of for (all ports on this controller) */
1897 } /* end of for (all controllers) */
1899 in_intr = 0;
1900 lwkt_reltoken(&tty_token);
1901 DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "end si_intr\n"));
1905 * Nudge the transmitter...
1907 * XXX: I inherited some funny code here. It implies the host card only
1908 * interrupts when the transmit buffer reaches the low-water-mark, and does
1909 * not interrupt when it's actually hits empty. In some cases, we have
1910 * processes waiting for complete drain, and we need to simulate an interrupt
1911 * about when we think the buffer is going to be empty (and retry if not).
1912 * I really am not certain about this... I *need* the hardware manuals.
1914 static void
1915 si_start(struct tty *tp)
1917 struct si_port *pp;
1918 volatile struct si_channel *ccbp;
1919 struct clist *qp;
1920 BYTE ipos;
1921 int nchar;
1922 int count, n, amount, buffer_full;
1924 crit_enter();
1925 lwkt_gettoken(&tty_token);
1927 qp = &tp->t_outq;
1928 pp = TP2PP(tp);
1930 DPRINT((pp, DBG_ENTRY|DBG_START,
1931 "si_start(%p) t_state %x sp_state %x t_outq.c_cc %d\n",
1932 tp, tp->t_state, pp->sp_state, qp->c_cc));
1934 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
1935 goto out;
1937 buffer_full = 0;
1938 ccbp = pp->sp_ccb;
1940 count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
1941 DPRINT((pp, DBG_START, "count %d\n", (BYTE)count));
1943 while ((nchar = qp->c_cc) > 0) {
1944 if ((BYTE)count >= 255) {
1945 buffer_full++;
1946 break;
1948 amount = min(nchar, (255 - (BYTE)count));
1949 ipos = (unsigned int)ccbp->hi_txipos;
1950 n = q_to_b(&tp->t_outq, si_txbuf, amount);
1951 /* will it fit in one lump? */
1952 if ((SI_BUFFERSIZE - ipos) >= n) {
1953 si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos], n);
1954 } else {
1955 si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos],
1956 SI_BUFFERSIZE - ipos);
1957 si_bcopyv(si_txbuf + (SI_BUFFERSIZE - ipos),
1958 &ccbp->hi_txbuf[0], n - (SI_BUFFERSIZE - ipos));
1960 ccbp->hi_txipos += n;
1961 count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
1964 if (count != 0 && nchar == 0) {
1965 tp->t_state |= TS_BUSY;
1966 } else {
1967 tp->t_state &= ~TS_BUSY;
1970 /* wakeup time? */
1971 ttwwakeup(tp);
1973 DPRINT((pp, DBG_START, "count %d, nchar %d, tp->t_state 0x%x\n",
1974 (BYTE)count, nchar, tp->t_state));
1976 if (tp->t_state & TS_BUSY)
1978 int time;
1980 time = ttspeedtab(tp->t_ospeed, chartimes);
1982 if (time > 0) {
1983 if (time < nchar)
1984 time = nchar / time;
1985 else
1986 time = 2;
1987 } else {
1988 DPRINT((pp, DBG_START,
1989 "bad char time value! %d\n", time));
1990 time = hz/10;
1993 if ((pp->sp_state & (SS_LSTART|SS_INLSTART)) == SS_LSTART) {
1994 callout_stop(&pp->lstart_ch);
1995 } else {
1996 pp->sp_state |= SS_LSTART;
1998 DPRINT((pp, DBG_START, "arming lstart, time=%d\n", time));
1999 callout_reset(&pp->lstart_ch, time, si_lstart, (void *)pp);
2002 out:
2003 lwkt_reltoken(&tty_token);
2004 crit_exit();
2005 DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n"));
2009 * Note: called at splsoftclock from the timeout code
2010 * This has to deal with two things... cause wakeups while waiting for
2011 * tty drains on last process exit, and call l_start at about the right
2012 * time for protocols like ppp.
2014 static void
2015 si_lstart(void *arg)
2017 struct si_port *pp = arg;
2018 struct tty *tp;
2020 DPRINT((pp, DBG_ENTRY|DBG_LSTART, "si_lstart(%p) sp_state %x\n",
2021 pp, pp->sp_state));
2023 crit_enter();
2024 lwkt_gettoken(&tty_token);
2026 if ((pp->sp_state & SS_OPEN) == 0 || (pp->sp_state & SS_LSTART) == 0) {
2027 lwkt_reltoken(&tty_token);
2028 crit_exit();
2029 return;
2031 pp->sp_state &= ~SS_LSTART;
2032 pp->sp_state |= SS_INLSTART;
2034 tp = pp->sp_tty;
2036 /* deal with the process exit case */
2037 ttwwakeup(tp);
2039 /* nudge protocols - eg: ppp */
2040 (*linesw[tp->t_line].l_start)(tp);
2042 pp->sp_state &= ~SS_INLSTART;
2043 lwkt_reltoken(&tty_token);
2044 crit_exit();
2048 * Stop output on a line. called at spltty();
2050 void
2051 si_stop(struct tty *tp, int rw)
2053 volatile struct si_channel *ccbp;
2054 struct si_port *pp;
2056 lwkt_gettoken(&tty_token);
2057 pp = TP2PP(tp);
2058 ccbp = pp->sp_ccb;
2060 DPRINT((TP2PP(tp), DBG_ENTRY|DBG_STOP, "si_stop(%p,%x)\n", tp, rw));
2062 /* XXX: must check (rw & FWRITE | FREAD) etc flushing... */
2063 if (rw & FWRITE) {
2064 /* what level are we meant to be flushing anyway? */
2065 if (tp->t_state & TS_BUSY) {
2066 si_command(TP2PP(tp), WFLUSH, SI_NOWAIT);
2067 tp->t_state &= ~TS_BUSY;
2068 ttwwakeup(tp); /* Bruce???? */
2071 #if 1 /* XXX: this doesn't work right yet.. */
2072 /* XXX: this may have been failing because we used to call l_rint()
2073 * while we were looping based on these two counters. Now, we collect
2074 * the data and then loop stuffing it into l_rint(), making this
2075 * useless. Should we cause this to blow away the staging buffer?
2077 if (rw & FREAD) {
2078 ccbp->hi_rxopos = ccbp->hi_rxipos;
2080 #endif
2081 lwkt_reltoken(&tty_token);
2085 * Issue a command to the host card CPU.
2088 static void
2089 si_command(struct si_port *pp, int cmd, int waitflag)
2091 volatile struct si_channel *ccbp = pp->sp_ccb;
2092 int x;
2094 DPRINT((pp, DBG_ENTRY|DBG_PARAM, "si_command(%p,%x,%d): hi_stat 0x%x\n",
2095 pp, cmd, waitflag, ccbp->hi_stat));
2097 crit_enter(); /* Keep others out */
2098 lwkt_gettoken(&tty_token);
2100 /* wait until it's finished what it was doing.. */
2101 /* XXX: sits in IDLE_BREAK until something disturbs it or break
2102 * is turned off. */
2103 while((x = ccbp->hi_stat) != IDLE_OPEN &&
2104 x != IDLE_CLOSE &&
2105 x != IDLE_BREAK &&
2106 x != cmd) {
2107 if (in_intr) { /* Prevent sleep in intr */
2108 DPRINT((pp, DBG_PARAM,
2109 "cmd intr collision - completing %d\trequested %d\n",
2110 x, cmd));
2111 lwkt_reltoken(&tty_token);
2112 crit_exit();
2113 return;
2114 } else if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, PCATCH,
2115 "sicmd1", 1)) {
2116 lwkt_reltoken(&tty_token);
2117 crit_exit();
2118 return;
2121 /* it should now be in IDLE_{OPEN|CLOSE|BREAK}, or "cmd" */
2123 /* if there was a pending command, cause a state-change wakeup */
2124 switch(pp->sp_pend) {
2125 case LOPEN:
2126 case MPEND:
2127 case MOPEN:
2128 case CONFIG:
2129 case SBREAK:
2130 case EBREAK:
2131 wakeup(&pp->sp_state);
2132 break;
2133 default:
2134 break;
2137 pp->sp_pend = cmd; /* New command pending */
2138 ccbp->hi_stat = cmd; /* Post it */
2140 if (waitflag) {
2141 if (in_intr) { /* If in interrupt handler */
2142 DPRINT((pp, DBG_PARAM,
2143 "attempt to sleep in si_intr - cmd req %d\n",
2144 cmd));
2145 lwkt_reltoken(&tty_token);
2146 crit_exit();
2147 return;
2148 } else while(ccbp->hi_stat != IDLE_OPEN &&
2149 ccbp->hi_stat != IDLE_BREAK) {
2150 if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, PCATCH,
2151 "sicmd2", 0))
2152 break;
2155 lwkt_reltoken(&tty_token);
2156 crit_exit();
2159 static void
2160 si_disc_optim(struct tty *tp, struct termios *t, struct si_port *pp)
2162 lwkt_gettoken(&tty_token);
2164 * XXX can skip a lot more cases if Smarts. Maybe
2165 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we
2166 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state.
2168 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) &&
2169 (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) &&
2170 (!(t->c_iflag & PARMRK) ||
2171 (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) &&
2172 !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) &&
2173 linesw[tp->t_line].l_rint == ttyinput)
2174 tp->t_state |= TS_CAN_BYPASS_L_RINT;
2175 else
2176 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
2177 pp->sp_hotchar = linesw[tp->t_line].l_hotchar;
2178 DPRINT((pp, DBG_OPTIM, "bypass: %s, hotchar: %x\n",
2179 (tp->t_state & TS_CAN_BYPASS_L_RINT) ? "on" : "off",
2180 pp->sp_hotchar));
2181 lwkt_reltoken(&tty_token);
2185 #ifdef SI_DEBUG
2187 void
2188 si_dprintf(struct si_port *pp, int flags, const char *fmt, ...)
2190 __va_list ap;
2192 if ((pp == NULL && (si_debug&flags)) ||
2193 (pp != NULL && ((pp->sp_debug&flags) || (si_debug&flags)))) {
2194 if (pp != NULL)
2195 kprintf("%ci%d(%d): ", 's',
2196 (int)SI_CARD(minor(pp->sp_tty->t_dev)),
2197 (int)SI_PORT(minor(pp->sp_tty->t_dev)));
2198 __va_start(ap, fmt);
2199 kvprintf(fmt, ap);
2200 __va_end(ap);
2204 static char *
2205 si_mctl2str(enum si_mctl cmd)
2207 switch (cmd) {
2208 case GET:
2209 return("GET");
2210 case SET:
2211 return("SET");
2212 case BIS:
2213 return("BIS");
2214 case BIC:
2215 return("BIC");
2217 return("BAD");
2220 #endif /* DEBUG */
2222 static char *
2223 si_modulename(int host_type, int uart_type)
2225 switch (host_type) {
2226 /* Z280 based cards */
2227 case SIEISA:
2228 case SIHOST2:
2229 case SIHOST:
2230 case SIPCI:
2231 switch (uart_type) {
2232 case 0:
2233 return(" (XIO)");
2234 case 1:
2235 return(" (SI)");
2237 break;
2238 /* T225 based hosts */
2239 case SIJETPCI:
2240 case SIJETISA:
2241 switch (uart_type) {
2242 case 0:
2243 return(" (SI)");
2244 case 40:
2245 return(" (XIO)");
2246 case 72:
2247 return(" (SXDC)");
2249 break;
2251 return("");