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