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