digi.c revision 126078
1/*-
2 * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
3 *   based on work by Slawa Olhovchenkov
4 *                    John Prince <johnp@knight-trosoft.com>
5 *                    Eric Hernes
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/dev/digi/digi.c 126078 2004-02-21 20:41:11Z phk $
30 */
31
32/*-
33 * TODO:
34 *	Figure out what the con bios stuff is supposed to do
35 *	Test with *LOTS* more cards - I only have a PCI8r and an ISA Xem.
36 */
37
38#include "opt_compat.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/proc.h>
43#include <sys/conf.h>
44#include <sys/linker.h>
45#include <sys/kernel.h>
46#include <sys/mbuf.h>
47#include <sys/malloc.h>
48#include <sys/tty.h>
49#include <sys/syslog.h>
50#include <sys/fcntl.h>
51#include <sys/bus.h>
52#include <sys/bus.h>
53#include <machine/resource.h>
54
55#include <sys/digiio.h>
56#include <dev/digi/digireg.h>
57#include <dev/digi/digi.h>
58#include <dev/digi/digi_mod.h>
59#include <dev/digi/digi_pci.h>
60
61
62#define	CTRL_DEV		0x800000
63#define	CALLOUT_MASK		0x400000
64#define	CONTROL_INIT_STATE	0x100000
65#define	CONTROL_LOCK_STATE	0x200000
66#define	CONTROL_MASK		(CTRL_DEV|CONTROL_INIT_STATE|CONTROL_LOCK_STATE)
67#define UNIT_MASK		0x030000
68#define PORT_MASK		0x0000FF
69#define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))
70#define	MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
71#define	MINOR_TO_UNIT(mynor)	(((mynor) & UNIT_MASK)>>16)
72#define MINOR_TO_PORT(mynor)	((mynor) & PORT_MASK)
73
74static d_open_t		digiopen;
75static d_close_t	digiclose;
76static d_read_t		digiread;
77static d_write_t	digiwrite;
78static d_ioctl_t	digiioctl;
79
80static void	digistop(struct tty *tp, int rw);
81static int	digimctl(struct digi_p *port, int bits, int how);
82static void	digi_poll(void *ptr);
83static void	digi_freemoduledata(struct digi_softc *);
84static void	fepcmd(struct digi_p *port, int cmd, int op, int ncmds);
85static void	digistart(struct tty *tp);
86static int	digiparam(struct tty *tp, struct termios *t);
87static void	digihardclose(struct digi_p *port);
88static void	digi_intr(void *);
89static int	digi_init(struct digi_softc *_sc);
90static int	digi_loadmoduledata(struct digi_softc *);
91static int	digi_inuse(struct digi_softc *);
92static void	digi_free_state(struct digi_softc *);
93
94#define	fepcmd_b(port, cmd, op1, op2, ncmds) \
95	fepcmd(port, cmd, (op2 << 8) | op1, ncmds)
96#define	fepcmd_w	fepcmd
97
98
99static speed_t digidefaultrate = TTYDEF_SPEED;
100
101struct con_bios {
102	struct con_bios *next;
103	u_char *bios;
104	size_t size;
105};
106
107static struct con_bios *con_bios_list;
108devclass_t	 digi_devclass;
109static char	 driver_name[] = "digi";
110unsigned 	 digi_debug = 0;
111
112static struct speedtab digispeedtab[] = {
113	{ 0,		0},			/* old (sysV-like) Bx codes */
114	{ 50,		1},
115	{ 75,		2},
116	{ 110,		3},
117	{ 134,		4},
118	{ 150,		5},
119	{ 200,		6},
120	{ 300,		7},
121	{ 600,		8},
122	{ 1200,		9},
123	{ 1800,		10},
124	{ 2400,		11},
125	{ 4800,		12},
126	{ 9600,		13},
127	{ 19200,	14},
128	{ 38400,	15},
129	{ 57600,	(02000 | 1)},
130	{ 76800,	(02000 | 2)},
131	{ 115200,	(02000 | 3)},
132	{ 230400,	(02000 | 6)},
133	{ -1,		-1}
134};
135
136const struct digi_control_signals digi_xixe_signals = {
137	0x02, 0x08, 0x10, 0x20, 0x40, 0x80
138};
139
140const struct digi_control_signals digi_normal_signals = {
141	0x02, 0x80, 0x20, 0x10, 0x40, 0x01
142};
143
144static struct cdevsw digi_sw = {
145	.d_open =	digiopen,
146	.d_close =	digiclose,
147	.d_read =	digiread,
148	.d_write =	digiwrite,
149	.d_ioctl =	digiioctl,
150	.d_name =	driver_name,
151	.d_flags =	D_TTY,
152};
153
154static void
155digi_poll(void *ptr)
156{
157	struct digi_softc *sc;
158
159	sc = (struct digi_softc *)ptr;
160	callout_handle_init(&sc->callout);
161	digi_intr(sc);
162	sc->callout = timeout(digi_poll, sc, (hz >= 200) ? hz / 100 : 1);
163}
164
165static void
166digi_int_test(void *v)
167{
168	struct digi_softc *sc = v;
169
170	callout_handle_init(&sc->inttest);
171#ifdef DIGI_INTERRUPT
172	if (sc->intr_timestamp.tv_sec || sc->intr_timestamp.tv_usec) {
173		/* interrupt OK! */
174		return;
175	}
176	log(LOG_ERR, "digi%d: Interrupt didn't work, use polled mode\n", unit);
177#endif
178	sc->callout = timeout(digi_poll, sc, (hz >= 200) ? hz / 100 : 1);
179}
180
181static void
182digi_freemoduledata(struct digi_softc *sc)
183{
184	if (sc->fep.data != NULL) {
185		free(sc->fep.data, M_TTYS);
186		sc->fep.data = NULL;
187	}
188	if (sc->link.data != NULL) {
189		free(sc->link.data, M_TTYS);
190		sc->link.data = NULL;
191	}
192	if (sc->bios.data != NULL) {
193		free(sc->bios.data, M_TTYS);
194		sc->bios.data = NULL;
195	}
196}
197
198static int
199digi_bcopy(const void *vfrom, void *vto, size_t sz)
200{
201	volatile const char *from = (volatile const char *)vfrom;
202	volatile char *to = (volatile char *)vto;
203	size_t i;
204
205	for (i = 0; i < sz; i++)
206		*to++ = *from++;
207
208	from = (const volatile char *)vfrom;
209	to = (volatile char *)vto;
210	for (i = 0; i < sz; i++)
211		if (*to++ != *from++)
212			return (0);
213	return (1);
214}
215
216void
217digi_delay(struct digi_softc *sc, const char *txt, u_long timo)
218{
219	if (cold)
220		DELAY(timo * 1000000 / hz);
221	else
222		tsleep(sc, PUSER | PCATCH, txt, timo);
223}
224
225static int
226digi_init(struct digi_softc *sc)
227{
228	int i, cnt, resp;
229	u_char *ptr;
230	int lowwater;
231	struct digi_p *port;
232	volatile struct board_chan *bc;
233
234	ptr = NULL;
235
236	if (sc->status == DIGI_STATUS_DISABLED) {
237		log(LOG_ERR, "digi%d: Cannot init a disabled card\n",
238		    sc->res.unit);
239		return (EIO);
240	}
241	if (sc->bios.data == NULL) {
242		log(LOG_ERR, "digi%d: Cannot init without BIOS\n",
243		    sc->res.unit);
244		return (EIO);
245	}
246#if 0
247	if (sc->link.data == NULL && sc->model >= PCCX) {
248		log(LOG_ERR, "digi%d: Cannot init without link info\n",
249		    sc->res.unit);
250		return (EIO);
251	}
252#endif
253	if (sc->fep.data == NULL) {
254		log(LOG_ERR, "digi%d: Cannot init without fep code\n",
255		    sc->res.unit);
256		return (EIO);
257	}
258	sc->status = DIGI_STATUS_NOTINIT;
259
260	if (sc->numports) {
261		/*
262		 * We're re-initialising - maybe because someone's attached
263		 * another port module.  For now, we just re-initialise
264		 * everything.
265		 */
266		if (digi_inuse(sc))
267			return (EBUSY);
268
269		digi_free_state(sc);
270	}
271
272	ptr = sc->setwin(sc, MISCGLOBAL);
273	for (i = 0; i < 16; i += 2)
274		vW(ptr + i) = 0;
275
276	switch (sc->model) {
277	case PCXEVE:
278		outb(sc->wport, 0xff);		/* window 7 */
279		ptr = sc->vmem + (BIOSCODE & 0x1fff);
280
281		if (!digi_bcopy(sc->bios.data, ptr, sc->bios.size)) {
282			device_printf(sc->dev, "BIOS upload failed\n");
283			return (EIO);
284		}
285
286		outb(sc->port, FEPCLR);
287		break;
288
289	case PCXE:
290	case PCXI:
291	case PCCX:
292		ptr = sc->setwin(sc, BIOSCODE + ((0xf000 - sc->mem_seg) << 4));
293		if (!digi_bcopy(sc->bios.data, ptr, sc->bios.size)) {
294			device_printf(sc->dev, "BIOS upload failed\n");
295			return (EIO);
296		}
297		break;
298
299	case PCXEM:
300	case PCIEPCX:
301	case PCIXR:
302		if (sc->pcibus)
303			PCIPORT = FEPRST;
304		else
305			outb(sc->port, FEPRST | FEPMEM);
306
307		for (i = 0; ((sc->pcibus ? PCIPORT : inb(sc->port)) &
308		    FEPMASK) != FEPRST; i++) {
309			if (i > hz) {
310				log(LOG_ERR, "digi%d: %s init reset failed\n",
311				    sc->res.unit, sc->name);
312				return (EIO);
313			}
314			digi_delay(sc, "digiinit0", 5);
315		}
316		DLOG(DIGIDB_INIT, (sc->dev, "Got init reset after %d us\n", i));
317
318		/* Now upload the BIOS */
319		cnt = (sc->bios.size < sc->win_size - BIOSOFFSET) ?
320		    sc->bios.size : sc->win_size - BIOSOFFSET;
321
322		ptr = sc->setwin(sc, BIOSOFFSET);
323		if (!digi_bcopy(sc->bios.data, ptr, cnt)) {
324			device_printf(sc->dev, "BIOS upload (1) failed\n");
325			return (EIO);
326		}
327
328		if (cnt != sc->bios.size) {
329			/* and the second part */
330			ptr = sc->setwin(sc, sc->win_size);
331			if (!digi_bcopy(sc->bios.data + cnt, ptr,
332			    sc->bios.size - cnt)) {
333				device_printf(sc->dev, "BIOS upload failed\n");
334				return (EIO);
335			}
336		}
337
338		ptr = sc->setwin(sc, 0);
339		vW(ptr + 0) = 0x0401;
340		vW(ptr + 2) = 0x0bf0;
341		vW(ptr + 4) = 0x0000;
342		vW(ptr + 6) = 0x0000;
343
344		break;
345	}
346
347	DLOG(DIGIDB_INIT, (sc->dev, "BIOS uploaded\n"));
348
349	ptr = sc->setwin(sc, MISCGLOBAL);
350	W(ptr) = 0;
351
352	if (sc->pcibus) {
353		PCIPORT = FEPCLR;
354		resp = FEPRST;
355	} else if (sc->model == PCXEVE) {
356		outb(sc->port, FEPCLR);
357		resp = FEPRST;
358	} else {
359		outb(sc->port, FEPCLR | FEPMEM);
360		resp = FEPRST | FEPMEM;
361	}
362
363	for (i = 0; ((sc->pcibus ? PCIPORT : inb(sc->port)) & FEPMASK)
364	    == resp; i++) {
365		if (i > hz) {
366			log(LOG_ERR, "digi%d: BIOS start failed\n",
367			    sc->res.unit);
368			return (EIO);
369		}
370		digi_delay(sc, "digibios0", 5);
371	}
372
373	DLOG(DIGIDB_INIT, (sc->dev, "BIOS started after %d us\n", i));
374
375	for (i = 0; vW(ptr) != *(u_short *)"GD"; i++) {
376		if (i > 2*hz) {
377			log(LOG_ERR, "digi%d: BIOS boot failed "
378			    "(0x%02x != 0x%02x)\n",
379			    sc->res.unit, vW(ptr), *(u_short *)"GD");
380			return (EIO);
381		}
382		digi_delay(sc, "digibios1", 5);
383	}
384
385	DLOG(DIGIDB_INIT, (sc->dev, "BIOS booted after %d iterations\n", i));
386
387	if (sc->link.data != NULL) {
388		DLOG(DIGIDB_INIT, (sc->dev, "Loading link data\n"));
389		ptr = sc->setwin(sc, 0xcd0);
390		digi_bcopy(sc->link.data, ptr, 21);	/* XXX 21 ? */
391	}
392
393	/* load FEP/OS */
394
395	switch (sc->model) {
396	case PCXE:
397	case PCXEVE:
398	case PCXI:
399		ptr = sc->setwin(sc, sc->model == PCXI ? 0x2000 : 0x0);
400		digi_bcopy(sc->fep.data, ptr, sc->fep.size);
401
402		/* A BIOS request to move our data to 0x2000 */
403		ptr = sc->setwin(sc, MBOX);
404		vW(ptr + 0) = 2;
405		vW(ptr + 2) = sc->mem_seg + FEPCODESEG;
406		vW(ptr + 4) = 0;
407		vW(ptr + 6) = FEPCODESEG;
408		vW(ptr + 8) = 0;
409		vW(ptr + 10) = sc->fep.size;
410
411		/* Run the BIOS request */
412		outb(sc->port, FEPREQ | FEPMEM);
413		outb(sc->port, FEPCLR | FEPMEM);
414
415		for (i = 0; W(ptr); i++) {
416			if (i > hz) {
417				log(LOG_ERR, "digi%d: FEP/OS move failed\n",
418				    sc->res.unit);
419				sc->hidewin(sc);
420				return (EIO);
421			}
422			digi_delay(sc, "digifep0", 5);
423		}
424		DLOG(DIGIDB_INIT,
425		    (sc->dev, "FEP/OS moved after %d iterations\n", i));
426
427		/* Clear the confirm word */
428		ptr = sc->setwin(sc, FEPSTAT);
429		vW(ptr + 0) = 0;
430
431		/* A BIOS request to execute the FEP/OS */
432		ptr = sc->setwin(sc, MBOX);
433		vW(ptr + 0) = 0x01;
434		vW(ptr + 2) = FEPCODESEG;
435		vW(ptr + 4) = 0x04;
436
437		/* Run the BIOS request */
438		outb(sc->port, FEPREQ);
439		outb(sc->port, FEPCLR);
440
441		ptr = sc->setwin(sc, FEPSTAT);
442
443		break;
444
445	case PCXEM:
446	case PCIEPCX:
447	case PCIXR:
448		DLOG(DIGIDB_INIT, (sc->dev, "Loading FEP/OS\n"));
449
450		cnt = (sc->fep.size < sc->win_size - BIOSOFFSET) ?
451		    sc->fep.size : sc->win_size - BIOSOFFSET;
452
453		ptr = sc->setwin(sc, BIOSOFFSET);
454		digi_bcopy(sc->fep.data, ptr, cnt);
455
456		if (cnt != sc->fep.size) {
457			ptr = sc->setwin(sc, BIOSOFFSET + cnt);
458			digi_bcopy(sc->fep.data + cnt, ptr,
459			    sc->fep.size - cnt);
460		}
461
462		DLOG(DIGIDB_INIT, (sc->dev, "FEP/OS loaded\n"));
463
464		ptr = sc->setwin(sc, 0xc30);
465		W(ptr + 4) = 0x1004;
466		W(ptr + 6) = 0xbfc0;
467		W(ptr + 0) = 0x03;
468		W(ptr + 2) = 0x00;
469
470		/* Clear the confirm word */
471		ptr = sc->setwin(sc, FEPSTAT);
472		W(ptr + 0) = 0;
473
474		if (sc->port)
475			outb(sc->port, 0);		/* XXX necessary ? */
476
477		break;
478
479	case PCCX:
480		ptr = sc->setwin(sc, 0xd000);
481		digi_bcopy(sc->fep.data, ptr, sc->fep.size);
482
483		/* A BIOS request to execute the FEP/OS */
484		ptr = sc->setwin(sc, 0xc40);
485		W(ptr + 0) = 1;
486		W(ptr + 2) = FEPCODE >> 4;
487		W(ptr + 4) = 4;
488
489		/* Clear the confirm word */
490		ptr = sc->setwin(sc, FEPSTAT);
491		W(ptr + 0) = 0;
492
493		/* Run the BIOS request */
494		outb(sc->port, FEPREQ | FEPMEM); /* send interrupt to BIOS */
495		outb(sc->port, FEPCLR | FEPMEM);
496		break;
497	}
498
499	/* Now wait 'till the FEP/OS has booted */
500	for (i = 0; vW(ptr) != *(u_short *)"OS"; i++) {
501		if (i > 2*hz) {
502			log(LOG_ERR, "digi%d: FEP/OS start failed "
503			    "(0x%02x != 0x%02x)\n",
504			    sc->res.unit, vW(ptr), *(u_short *)"OS");
505			sc->hidewin(sc);
506			return (EIO);
507		}
508		digi_delay(sc, "digifep1", 5);
509	}
510
511	DLOG(DIGIDB_INIT, (sc->dev, "FEP/OS started after %d iterations\n", i));
512
513	if (sc->model >= PCXEM) {
514		ptr = sc->setwin(sc, 0xe04);
515		vW(ptr) = 2;
516		ptr = sc->setwin(sc, 0xc02);
517		sc->numports = vW(ptr);
518	} else {
519		ptr = sc->setwin(sc, 0xc22);
520		sc->numports = vW(ptr);
521	}
522
523	if (sc->numports == 0) {
524		device_printf(sc->dev, "%s, 0 ports found\n", sc->name);
525		sc->hidewin(sc);
526		return (0);
527	}
528
529	if (sc->numports > 256) {
530		/* Our minor numbering scheme is broken for more than 256 */
531		device_printf(sc->dev, "%s, 256 ports (%d ports found)\n",
532		    sc->name, sc->numports);
533		sc->numports = 256;
534	} else
535		device_printf(sc->dev, "%s, %d ports found\n", sc->name,
536		    sc->numports);
537
538	if (sc->ports)
539		free(sc->ports, M_TTYS);
540	sc->ports = malloc(sizeof(struct digi_p) * sc->numports,
541	    M_TTYS, M_WAITOK | M_ZERO);
542
543	if (sc->ttys)
544		free(sc->ttys, M_TTYS);
545	sc->ttys = malloc(sizeof(struct tty) * sc->numports,
546	    M_TTYS, M_WAITOK | M_ZERO);
547
548	/*
549	 * XXX Should read port 0xc90 for an array of 2byte values, 1 per
550	 * port.  If the value is 0, the port is broken....
551	 */
552
553	ptr = sc->setwin(sc, 0);
554
555	/* We should now init per-port structures */
556	bc = (volatile struct board_chan *)(ptr + CHANSTRUCT);
557	sc->gdata = (volatile struct global_data *)(ptr + FEP_GLOBAL);
558
559	sc->memcmd = ptr + sc->gdata->cstart;
560	sc->memevent = ptr + sc->gdata->istart;
561
562	for (i = 0; i < sc->numports; i++, bc++) {
563		port = sc->ports + i;
564		port->pnum = i;
565		port->sc = sc;
566		port->status = ENABLED;
567		port->tp = sc->ttys + i;
568		port->bc = bc;
569
570		if (sc->model == PCXEVE) {
571			port->txbuf = ptr +
572			    (((bc->tseg - sc->mem_seg) << 4) & 0x1fff);
573			port->rxbuf = ptr +
574			    (((bc->rseg - sc->mem_seg) << 4) & 0x1fff);
575			port->txwin = FEPWIN | ((bc->tseg - sc->mem_seg) >> 9);
576			port->rxwin = FEPWIN | ((bc->rseg - sc->mem_seg) >> 9);
577		} else if (sc->model == PCXI || sc->model == PCXE) {
578			port->txbuf = ptr + ((bc->tseg - sc->mem_seg) << 4);
579			port->rxbuf = ptr + ((bc->rseg - sc->mem_seg) << 4);
580			port->txwin = port->rxwin = 0;
581		} else {
582			port->txbuf = ptr +
583			    (((bc->tseg - sc->mem_seg) << 4) % sc->win_size);
584			port->rxbuf = ptr +
585			    (((bc->rseg - sc->mem_seg) << 4) % sc->win_size);
586			port->txwin = FEPWIN |
587			    (((bc->tseg - sc->mem_seg) << 4) / sc->win_size);
588			port->rxwin = FEPWIN |
589			    (((bc->rseg - sc->mem_seg) << 4) / sc->win_size);
590		}
591		port->txbufsize = bc->tmax + 1;
592		port->rxbufsize = bc->rmax + 1;
593
594		lowwater = port->txbufsize >> 2;
595		if (lowwater > 1024)
596			lowwater = 1024;
597		sc->setwin(sc, 0);
598		fepcmd_w(port, STXLWATER, lowwater, 10);
599		fepcmd_w(port, SRXLWATER, port->rxbufsize >> 2, 10);
600		fepcmd_w(port, SRXHWATER, (3 * port->rxbufsize) >> 2, 10);
601
602		bc->edelay = 100;
603		port->dtr_wait = 3 * hz;
604
605		/*
606		 * We don't use all the flags from <sys/ttydefaults.h> since
607		 * they are only relevant for logins.  It's important to have
608		 * echo off initially so that the line doesn't start blathering
609		 * before the echo flag can be turned off.
610		 */
611		port->it_in.c_iflag = 0;
612		port->it_in.c_oflag = 0;
613		port->it_in.c_cflag = TTYDEF_CFLAG;
614		port->it_in.c_lflag = 0;
615		termioschars(&port->it_in);
616		port->it_in.c_ispeed = port->it_in.c_ospeed = digidefaultrate;
617		port->it_out = port->it_in;
618		port->send_ring = 1;	/* Default action on signal RI */
619
620		port->dev[0] = make_dev(&digi_sw, (sc->res.unit << 16) + i,
621		    UID_ROOT, GID_WHEEL, 0600, "ttyD%d.%d", sc->res.unit, i);
622		port->dev[1] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) |
623		    CONTROL_INIT_STATE, UID_ROOT, GID_WHEEL,
624		    0600, "ttyiD%d.%d", sc->res.unit, i);
625		port->dev[2] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) |
626		    CONTROL_LOCK_STATE, UID_ROOT, GID_WHEEL,
627		    0600, "ttylD%d.%d", sc->res.unit, i);
628		port->dev[3] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) |
629		    CALLOUT_MASK, UID_UUCP, GID_DIALER,
630		    0660, "cuaD%d.%d", sc->res.unit, i);
631		port->dev[4] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) |
632		    CALLOUT_MASK | CONTROL_INIT_STATE, UID_UUCP, GID_DIALER,
633		    0660, "cuaiD%d.%d", sc->res.unit, i);
634		port->dev[5] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) |
635		    CALLOUT_MASK | CONTROL_LOCK_STATE, UID_UUCP, GID_DIALER,
636		    0660, "cualD%d.%d", sc->res.unit, i);
637	}
638
639	sc->hidewin(sc);
640	sc->inttest = timeout(digi_int_test, sc, hz);
641	/* fepcmd_w(&sc->ports[0], 0xff, 0, 0); */
642	sc->status = DIGI_STATUS_ENABLED;
643
644	return (0);
645}
646
647static int
648digimctl(struct digi_p *port, int bits, int how)
649{
650	int mstat;
651
652	if (how == DMGET) {
653		port->sc->setwin(port->sc, 0);
654		mstat = port->bc->mstat;
655		port->sc->hidewin(port->sc);
656		bits = TIOCM_LE;
657		if (mstat & port->sc->csigs->rts)
658			bits |= TIOCM_RTS;
659		if (mstat & port->cd)
660			bits |= TIOCM_CD;
661		if (mstat & port->dsr)
662			bits |= TIOCM_DSR;
663		if (mstat & port->sc->csigs->cts)
664			bits |= TIOCM_CTS;
665		if (mstat & port->sc->csigs->ri)
666			bits |= TIOCM_RI;
667		if (mstat & port->sc->csigs->dtr)
668			bits |= TIOCM_DTR;
669		return (bits);
670	}
671
672	/* Only DTR and RTS may be set */
673	mstat = 0;
674	if (bits & TIOCM_DTR)
675		mstat |= port->sc->csigs->dtr;
676	if (bits & TIOCM_RTS)
677		mstat |= port->sc->csigs->rts;
678
679	switch (how) {
680	case DMSET:
681		fepcmd_b(port, SETMODEM, mstat, ~mstat, 0);
682		break;
683	case DMBIS:
684		fepcmd_b(port, SETMODEM, mstat, 0, 0);
685		break;
686	case DMBIC:
687		fepcmd_b(port, SETMODEM, 0, mstat, 0);
688		break;
689	}
690
691	return (0);
692}
693
694static void
695digi_disc_optim(struct tty *tp, struct termios *t, struct digi_p *port)
696{
697	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP)) &&
698	    (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) &&
699	    (!(t->c_iflag & PARMRK) ||
700	    (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) &&
701	    !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) &&
702	    linesw[tp->t_line].l_rint == ttyinput)
703		tp->t_state |= TS_CAN_BYPASS_L_RINT;
704	else
705		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
706}
707
708static int
709digiopen(dev_t dev, int flag, int mode, struct thread *td)
710{
711	struct digi_softc *sc;
712	struct tty *tp;
713	int unit;
714	int pnum;
715	struct digi_p *port;
716	int s;
717	int error, mynor;
718	volatile struct board_chan *bc;
719
720	error = 0;
721	mynor = minor(dev);
722	unit = MINOR_TO_UNIT(minor(dev));
723	pnum = MINOR_TO_PORT(minor(dev));
724
725	sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
726	if (!sc)
727		return (ENXIO);
728
729	if (sc->status != DIGI_STATUS_ENABLED) {
730		DLOG(DIGIDB_OPEN, (sc->dev, "Cannot open a disabled card\n"));
731		return (ENXIO);
732	}
733	if (pnum >= sc->numports) {
734		DLOG(DIGIDB_OPEN, (sc->dev, "port%d: Doesn't exist\n", pnum));
735		return (ENXIO);
736	}
737	if (mynor & (CTRL_DEV | CONTROL_MASK)) {
738		sc->opencnt++;
739		return (0);
740	}
741	port = &sc->ports[pnum];
742	tp = dev->si_tty = port->tp;
743	bc = port->bc;
744
745	s = spltty();
746
747open_top:
748	while (port->status & DIGI_DTR_OFF) {
749		port->wopeners++;
750		error = tsleep(&port->dtr_wait, TTIPRI | PCATCH, "digidtr", 0);
751		port->wopeners--;
752		if (error)
753			goto out;
754	}
755
756	if (tp->t_state & TS_ISOPEN) {
757		/*
758		 * The device is open, so everything has been initialized.
759		 * Handle conflicts.
760		 */
761		if (mynor & CALLOUT_MASK) {
762			if (!port->active_out) {
763				error = EBUSY;
764				DLOG(DIGIDB_OPEN, (sc->dev, "port %d:"
765				    " BUSY error = %d\n", pnum, error));
766				goto out;
767			}
768		} else if (port->active_out) {
769			if (flag & O_NONBLOCK) {
770				error = EBUSY;
771				DLOG(DIGIDB_OPEN, (sc->dev,
772				    "port %d: BUSY error = %d\n", pnum, error));
773				goto out;
774			}
775			port->wopeners++;
776			error = tsleep(&port->active_out, TTIPRI | PCATCH,
777			    "digibi", 0);
778			port->wopeners--;
779			if (error != 0) {
780				DLOG(DIGIDB_OPEN, (sc->dev,
781				    "port %d: tsleep(digibi) error = %d\n",
782				    pnum, error));
783				goto out;
784			}
785			goto open_top;
786		}
787		if (tp->t_state & TS_XCLUDE && suser(td) != 0) {
788			error = EBUSY;
789			goto out;
790		}
791	} else {
792		/*
793		 * The device isn't open, so there are no conflicts.
794		 * Initialize it.  Initialization is done twice in many
795		 * cases: to preempt sleeping callin opens if we are callout,
796		 * and to complete a callin open after DCD rises.
797		 */
798		tp->t_oproc = digistart;
799		tp->t_param = digiparam;
800		tp->t_stop = digistop;
801		tp->t_dev = dev;
802		tp->t_termios = (mynor & CALLOUT_MASK) ?
803		    port->it_out : port->it_in;
804		sc->setwin(sc, 0);
805
806		bc->rout = bc->rin;	/* clear input queue */
807		bc->idata = 1;
808		bc->iempty = 1;
809		bc->ilow = 1;
810		bc->mint = port->cd | port->sc->csigs->ri;
811		bc->tin = bc->tout;
812		if (port->ialtpin) {
813			port->cd = sc->csigs->dsr;
814			port->dsr = sc->csigs->cd;
815		} else {
816			port->cd = sc->csigs->cd;
817			port->dsr = sc->csigs->dsr;
818		}
819		port->wopeners++;			/* XXX required ? */
820		error = digiparam(tp, &tp->t_termios);
821		port->wopeners--;
822
823		if (error != 0) {
824			DLOG(DIGIDB_OPEN, (sc->dev,
825			    "port %d: cxpparam error = %d\n", pnum, error));
826			goto out;
827		}
828		ttsetwater(tp);
829
830		/* handle fake and initial DCD for callout devices */
831
832		if (bc->mstat & port->cd || mynor & CALLOUT_MASK)
833			linesw[tp->t_line].l_modem(tp, 1);
834	}
835
836	/* Wait for DCD if necessary */
837	if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) &&
838	    !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
839		port->wopeners++;
840		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "digidcd", 0);
841		port->wopeners--;
842		if (error != 0) {
843			DLOG(DIGIDB_OPEN, (sc->dev,
844			    "port %d: tsleep(digidcd) error = %d\n",
845			    pnum, error));
846			goto out;
847		}
848		goto open_top;
849	}
850	error = linesw[tp->t_line].l_open(dev, tp);
851	DLOG(DIGIDB_OPEN, (sc->dev, "port %d: l_open error = %d\n",
852	    pnum, error));
853
854	digi_disc_optim(tp, &tp->t_termios, port);
855
856	if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
857		port->active_out = TRUE;
858
859	if (tp->t_state & TS_ISOPEN)
860		sc->opencnt++;
861out:
862	splx(s);
863
864	if (!(tp->t_state & TS_ISOPEN))
865		digihardclose(port);
866
867	DLOG(DIGIDB_OPEN, (sc->dev, "port %d: open() returns %d\n",
868	    pnum, error));
869
870	return (error);
871}
872
873static int
874digiclose(dev_t dev, int flag, int mode, struct thread *td)
875{
876	int mynor;
877	struct tty *tp;
878	int unit, pnum;
879	struct digi_softc *sc;
880	struct digi_p *port;
881	int s;
882
883	mynor = minor(dev);
884	unit = MINOR_TO_UNIT(mynor);
885	pnum = MINOR_TO_PORT(mynor);
886
887	sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
888	KASSERT(sc, ("digi%d: softc not allocated in digiclose\n", unit));
889
890	if (mynor & (CTRL_DEV | CONTROL_MASK)) {
891		sc->opencnt--;
892		return (0);
893	}
894
895	port = sc->ports + pnum;
896	tp = port->tp;
897
898	DLOG(DIGIDB_CLOSE, (sc->dev, "port %d: closing\n", pnum));
899
900	s = spltty();
901	linesw[tp->t_line].l_close(tp, flag);
902	digi_disc_optim(tp, &tp->t_termios, port);
903	digistop(tp, FREAD | FWRITE);
904	digihardclose(port);
905	ttyclose(tp);
906	if (--sc->opencnt == 0)
907		splx(s);
908	return (0);
909}
910
911static void
912digidtrwakeup(void *chan)
913{
914	struct digi_p *port = chan;
915
916	port->status &= ~DIGI_DTR_OFF;
917	wakeup(&port->dtr_wait);
918	port->wopeners--;
919}
920
921static void
922digihardclose(struct digi_p *port)
923{
924	volatile struct board_chan *bc;
925	int s;
926
927	bc = port->bc;
928
929	s = spltty();
930	port->sc->setwin(port->sc, 0);
931	bc->idata = 0;
932	bc->iempty = 0;
933	bc->ilow = 0;
934	bc->mint = 0;
935	if ((port->tp->t_cflag & HUPCL) ||
936	    (!port->active_out && !(bc->mstat & port->cd) &&
937	    !(port->it_in.c_cflag & CLOCAL)) ||
938	    !(port->tp->t_state & TS_ISOPEN)) {
939		digimctl(port, TIOCM_DTR | TIOCM_RTS, DMBIC);
940		if (port->dtr_wait != 0) {
941			/* Schedule a wakeup of any callin devices */
942			port->wopeners++;
943			timeout(&digidtrwakeup, port, port->dtr_wait);
944			port->status |= DIGI_DTR_OFF;
945		}
946	}
947	port->active_out = FALSE;
948	wakeup(&port->active_out);
949	wakeup(TSA_CARR_ON(port->tp));
950	splx(s);
951}
952
953static int
954digiread(dev_t dev, struct uio *uio, int flag)
955{
956	int mynor;
957	struct tty *tp;
958	int error, unit, pnum;
959	struct digi_softc *sc;
960
961	mynor = minor(dev);
962	if (mynor & CONTROL_MASK)
963		return (ENODEV);
964
965	unit = MINOR_TO_UNIT(mynor);
966	pnum = MINOR_TO_PORT(mynor);
967
968	sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
969	KASSERT(sc, ("digi%d: softc not allocated in digiclose\n", unit));
970	tp = &sc->ttys[pnum];
971
972	error = linesw[tp->t_line].l_read(tp, uio, flag);
973	DLOG(DIGIDB_READ, (sc->dev, "port %d: read() returns %d\n",
974	    pnum, error));
975
976	return (error);
977}
978
979static int
980digiwrite(dev_t dev, struct uio *uio, int flag)
981{
982	int mynor;
983	struct tty *tp;
984	int error, unit, pnum;
985	struct digi_softc *sc;
986
987	mynor = minor(dev);
988	if (mynor & CONTROL_MASK)
989		return (ENODEV);
990
991	unit = MINOR_TO_UNIT(mynor);
992	pnum = MINOR_TO_PORT(mynor);
993
994	sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
995	KASSERT(sc, ("digi%d: softc not allocated in digiclose\n", unit));
996	tp = &sc->ttys[pnum];
997
998	error = linesw[tp->t_line].l_write(tp, uio, flag);
999	DLOG(DIGIDB_WRITE, (sc->dev, "port %d: write() returns %d\n",
1000	    pnum, error));
1001
1002	return (error);
1003}
1004
1005/*
1006 * Load module "digi_<mod>.ko" and look for a symbol called digi_mod_<mod>.
1007 *
1008 * Populate sc->bios, sc->fep, and sc->link from this data.
1009 *
1010 * sc->fep.data, sc->bios.data and sc->link.data are malloc()d according
1011 * to their respective sizes.
1012 *
1013 * The module is unloaded when we're done.
1014 */
1015static int
1016digi_loadmoduledata(struct digi_softc *sc)
1017{
1018	struct digi_mod *digi_mod;
1019	linker_file_t lf;
1020	char *modfile, *sym;
1021	caddr_t symptr;
1022	int modlen, res;
1023
1024	KASSERT(sc->bios.data == NULL, ("Uninitialised BIOS variable"));
1025	KASSERT(sc->fep.data == NULL, ("Uninitialised FEP variable"));
1026	KASSERT(sc->link.data == NULL, ("Uninitialised LINK variable"));
1027	KASSERT(sc->module != NULL, ("Uninitialised module name"));
1028
1029	modlen = strlen(sc->module);
1030	modfile = malloc(modlen + 6, M_TEMP, M_WAITOK);
1031	snprintf(modfile, modlen + 6, "digi_%s", sc->module);
1032	if ((res = linker_reference_module(modfile, NULL, &lf)) != 0) {
1033		if (res == ENOENT && rootdev == NODEV)
1034			printf("%s: Failed to autoload module: No filesystem\n",
1035			    modfile);
1036		else
1037			printf("%s: Failed %d to autoload module\n", modfile,
1038			    res);
1039	}
1040	free(modfile, M_TEMP);
1041	if (res != 0)
1042		return (res);
1043
1044	sym = malloc(modlen + 10, M_TEMP, M_WAITOK);
1045	snprintf(sym, modlen + 10, "digi_mod_%s", sc->module);
1046	if ((symptr = linker_file_lookup_symbol(lf, sym, 0)) == NULL)
1047		printf("digi_%s.ko: Symbol `%s' not found\n", sc->module, sym);
1048	free(sym, M_TEMP);
1049
1050	digi_mod = (struct digi_mod *)symptr;
1051	if (digi_mod->dm_version != DIGI_MOD_VERSION) {
1052		printf("digi_%s.ko: Invalid version %d (need %d)\n",
1053		    sc->module, digi_mod->dm_version, DIGI_MOD_VERSION);
1054		linker_file_unload(lf);
1055		return (EINVAL);
1056	}
1057
1058	sc->bios.size = digi_mod->dm_bios.size;
1059	if (sc->bios.size != 0 && digi_mod->dm_bios.data != NULL) {
1060		sc->bios.data = malloc(sc->bios.size, M_TTYS, M_WAITOK);
1061		bcopy(digi_mod->dm_bios.data, sc->bios.data, sc->bios.size);
1062	}
1063
1064	sc->fep.size = digi_mod->dm_fep.size;
1065	if (sc->fep.size != 0 && digi_mod->dm_fep.data != NULL) {
1066		sc->fep.data = malloc(sc->fep.size, M_TTYS, M_WAITOK);
1067		bcopy(digi_mod->dm_fep.data, sc->fep.data, sc->fep.size);
1068	}
1069
1070	sc->link.size = digi_mod->dm_link.size;
1071	if (sc->link.size != 0 && digi_mod->dm_link.data != NULL) {
1072		sc->link.data = malloc(sc->link.size, M_TTYS, M_WAITOK);
1073		bcopy(digi_mod->dm_link.data, sc->link.data, sc->link.size);
1074	}
1075
1076	linker_file_unload(lf);
1077
1078	return (0);
1079}
1080
1081static int
1082digiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
1083{
1084	int unit, pnum, mynor, error, s;
1085	struct digi_softc *sc;
1086	struct digi_p *port;
1087	struct tty *tp;
1088#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1089	int oldcmd;
1090	struct termios term;
1091#endif
1092
1093	mynor = minor(dev);
1094	unit = MINOR_TO_UNIT(mynor);
1095	pnum = MINOR_TO_PORT(mynor);
1096
1097	sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
1098	KASSERT(sc, ("digi%d: softc not allocated in digiioctl\n", unit));
1099
1100	if (sc->status == DIGI_STATUS_DISABLED)
1101		return (ENXIO);
1102
1103	if (mynor & CTRL_DEV) {
1104		switch (cmd) {
1105		case DIGIIO_DEBUG:
1106#ifdef DEBUG
1107			digi_debug = *(int *)data;
1108			return (0);
1109#else
1110			device_printf(sc->dev, "DEBUG not defined\n");
1111			return (ENXIO);
1112#endif
1113		case DIGIIO_REINIT:
1114			digi_loadmoduledata(sc);
1115			error = digi_init(sc);
1116			digi_freemoduledata(sc);
1117			return (error);
1118
1119		case DIGIIO_MODEL:
1120			*(enum digi_model *)data = sc->model;
1121			return (0);
1122
1123		case DIGIIO_IDENT:
1124			return (copyout(sc->name, *(char **)data,
1125			    strlen(sc->name) + 1));
1126		}
1127	}
1128
1129	if (pnum >= sc->numports)
1130		return (ENXIO);
1131
1132	port = sc->ports + pnum;
1133	if (!(port->status & ENABLED))
1134		return (ENXIO);
1135
1136	tp = port->tp;
1137
1138	if (mynor & CONTROL_MASK) {
1139		struct termios *ct;
1140
1141		switch (mynor & CONTROL_MASK) {
1142		case CONTROL_INIT_STATE:
1143			ct = (mynor & CALLOUT_MASK) ?
1144			    &port->it_out : &port->it_in;
1145			break;
1146		case CONTROL_LOCK_STATE:
1147			ct = (mynor & CALLOUT_MASK) ?
1148			    &port->lt_out : &port->lt_in;
1149			break;
1150		default:
1151			return (ENODEV);	/* /dev/nodev */
1152		}
1153
1154		switch (cmd) {
1155		case TIOCSETA:
1156			error = suser(td);
1157			if (error != 0)
1158				return (error);
1159			*ct = *(struct termios *)data;
1160			return (0);
1161
1162		case TIOCGETA:
1163			*(struct termios *)data = *ct;
1164			return (0);
1165
1166		case TIOCGETD:
1167			*(int *)data = TTYDISC;
1168			return (0);
1169
1170		case TIOCGWINSZ:
1171			bzero(data, sizeof(struct winsize));
1172			return (0);
1173
1174		case DIGIIO_GETALTPIN:
1175			switch (mynor & CONTROL_MASK) {
1176			case CONTROL_INIT_STATE:
1177				*(int *)data = port->ialtpin;
1178				break;
1179
1180			case CONTROL_LOCK_STATE:
1181				*(int *)data = port->laltpin;
1182				break;
1183
1184			default:
1185				panic("Confusion when re-testing minor");
1186				return (ENODEV);
1187			}
1188			return (0);
1189
1190		case DIGIIO_SETALTPIN:
1191			switch (mynor & CONTROL_MASK) {
1192			case CONTROL_INIT_STATE:
1193				if (!port->laltpin) {
1194					port->ialtpin = !!*(int *)data;
1195					DLOG(DIGIDB_SET, (sc->dev,
1196					    "port%d: initial ALTPIN %s\n", pnum,
1197					    port->ialtpin ? "set" : "cleared"));
1198				}
1199				break;
1200
1201			case CONTROL_LOCK_STATE:
1202				port->laltpin = !!*(int *)data;
1203				DLOG(DIGIDB_SET, (sc->dev,
1204				    "port%d: ALTPIN %slocked\n",
1205				    pnum, port->laltpin ? "" : "un"));
1206				break;
1207
1208			default:
1209				panic("Confusion when re-testing minor");
1210				return (ENODEV);
1211			}
1212			return (0);
1213
1214		default:
1215			return (ENOTTY);
1216		}
1217	}
1218
1219	switch (cmd) {
1220	case DIGIIO_GETALTPIN:
1221		*(int *)data = !!(port->dsr == sc->csigs->cd);
1222		return (0);
1223
1224	case DIGIIO_SETALTPIN:
1225		if (!port->laltpin) {
1226			if (*(int *)data) {
1227				DLOG(DIGIDB_SET, (sc->dev,
1228				    "port%d: ALTPIN set\n", pnum));
1229				port->cd = sc->csigs->dsr;
1230				port->dsr = sc->csigs->cd;
1231			} else {
1232				DLOG(DIGIDB_SET, (sc->dev,
1233				    "port%d: ALTPIN cleared\n", pnum));
1234				port->cd = sc->csigs->cd;
1235				port->dsr = sc->csigs->dsr;
1236			}
1237		}
1238		return (0);
1239	}
1240
1241	tp = port->tp;
1242#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1243	term = tp->t_termios;
1244	oldcmd = cmd;
1245	error = ttsetcompat(tp, &cmd, data, &term);
1246	if (error != 0)
1247		return (error);
1248	if (cmd != oldcmd)
1249		data = (caddr_t) & term;
1250#endif
1251	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
1252		int cc;
1253		struct termios *dt;
1254		struct termios *lt;
1255
1256		dt = (struct termios *)data;
1257		lt = (mynor & CALLOUT_MASK) ? &port->lt_out : &port->lt_in;
1258
1259		dt->c_iflag =
1260		    (tp->t_iflag & lt->c_iflag) | (dt->c_iflag & ~lt->c_iflag);
1261		dt->c_oflag =
1262		    (tp->t_oflag & lt->c_oflag) | (dt->c_oflag & ~lt->c_oflag);
1263		dt->c_cflag =
1264		    (tp->t_cflag & lt->c_cflag) | (dt->c_cflag & ~lt->c_cflag);
1265		dt->c_lflag =
1266		    (tp->t_lflag & lt->c_lflag) | (dt->c_lflag & ~lt->c_lflag);
1267		port->c_iflag = dt->c_iflag & (IXOFF | IXON | IXANY);
1268		dt->c_iflag &= ~(IXOFF | IXON | IXANY);
1269		for (cc = 0; cc < NCCS; ++cc)
1270			if (lt->c_cc[cc] != 0)
1271				dt->c_cc[cc] = tp->t_cc[cc];
1272		if (lt->c_ispeed != 0)
1273			dt->c_ispeed = tp->t_ispeed;
1274		if (lt->c_ospeed != 0)
1275			dt->c_ospeed = tp->t_ospeed;
1276	}
1277	error = linesw[tp->t_line].l_ioctl(tp, cmd, data, flag, td);
1278	if (error == 0 && cmd == TIOCGETA)
1279		((struct termios *)data)->c_iflag |= port->c_iflag;
1280
1281	if (error >= 0 && error != ENOIOCTL)
1282		return (error);
1283	s = spltty();
1284	error = ttioctl(tp, cmd, data, flag);
1285	if (error == 0 && cmd == TIOCGETA)
1286		((struct termios *)data)->c_iflag |= port->c_iflag;
1287
1288	digi_disc_optim(tp, &tp->t_termios, port);
1289	if (error >= 0 && error != ENOIOCTL) {
1290		splx(s);
1291		return (error);
1292	}
1293	sc->setwin(sc, 0);
1294	switch (cmd) {
1295	case DIGIIO_RING:
1296		port->send_ring = *(u_char *)data;
1297		break;
1298	case TIOCSBRK:
1299		/*
1300		 * now it sends 400 millisecond break because I don't know
1301		 * how to send an infinite break
1302		 */
1303		fepcmd_w(port, SENDBREAK, 400, 10);
1304		break;
1305	case TIOCCBRK:
1306		/* now it's empty */
1307		break;
1308	case TIOCSDTR:
1309		digimctl(port, TIOCM_DTR, DMBIS);
1310		break;
1311	case TIOCCDTR:
1312		digimctl(port, TIOCM_DTR, DMBIC);
1313		break;
1314	case TIOCMSET:
1315		digimctl(port, *(int *)data, DMSET);
1316		break;
1317	case TIOCMBIS:
1318		digimctl(port, *(int *)data, DMBIS);
1319		break;
1320	case TIOCMBIC:
1321		digimctl(port, *(int *)data, DMBIC);
1322		break;
1323	case TIOCMGET:
1324		*(int *)data = digimctl(port, 0, DMGET);
1325		break;
1326	case TIOCMSDTRWAIT:
1327		error = suser(td);
1328		if (error != 0) {
1329			splx(s);
1330			return (error);
1331		}
1332		port->dtr_wait = *(int *)data *hz / 100;
1333
1334		break;
1335	case TIOCMGDTRWAIT:
1336		*(int *)data = port->dtr_wait * 100 / hz;
1337		break;
1338#ifdef DIGI_INTERRUPT
1339	case TIOCTIMESTAMP:
1340		*(struct timeval *)data = sc->intr_timestamp;
1341
1342		break;
1343#endif
1344	default:
1345		splx(s);
1346		return (ENOTTY);
1347	}
1348	splx(s);
1349	return (0);
1350}
1351
1352static int
1353digiparam(struct tty *tp, struct termios *t)
1354{
1355	int mynor;
1356	int unit;
1357	int pnum;
1358	struct digi_softc *sc;
1359	struct digi_p *port;
1360	int cflag;
1361	int iflag;
1362	int hflow;
1363	int s;
1364	int window;
1365
1366	mynor = minor(tp->t_dev);
1367	unit = MINOR_TO_UNIT(mynor);
1368	pnum = MINOR_TO_PORT(mynor);
1369
1370	sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
1371	KASSERT(sc, ("digi%d: softc not allocated in digiparam\n", unit));
1372
1373	port = &sc->ports[pnum];
1374
1375	DLOG(DIGIDB_SET, (sc->dev, "port%d: setting parameters\n", pnum));
1376
1377	if (t->c_ispeed == 0)
1378		t->c_ispeed = t->c_ospeed;
1379
1380	cflag = ttspeedtab(t->c_ospeed, digispeedtab);
1381
1382	if (cflag < 0 || (cflag > 0 && t->c_ispeed != t->c_ospeed))
1383		return (EINVAL);
1384
1385	s = splclock();
1386
1387	window = sc->window;
1388	sc->setwin(sc, 0);
1389
1390	if (cflag == 0) {				/* hangup */
1391		DLOG(DIGIDB_SET, (sc->dev, "port%d: hangup\n", pnum));
1392		digimctl(port, TIOCM_DTR | TIOCM_RTS, DMBIC);
1393	} else {
1394		digimctl(port, TIOCM_DTR | TIOCM_RTS, DMBIS);
1395
1396		DLOG(DIGIDB_SET, (sc->dev, "port%d: CBAUD = %d\n", pnum,
1397		    cflag));
1398
1399#if 0
1400		/* convert flags to sysV-style values */
1401		if (t->c_cflag & PARODD)
1402			cflag |= 0x0200;
1403		if (t->c_cflag & PARENB)
1404			cflag |= 0x0100;
1405		if (t->c_cflag & CSTOPB)
1406			cflag |= 0x0080;
1407#else
1408		/* convert flags to sysV-style values */
1409		if (t->c_cflag & PARODD)
1410			cflag |= FEP_PARODD;
1411		if (t->c_cflag & PARENB)
1412			cflag |= FEP_PARENB;
1413		if (t->c_cflag & CSTOPB)
1414			cflag |= FEP_CSTOPB;
1415		if (t->c_cflag & CLOCAL)
1416			cflag |= FEP_CLOCAL;
1417#endif
1418
1419		cflag |= (t->c_cflag & CSIZE) >> 4;
1420		DLOG(DIGIDB_SET, (sc->dev, "port%d: CFLAG = 0x%x\n", pnum,
1421		    cflag));
1422		fepcmd_w(port, SETCFLAGS, (unsigned)cflag, 0);
1423	}
1424
1425	iflag =
1426	    t->c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP);
1427	if (port->c_iflag & IXON)
1428		iflag |= 0x400;
1429	if (port->c_iflag & IXANY)
1430		iflag |= 0x800;
1431	if (port->c_iflag & IXOFF)
1432		iflag |= 0x1000;
1433
1434	DLOG(DIGIDB_SET, (sc->dev, "port%d: set iflag = 0x%x\n", pnum, iflag));
1435	fepcmd_w(port, SETIFLAGS, (unsigned)iflag, 0);
1436
1437	hflow = 0;
1438	if (t->c_cflag & CDTR_IFLOW)
1439		hflow |= sc->csigs->dtr;
1440	if (t->c_cflag & CRTS_IFLOW)
1441		hflow |= sc->csigs->rts;
1442	if (t->c_cflag & CCTS_OFLOW)
1443		hflow |= sc->csigs->cts;
1444	if (t->c_cflag & CDSR_OFLOW)
1445		hflow |= port->dsr;
1446	if (t->c_cflag & CCAR_OFLOW)
1447		hflow |= port->cd;
1448
1449	DLOG(DIGIDB_SET, (sc->dev, "port%d: set hflow = 0x%x\n", pnum, hflow));
1450	fepcmd_w(port, SETHFLOW, 0xff00 | (unsigned)hflow, 0);
1451
1452	DLOG(DIGIDB_SET, (sc->dev, "port%d: set startc(0x%x), stopc(0x%x)\n",
1453	    pnum, t->c_cc[VSTART], t->c_cc[VSTOP]));
1454	fepcmd_b(port, SONOFFC, t->c_cc[VSTART], t->c_cc[VSTOP], 0);
1455
1456	if (sc->window != 0)
1457		sc->towin(sc, 0);
1458	if (window != 0)
1459		sc->towin(sc, window);
1460	splx(s);
1461
1462	return (0);
1463}
1464
1465static void
1466digi_intr(void *vp)
1467{
1468	struct digi_p *port;
1469	char *cxcon;
1470	struct digi_softc *sc;
1471	int ehead, etail;
1472	volatile struct board_chan *bc;
1473	struct tty *tp;
1474	int head, tail;
1475	int wrapmask;
1476	int size, window;
1477	struct event {
1478		u_char pnum;
1479		u_char event;
1480		u_char mstat;
1481		u_char lstat;
1482	} event;
1483
1484	sc = vp;
1485
1486	if (sc->status != DIGI_STATUS_ENABLED) {
1487		DLOG(DIGIDB_IRQ, (sc->dev, "interrupt on disabled board !\n"));
1488		return;
1489	}
1490
1491#ifdef DIGI_INTERRUPT
1492	microtime(&sc->intr_timestamp);
1493#endif
1494
1495	window = sc->window;
1496	sc->setwin(sc, 0);
1497
1498	if (sc->model >= PCXEM && W(sc->vmem + 0xd00)) {
1499		struct con_bios *con = con_bios_list;
1500		register u_char *ptr;
1501
1502		ptr = sc->vmem + W(sc->vmem + 0xd00);
1503		while (con) {
1504			if (ptr[1] && W(ptr + 2) == W(con->bios + 2))
1505				/* Not first block -- exact match */
1506				break;
1507
1508			if (W(ptr + 4) >= W(con->bios + 4) &&
1509			    W(ptr + 4) <= W(con->bios + 6))
1510				/* Initial search concetrator BIOS */
1511				break;
1512		}
1513
1514		if (con == NULL) {
1515			log(LOG_ERR, "digi%d: wanted bios LREV = 0x%04x"
1516			    " not found!\n", sc->res.unit, W(ptr + 4));
1517			W(ptr + 10) = 0;
1518			W(sc->vmem + 0xd00) = 0;
1519			goto eoi;
1520		}
1521		cxcon = con->bios;
1522		W(ptr + 4) = W(cxcon + 4);
1523		W(ptr + 6) = W(cxcon + 6);
1524		if (ptr[1] == 0)
1525			W(ptr + 2) = W(cxcon + 2);
1526		W(ptr + 8) = (ptr[1] << 6) + W(cxcon + 8);
1527		size = W(cxcon + 10) - (ptr[1] << 10);
1528		if (size <= 0) {
1529			W(ptr + 8) = W(cxcon + 8);
1530			W(ptr + 10) = 0;
1531		} else {
1532			if (size > 1024)
1533				size = 1024;
1534			W(ptr + 10) = size;
1535			bcopy(cxcon + (ptr[1] << 10), ptr + 12, size);
1536		}
1537		W(sc->vmem + 0xd00) = 0;
1538		goto eoi;
1539	}
1540
1541	ehead = sc->gdata->ein;
1542	etail = sc->gdata->eout;
1543	if (ehead == etail) {
1544#ifdef DEBUG
1545		sc->intr_count++;
1546		if (sc->intr_count % 6000 == 0) {
1547			DLOG(DIGIDB_IRQ, (sc->dev,
1548			    "6000 useless polls %x %x\n", ehead, etail));
1549			sc->intr_count = 0;
1550		}
1551#endif
1552		goto eoi;
1553	}
1554	while (ehead != etail) {
1555		event = *(volatile struct event *)(sc->memevent + etail);
1556
1557		etail = (etail + 4) & sc->gdata->imax;
1558
1559		if (event.pnum >= sc->numports) {
1560			log(LOG_ERR, "digi%d: port %d: got event"
1561			    " on nonexisting port\n", sc->res.unit,
1562			    event.pnum);
1563			continue;
1564		}
1565		port = &sc->ports[event.pnum];
1566		bc = port->bc;
1567		tp = port->tp;
1568
1569		if (!(tp->t_state & TS_ISOPEN) && !port->wopeners) {
1570			DLOG(DIGIDB_IRQ, (sc->dev,
1571			    "port %d: event 0x%x on closed port\n",
1572			    event.pnum, event.event));
1573			bc->rout = bc->rin;
1574			bc->idata = 0;
1575			bc->iempty = 0;
1576			bc->ilow = 0;
1577			bc->mint = 0;
1578			continue;
1579		}
1580		if (event.event & ~ALL_IND)
1581			log(LOG_ERR, "digi%d: port%d: ? event 0x%x mstat 0x%x"
1582			    " lstat 0x%x\n", sc->res.unit, event.pnum,
1583			    event.event, event.mstat, event.lstat);
1584
1585		if (event.event & DATA_IND) {
1586			DLOG(DIGIDB_IRQ, (sc->dev, "port %d: DATA_IND\n",
1587			    event.pnum));
1588			wrapmask = port->rxbufsize - 1;
1589			head = bc->rin;
1590			tail = bc->rout;
1591
1592			size = 0;
1593			if (!(tp->t_state & TS_ISOPEN)) {
1594				bc->rout = head;
1595				goto end_of_data;
1596			}
1597			while (head != tail) {
1598				int top;
1599
1600				DLOG(DIGIDB_INT, (sc->dev,
1601				    "port %d: p rx head = %d tail = %d\n",
1602				    event.pnum, head, tail));
1603				top = (head > tail) ? head : wrapmask + 1;
1604				sc->towin(sc, port->rxwin);
1605				size = top - tail;
1606				if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1607					size = b_to_q((char *)port->rxbuf +
1608					    tail, size, &tp->t_rawq);
1609					tail = top - size;
1610					ttwakeup(tp);
1611				} else for (; tail < top;) {
1612					linesw[tp->t_line].
1613					    l_rint(port->rxbuf[tail], tp);
1614					sc->towin(sc, port->rxwin);
1615					size--;
1616					tail++;
1617					if (tp->t_state & TS_TBLOCK)
1618						break;
1619				}
1620				tail &= wrapmask;
1621				sc->setwin(sc, 0);
1622				bc->rout = tail;
1623				head = bc->rin;
1624				if (size)
1625					break;
1626			}
1627
1628			if (bc->orun) {
1629				CE_RECORD(port, CE_OVERRUN);
1630				log(LOG_ERR, "digi%d: port%d: %s\n",
1631				    sc->res.unit, event.pnum,
1632				    digi_errortxt(CE_OVERRUN));
1633				bc->orun = 0;
1634			}
1635end_of_data:
1636			if (size) {
1637				tp->t_state |= TS_TBLOCK;
1638				port->status |= PAUSE_RX;
1639				DLOG(DIGIDB_RX, (sc->dev, "port %d: pause RX\n",
1640				    event.pnum));
1641			} else {
1642				bc->idata = 1;
1643			}
1644		}
1645
1646		if (event.event & MODEMCHG_IND) {
1647			DLOG(DIGIDB_MODEM, (sc->dev, "port %d: MODEMCHG_IND\n",
1648			    event.pnum));
1649
1650			if ((event.mstat ^ event.lstat) & port->cd) {
1651				sc->hidewin(sc);
1652				linesw[tp->t_line].l_modem
1653				    (tp, event.mstat & port->cd);
1654				sc->setwin(sc, 0);
1655				wakeup(TSA_CARR_ON(tp));
1656			}
1657
1658			if (event.mstat & sc->csigs->ri) {
1659				DLOG(DIGIDB_RI, (sc->dev, "port %d: RING\n",
1660				    event.pnum));
1661				if (port->send_ring) {
1662					linesw[tp->t_line].l_rint('R', tp);
1663					linesw[tp->t_line].l_rint('I', tp);
1664					linesw[tp->t_line].l_rint('N', tp);
1665					linesw[tp->t_line].l_rint('G', tp);
1666					linesw[tp->t_line].l_rint('\r', tp);
1667					linesw[tp->t_line].l_rint('\n', tp);
1668				}
1669			}
1670		}
1671		if (event.event & BREAK_IND) {
1672			DLOG(DIGIDB_MODEM, (sc->dev, "port %d: BREAK_IND\n",
1673			    event.pnum));
1674			linesw[tp->t_line].l_rint(TTY_BI, tp);
1675		}
1676		if (event.event & (LOWTX_IND | EMPTYTX_IND)) {
1677			DLOG(DIGIDB_IRQ, (sc->dev, "port %d:%s%s\n",
1678			    event.pnum,
1679			    event.event & LOWTX_IND ? " LOWTX" : "",
1680			    event.event & EMPTYTX_IND ?  " EMPTYTX" : ""));
1681			(*linesw[tp->t_line].l_start)(tp);
1682		}
1683	}
1684	sc->gdata->eout = etail;
1685eoi:
1686	if (sc->window != 0)
1687		sc->towin(sc, 0);
1688	if (window != 0)
1689		sc->towin(sc, window);
1690}
1691
1692static void
1693digistart(struct tty *tp)
1694{
1695	int unit;
1696	int pnum;
1697	struct digi_p *port;
1698	struct digi_softc *sc;
1699	volatile struct board_chan *bc;
1700	int head, tail;
1701	int size, ocount, totcnt = 0;
1702	int s;
1703	int wmask;
1704
1705	unit = MINOR_TO_UNIT(minor(tp->t_dev));
1706	pnum = MINOR_TO_PORT(minor(tp->t_dev));
1707
1708	sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
1709	KASSERT(sc, ("digi%d: softc not allocated in digistart\n", unit));
1710
1711	port = &sc->ports[pnum];
1712	bc = port->bc;
1713
1714	wmask = port->txbufsize - 1;
1715
1716	s = spltty();
1717	port->lcc = tp->t_outq.c_cc;
1718	sc->setwin(sc, 0);
1719	if (!(tp->t_state & TS_TBLOCK)) {
1720		if (port->status & PAUSE_RX) {
1721			DLOG(DIGIDB_RX, (sc->dev, "port %d: resume RX\n",
1722			    pnum));
1723			/*
1724			 * CAREFUL - braces are needed here if the DLOG is
1725			 * optimised out!
1726			 */
1727		}
1728		port->status &= ~PAUSE_RX;
1729		bc->idata = 1;
1730	}
1731	if (!(tp->t_state & TS_TTSTOP) && port->status & PAUSE_TX) {
1732		DLOG(DIGIDB_TX, (sc->dev, "port %d: resume TX\n", pnum));
1733		port->status &= ~PAUSE_TX;
1734		fepcmd_w(port, RESUMETX, 0, 10);
1735	}
1736	if (tp->t_outq.c_cc == 0)
1737		tp->t_state &= ~TS_BUSY;
1738	else
1739		tp->t_state |= TS_BUSY;
1740
1741	head = bc->tin;
1742	while (tp->t_outq.c_cc != 0) {
1743		tail = bc->tout;
1744		DLOG(DIGIDB_INT, (sc->dev, "port%d: s tx head = %d tail = %d\n",
1745		    pnum, head, tail));
1746
1747		if (head < tail)
1748			size = tail - head - 1;
1749		else {
1750			size = port->txbufsize - head;
1751			if (tail == 0)
1752				size--;
1753		}
1754
1755		if (size == 0)
1756			break;
1757		sc->towin(sc, port->txwin);
1758		ocount = q_to_b(&tp->t_outq, port->txbuf + head, size);
1759		totcnt += ocount;
1760		head += ocount;
1761		head &= wmask;
1762		sc->setwin(sc, 0);
1763		bc->tin = head;
1764		bc->iempty = 1;
1765		bc->ilow = 1;
1766	}
1767	port->lostcc = tp->t_outq.c_cc;
1768	tail = bc->tout;
1769	if (head < tail)
1770		size = port->txbufsize - tail + head;
1771	else
1772		size = head - tail;
1773
1774	port->lbuf = size;
1775	DLOG(DIGIDB_INT, (sc->dev, "port%d: s total cnt = %d\n", pnum, totcnt));
1776	ttwwakeup(tp);
1777	splx(s);
1778}
1779
1780static void
1781digistop(struct tty *tp, int rw)
1782{
1783	struct digi_softc *sc;
1784	int unit;
1785	int pnum;
1786	struct digi_p *port;
1787
1788	unit = MINOR_TO_UNIT(minor(tp->t_dev));
1789	pnum = MINOR_TO_PORT(minor(tp->t_dev));
1790
1791	sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
1792	KASSERT(sc, ("digi%d: softc not allocated in digistop\n", unit));
1793	port = sc->ports + pnum;
1794
1795	DLOG(DIGIDB_TX, (sc->dev, "port %d: pause TX\n", pnum));
1796	port->status |= PAUSE_TX;
1797	fepcmd_w(port, PAUSETX, 0, 10);
1798}
1799
1800static void
1801fepcmd(struct digi_p *port, int cmd, int op1, int ncmds)
1802{
1803	u_char *mem;
1804	unsigned tail, head;
1805	int count, n;
1806
1807	mem = port->sc->memcmd;
1808
1809	port->sc->setwin(port->sc, 0);
1810
1811	head = port->sc->gdata->cin;
1812	mem[head + 0] = cmd;
1813	mem[head + 1] = port->pnum;
1814	*(u_short *)(mem + head + 2) = op1;
1815
1816	head = (head + 4) & port->sc->gdata->cmax;
1817	port->sc->gdata->cin = head;
1818
1819	for (count = FEPTIMEOUT; count > 0; count--) {
1820		head = port->sc->gdata->cin;
1821		tail = port->sc->gdata->cout;
1822		n = (head - tail) & port->sc->gdata->cmax;
1823
1824		if (n <= ncmds * sizeof(short) * 4)
1825			break;
1826	}
1827	if (count == 0)
1828		log(LOG_ERR, "digi%d: port%d: timeout on FEP command\n",
1829		    port->sc->res.unit, port->pnum);
1830}
1831
1832const char *
1833digi_errortxt(int id)
1834{
1835	static const char *error_desc[] = {
1836		"silo overflow",
1837		"interrupt-level buffer overflow",
1838		"tty-level buffer overflow",
1839	};
1840
1841	KASSERT(id >= 0 && id < sizeof(error_desc) / sizeof(error_desc[0]),
1842	    ("Unexpected digi error id %d\n", id));
1843
1844	return (error_desc[id]);
1845}
1846
1847int
1848digi_attach(struct digi_softc *sc)
1849{
1850	sc->res.ctldev = make_dev(&digi_sw,
1851	    (sc->res.unit << 16) | CTRL_DEV, UID_ROOT, GID_WHEEL,
1852	    0600, "digi%r.ctl", sc->res.unit);
1853
1854	digi_loadmoduledata(sc);
1855	digi_init(sc);
1856	digi_freemoduledata(sc);
1857
1858	return (0);
1859}
1860
1861static int
1862digi_inuse(struct digi_softc *sc)
1863{
1864	int i;
1865
1866	for (i = 0; i < sc->numports; i++)
1867		if (sc->ttys[i].t_state & TS_ISOPEN) {
1868			DLOG(DIGIDB_INIT, (sc->dev, "port%d: busy\n", i));
1869			return (1);
1870		} else if (sc->ports[i].wopeners || sc->ports[i].opencnt) {
1871			DLOG(DIGIDB_INIT, (sc->dev, "port%d: blocked in open\n",
1872			    i));
1873			return (1);
1874		}
1875	return (0);
1876}
1877
1878static void
1879digi_free_state(struct digi_softc *sc)
1880{
1881	int d, i;
1882
1883	/* Blow it all away */
1884
1885	for (i = 0; i < sc->numports; i++)
1886		for (d = 0; d < 6; d++)
1887			destroy_dev(sc->ports[i].dev[d]);
1888
1889	untimeout(digi_poll, sc, sc->callout);
1890	callout_handle_init(&sc->callout);
1891	untimeout(digi_int_test, sc, sc->inttest);
1892	callout_handle_init(&sc->inttest);
1893
1894	bus_teardown_intr(sc->dev, sc->res.irq, sc->res.irqHandler);
1895#ifdef DIGI_INTERRUPT
1896	if (sc->res.irq != NULL) {
1897		bus_release_resource(dev, SYS_RES_IRQ, sc->res.irqrid,
1898		    sc->res.irq);
1899		sc->res.irq = NULL;
1900	}
1901#endif
1902	if (sc->numports) {
1903		KASSERT(sc->ports, ("digi%d: Lost my ports ?", sc->res.unit));
1904		KASSERT(sc->ttys, ("digi%d: Lost my ttys ?", sc->res.unit));
1905		free(sc->ports, M_TTYS);
1906		sc->ports = NULL;
1907		free(sc->ttys, M_TTYS);
1908		sc->ttys = NULL;
1909		sc->numports = 0;
1910	}
1911
1912	sc->status = DIGI_STATUS_NOTINIT;
1913}
1914
1915int
1916digi_detach(device_t dev)
1917{
1918	struct digi_softc *sc = device_get_softc(dev);
1919
1920	DLOG(DIGIDB_INIT, (sc->dev, "detaching\n"));
1921
1922	/* If we're INIT'd, numports must be 0 */
1923	KASSERT(sc->numports == 0 || sc->status != DIGI_STATUS_NOTINIT,
1924	    ("digi%d: numports(%d) & status(%d) are out of sync",
1925	    sc->res.unit, sc->numports, (int)sc->status));
1926
1927	if (digi_inuse(sc))
1928		return (EBUSY);
1929
1930	digi_free_state(sc);
1931
1932	destroy_dev(sc->res.ctldev);
1933
1934	if (sc->res.mem != NULL) {
1935		bus_release_resource(dev, SYS_RES_MEMORY, sc->res.mrid,
1936		    sc->res.mem);
1937		sc->res.mem = NULL;
1938	}
1939	if (sc->res.io != NULL) {
1940		bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
1941		    sc->res.io);
1942		sc->res.io = NULL;
1943	}
1944
1945	return (0);
1946}
1947
1948int
1949digi_shutdown(device_t dev)
1950{
1951	return (0);
1952}
1953
1954MODULE_VERSION(digi, 1);
1955