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