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