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