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