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