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