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