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