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