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