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