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