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