2 * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Slawa Olhovchenkov
4 * John Prince <johnp@knight-trosoft.com>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
29 * $FreeBSD: src/sys/dev/digi/digi.c,v 1.36 2003/09/26 09:05:57 phk Exp $
30 * $DragonFly: src/sys/dev/serial/digi/digi.c,v 1.11 2008/04/30 17:28:17 dillon Exp $
35 * Figure out what the con bios stuff is supposed to do
36 * Test with *LOTS* more cards - I only have a PCI8r and an ISA Xem.
39 #include "opt_compat.h"
41 #include <sys/param.h>
42 #include <sys/systm.h>
46 #include <sys/linker.h>
47 #include <sys/kernel.h>
49 #include <sys/malloc.h>
51 #include <sys/syslog.h>
52 #include <sys/fcntl.h>
55 #include <sys/thread2.h>
60 #include <dev/serial/digi/digiio.h>
61 #include <dev/serial/digi/digireg.h>
62 #include <dev/serial/digi/digi.h>
63 #include <dev/serial/digi/digi_pci.h>
64 #include <dev/serial/digi/digi_bios.h>
66 #define CDEV_MAJOR 162
68 #define CTRL_DEV 0x800000
69 #define CALLOUT_MASK 0x400000
70 #define CONTROL_INIT_STATE 0x100000
71 #define CONTROL_LOCK_STATE 0x200000
72 #define CONTROL_MASK (CTRL_DEV|CONTROL_INIT_STATE|CONTROL_LOCK_STATE)
73 #define UNIT_MASK 0x030000
74 #define PORT_MASK 0x0000FF
75 #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
76 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
77 #define MINOR_TO_UNIT(mynor) (((mynor) & UNIT_MASK)>>16)
78 #define MINOR_TO_PORT(mynor) ((mynor) & PORT_MASK)
80 static d_open_t digiopen
;
81 static d_close_t digiclose
;
82 static d_read_t digiread
;
83 static d_write_t digiwrite
;
84 static d_ioctl_t digiioctl
;
86 static void digistop(struct tty
*tp
, int rw
);
87 static int digimctl(struct digi_p
*port
, int bits
, int how
);
88 static void digi_poll(void *ptr
);
89 static void digi_freedata(struct digi_softc
*);
90 static void fepcmd(struct digi_p
*port
, int cmd
, int op
, int ncmds
);
91 static void digistart(struct tty
*tp
);
92 static int digiparam(struct tty
*tp
, struct termios
*t
);
93 static void digihardclose(struct digi_p
*port
);
94 static void digi_intr(void *);
95 static int digi_init(struct digi_softc
*_sc
);
96 static int digi_loaddata(struct digi_softc
*);
97 static int digi_inuse(struct digi_softc
*);
98 static void digi_free_state(struct digi_softc
*);
100 #define fepcmd_b(port, cmd, op1, op2, ncmds) \
101 fepcmd(port, cmd, (op2 << 8) | op1, ncmds)
102 #define fepcmd_w fepcmd
105 static speed_t digidefaultrate
= TTYDEF_SPEED
;
108 struct con_bios
*next
;
113 static struct con_bios
*con_bios_list
;
114 devclass_t digi_devclass
;
115 unsigned digi_debug
= 0;
117 static struct speedtab digispeedtab
[] = {
118 { 0, 0}, /* old (sysV-like) Bx codes */
134 { 57600, (02000 | 1)},
135 { 76800, (02000 | 2)},
136 { 115200, (02000 | 3)},
137 { 230400, (02000 | 6)},
141 const struct digi_control_signals digi_xixe_signals
= {
142 0x02, 0x08, 0x10, 0x20, 0x40, 0x80
145 const struct digi_control_signals digi_normal_signals
= {
146 0x02, 0x80, 0x20, 0x10, 0x40, 0x01
149 static struct dev_ops digi_ops
= {
150 { "dgm", CDEV_MAJOR
, D_TTY
},
152 .d_close
= digiclose
,
154 .d_write
= digiwrite
,
155 .d_ioctl
= digiioctl
,
157 .d_kqfilter
= ttykqfilter
163 struct digi_softc
*sc
;
165 sc
= (struct digi_softc
*)ptr
;
166 callout_init(&sc
->callout
);
168 callout_reset(&sc
->callout
, (hz
>= 200) ? hz
/ 100 : 1, digi_poll
, sc
);
172 digi_int_test(void *v
)
174 struct digi_softc
*sc
= v
;
176 callout_init(&sc
->inttest
);
177 #ifdef DIGI_INTERRUPT
178 if (sc
->intr_timestamp
.tv_sec
|| sc
->intr_timestamp
.tv_usec
) {
182 log(LOG_ERR
, "digi%d: Interrupt didn't work, use polled mode\n", unit
);
184 callout_reset(&sc
->callout
, (hz
>= 200) ? hz
/ 100 : 1, digi_poll
, sc
);
188 digi_freedata(struct digi_softc
*sc
)
190 if (sc
->fep
.data
!= NULL
) {
191 kfree(sc
->fep
.data
, M_TTYS
);
194 if (sc
->link
.data
!= NULL
) {
195 kfree(sc
->link
.data
, M_TTYS
);
196 sc
->link
.data
= NULL
;
198 if (sc
->bios
.data
!= NULL
) {
199 kfree(sc
->bios
.data
, M_TTYS
);
200 sc
->bios
.data
= NULL
;
205 digi_bcopy(const void *vfrom
, void *vto
, size_t sz
)
207 volatile const char *from
= (volatile const char *)vfrom
;
208 volatile char *to
= (volatile char *)vto
;
211 for (i
= 0; i
< sz
; i
++)
214 from
= (const volatile char *)vfrom
;
215 to
= (volatile char *)vto
;
216 for (i
= 0; i
< sz
; i
++)
217 if (*to
++ != *from
++)
223 digi_delay(struct digi_softc
*sc
, const char *txt
, u_long timo
)
226 DELAY(timo
* 1000000 / hz
);
228 tsleep(sc
, PCATCH
, txt
, timo
);
232 digi_init(struct digi_softc
*sc
)
238 volatile struct board_chan
*bc
;
242 if (sc
->status
== DIGI_STATUS_DISABLED
) {
243 log(LOG_ERR
, "digi%d: Cannot init a disabled card\n",
247 if (sc
->bios
.data
== NULL
) {
248 log(LOG_ERR
, "digi%d: Cannot init without BIOS\n",
253 if (sc
->link
.data
== NULL
&& sc
->model
>= PCCX
) {
254 log(LOG_ERR
, "digi%d: Cannot init without link info\n",
259 if (sc
->fep
.data
== NULL
) {
260 log(LOG_ERR
, "digi%d: Cannot init without fep code\n",
264 sc
->status
= DIGI_STATUS_NOTINIT
;
268 * We're re-initialising - maybe because someone's attached
269 * another port module. For now, we just re-initialise
278 ptr
= sc
->setwin(sc
, MISCGLOBAL
);
279 for (i
= 0; i
< 16; i
+= 2)
284 outb(sc
->wport
, 0xff); /* window 7 */
285 ptr
= sc
->vmem
+ (BIOSCODE
& 0x1fff);
287 if (!digi_bcopy(sc
->bios
.data
, ptr
, sc
->bios
.size
)) {
288 device_printf(sc
->dev
, "BIOS upload failed\n");
292 outb(sc
->port
, FEPCLR
);
298 ptr
= sc
->setwin(sc
, BIOSCODE
+ ((0xf000 - sc
->mem_seg
) << 4));
299 if (!digi_bcopy(sc
->bios
.data
, ptr
, sc
->bios
.size
)) {
300 device_printf(sc
->dev
, "BIOS upload failed\n");
311 outb(sc
->port
, FEPRST
| FEPMEM
);
313 for (i
= 0; ((sc
->pcibus
? PCIPORT
: inb(sc
->port
)) &
314 FEPMASK
) != FEPRST
; i
++) {
316 log(LOG_ERR
, "digi%d: %s init reset failed\n",
317 sc
->res
.unit
, sc
->name
);
320 digi_delay(sc
, "digiinit0", 5);
322 DLOG(DIGIDB_INIT
, (sc
->dev
, "Got init reset after %d us\n", i
));
324 /* Now upload the BIOS */
325 cnt
= (sc
->bios
.size
< sc
->win_size
- BIOSOFFSET
) ?
326 sc
->bios
.size
: sc
->win_size
- BIOSOFFSET
;
328 ptr
= sc
->setwin(sc
, BIOSOFFSET
);
329 if (!digi_bcopy(sc
->bios
.data
, ptr
, cnt
)) {
330 device_printf(sc
->dev
, "BIOS upload (1) failed\n");
334 if (cnt
!= sc
->bios
.size
) {
335 /* and the second part */
336 ptr
= sc
->setwin(sc
, sc
->win_size
);
337 if (!digi_bcopy(sc
->bios
.data
+ cnt
, ptr
,
338 sc
->bios
.size
- cnt
)) {
339 device_printf(sc
->dev
, "BIOS upload failed\n");
344 ptr
= sc
->setwin(sc
, 0);
345 vW(ptr
+ 0) = 0x0401;
346 vW(ptr
+ 2) = 0x0bf0;
347 vW(ptr
+ 4) = 0x0000;
348 vW(ptr
+ 6) = 0x0000;
353 DLOG(DIGIDB_INIT
, (sc
->dev
, "BIOS uploaded\n"));
355 ptr
= sc
->setwin(sc
, MISCGLOBAL
);
361 } else if (sc
->model
== PCXEVE
) {
362 outb(sc
->port
, FEPCLR
);
365 outb(sc
->port
, FEPCLR
| FEPMEM
);
366 resp
= FEPRST
| FEPMEM
;
369 for (i
= 0; ((sc
->pcibus
? PCIPORT
: inb(sc
->port
)) & FEPMASK
)
372 log(LOG_ERR
, "digi%d: BIOS start failed\n",
376 digi_delay(sc
, "digibios0", 5);
379 DLOG(DIGIDB_INIT
, (sc
->dev
, "BIOS started after %d us\n", i
));
381 for (i
= 0; vW(ptr
) != *(u_short
*)"GD"; i
++) {
383 log(LOG_ERR
, "digi%d: BIOS boot failed "
384 "(0x%02x != 0x%02x)\n",
385 sc
->res
.unit
, vW(ptr
), *(u_short
*)"GD");
388 digi_delay(sc
, "digibios1", 5);
391 DLOG(DIGIDB_INIT
, (sc
->dev
, "BIOS booted after %d iterations\n", i
));
393 if (sc
->link
.data
!= NULL
) {
394 DLOG(DIGIDB_INIT
, (sc
->dev
, "Loading link data\n"));
395 ptr
= sc
->setwin(sc
, 0xcd0);
396 digi_bcopy(sc
->link
.data
, ptr
, 21); /* XXX 21 ? */
405 ptr
= sc
->setwin(sc
, sc
->model
== PCXI
? 0x2000 : 0x0);
406 digi_bcopy(sc
->fep
.data
, ptr
, sc
->fep
.size
);
408 /* A BIOS request to move our data to 0x2000 */
409 ptr
= sc
->setwin(sc
, MBOX
);
411 vW(ptr
+ 2) = sc
->mem_seg
+ FEPCODESEG
;
413 vW(ptr
+ 6) = FEPCODESEG
;
415 vW(ptr
+ 10) = sc
->fep
.size
;
417 /* Run the BIOS request */
418 outb(sc
->port
, FEPREQ
| FEPMEM
);
419 outb(sc
->port
, FEPCLR
| FEPMEM
);
421 for (i
= 0; W(ptr
); i
++) {
423 log(LOG_ERR
, "digi%d: FEP/OS move failed\n",
428 digi_delay(sc
, "digifep0", 5);
431 (sc
->dev
, "FEP/OS moved after %d iterations\n", i
));
433 /* Clear the confirm word */
434 ptr
= sc
->setwin(sc
, FEPSTAT
);
437 /* A BIOS request to execute the FEP/OS */
438 ptr
= sc
->setwin(sc
, MBOX
);
440 vW(ptr
+ 2) = FEPCODESEG
;
443 /* Run the BIOS request */
444 outb(sc
->port
, FEPREQ
);
445 outb(sc
->port
, FEPCLR
);
447 ptr
= sc
->setwin(sc
, FEPSTAT
);
454 DLOG(DIGIDB_INIT
, (sc
->dev
, "Loading FEP/OS\n"));
456 cnt
= (sc
->fep
.size
< sc
->win_size
- BIOSOFFSET
) ?
457 sc
->fep
.size
: sc
->win_size
- BIOSOFFSET
;
459 ptr
= sc
->setwin(sc
, BIOSOFFSET
);
460 digi_bcopy(sc
->fep
.data
, ptr
, cnt
);
462 if (cnt
!= sc
->fep
.size
) {
463 ptr
= sc
->setwin(sc
, BIOSOFFSET
+ cnt
);
464 digi_bcopy(sc
->fep
.data
+ cnt
, ptr
,
468 DLOG(DIGIDB_INIT
, (sc
->dev
, "FEP/OS loaded\n"));
470 ptr
= sc
->setwin(sc
, 0xc30);
476 /* Clear the confirm word */
477 ptr
= sc
->setwin(sc
, FEPSTAT
);
481 outb(sc
->port
, 0); /* XXX necessary ? */
486 ptr
= sc
->setwin(sc
, 0xd000);
487 digi_bcopy(sc
->fep
.data
, ptr
, sc
->fep
.size
);
489 /* A BIOS request to execute the FEP/OS */
490 ptr
= sc
->setwin(sc
, 0xc40);
492 W(ptr
+ 2) = FEPCODE
>> 4;
495 /* Clear the confirm word */
496 ptr
= sc
->setwin(sc
, FEPSTAT
);
499 /* Run the BIOS request */
500 outb(sc
->port
, FEPREQ
| FEPMEM
); /* send interrupt to BIOS */
501 outb(sc
->port
, FEPCLR
| FEPMEM
);
505 /* Now wait 'till the FEP/OS has booted */
506 for (i
= 0; vW(ptr
) != *(u_short
*)"OS"; i
++) {
508 log(LOG_ERR
, "digi%d: FEP/OS start failed "
509 "(0x%02x != 0x%02x)\n",
510 sc
->res
.unit
, vW(ptr
), *(u_short
*)"OS");
514 digi_delay(sc
, "digifep1", 5);
517 DLOG(DIGIDB_INIT
, (sc
->dev
, "FEP/OS started after %d iterations\n", i
));
519 if (sc
->model
>= PCXEM
) {
520 ptr
= sc
->setwin(sc
, 0xe04);
522 ptr
= sc
->setwin(sc
, 0xc02);
523 sc
->numports
= vW(ptr
);
525 ptr
= sc
->setwin(sc
, 0xc22);
526 sc
->numports
= vW(ptr
);
529 if (sc
->numports
== 0) {
530 device_printf(sc
->dev
, "%s, 0 ports found\n", sc
->name
);
535 if (sc
->numports
> 256) {
536 /* Our minor numbering scheme is broken for more than 256 */
537 device_printf(sc
->dev
, "%s, 256 ports (%d ports found)\n",
538 sc
->name
, sc
->numports
);
541 device_printf(sc
->dev
, "%s, %d ports found\n", sc
->name
,
545 kfree(sc
->ports
, M_TTYS
);
546 sc
->ports
= kmalloc(sizeof(struct digi_p
) * sc
->numports
,
547 M_TTYS
, M_WAITOK
| M_ZERO
);
550 kfree(sc
->ttys
, M_TTYS
);
551 sc
->ttys
= kmalloc(sizeof(struct tty
) * sc
->numports
,
552 M_TTYS
, M_WAITOK
| M_ZERO
);
555 * XXX Should read port 0xc90 for an array of 2byte values, 1 per
556 * port. If the value is 0, the port is broken....
559 ptr
= sc
->setwin(sc
, 0);
561 /* We should now init per-port structures */
562 bc
= (volatile struct board_chan
*)(ptr
+ CHANSTRUCT
);
563 sc
->gdata
= (volatile struct global_data
*)(ptr
+ FEP_GLOBAL
);
565 sc
->memcmd
= ptr
+ sc
->gdata
->cstart
;
566 sc
->memevent
= ptr
+ sc
->gdata
->istart
;
568 for (i
= 0; i
< sc
->numports
; i
++, bc
++) {
569 port
= sc
->ports
+ i
;
572 port
->status
= ENABLED
;
573 port
->tp
= sc
->ttys
+ i
;
576 if (sc
->model
== PCXEVE
) {
578 (((bc
->tseg
- sc
->mem_seg
) << 4) & 0x1fff);
580 (((bc
->rseg
- sc
->mem_seg
) << 4) & 0x1fff);
581 port
->txwin
= FEPWIN
| ((bc
->tseg
- sc
->mem_seg
) >> 9);
582 port
->rxwin
= FEPWIN
| ((bc
->rseg
- sc
->mem_seg
) >> 9);
583 } else if (sc
->model
== PCXI
|| sc
->model
== PCXE
) {
584 port
->txbuf
= ptr
+ ((bc
->tseg
- sc
->mem_seg
) << 4);
585 port
->rxbuf
= ptr
+ ((bc
->rseg
- sc
->mem_seg
) << 4);
586 port
->txwin
= port
->rxwin
= 0;
589 (((bc
->tseg
- sc
->mem_seg
) << 4) % sc
->win_size
);
591 (((bc
->rseg
- sc
->mem_seg
) << 4) % sc
->win_size
);
592 port
->txwin
= FEPWIN
|
593 (((bc
->tseg
- sc
->mem_seg
) << 4) / sc
->win_size
);
594 port
->rxwin
= FEPWIN
|
595 (((bc
->rseg
- sc
->mem_seg
) << 4) / sc
->win_size
);
597 port
->txbufsize
= bc
->tmax
+ 1;
598 port
->rxbufsize
= bc
->rmax
+ 1;
600 lowwater
= port
->txbufsize
>> 2;
604 fepcmd_w(port
, STXLWATER
, lowwater
, 10);
605 fepcmd_w(port
, SRXLWATER
, port
->rxbufsize
>> 2, 10);
606 fepcmd_w(port
, SRXHWATER
, (3 * port
->rxbufsize
) >> 2, 10);
609 port
->dtr_wait
= 3 * hz
;
612 * We don't use all the flags from <sys/ttydefaults.h> since
613 * they are only relevant for logins. It's important to have
614 * echo off initially so that the line doesn't start blathering
615 * before the echo flag can be turned off.
617 port
->it_in
.c_iflag
= 0;
618 port
->it_in
.c_oflag
= 0;
619 port
->it_in
.c_cflag
= TTYDEF_CFLAG
;
620 port
->it_in
.c_lflag
= 0;
621 termioschars(&port
->it_in
);
622 port
->it_in
.c_ispeed
= port
->it_in
.c_ospeed
= digidefaultrate
;
623 port
->it_out
= port
->it_in
;
624 port
->send_ring
= 1; /* Default action on signal RI */
626 port
->dev
[0] = make_dev(&digi_ops
, (sc
->res
.unit
<< 16) + i
,
627 UID_ROOT
, GID_WHEEL
, 0600, "ttyD%d.%d", sc
->res
.unit
, i
);
628 port
->dev
[1] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
629 CONTROL_INIT_STATE
, UID_ROOT
, GID_WHEEL
,
630 0600, "ttyiD%d.%d", sc
->res
.unit
, i
);
631 port
->dev
[2] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
632 CONTROL_LOCK_STATE
, UID_ROOT
, GID_WHEEL
,
633 0600, "ttylD%d.%d", sc
->res
.unit
, i
);
634 port
->dev
[3] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
635 CALLOUT_MASK
, UID_UUCP
, GID_DIALER
,
636 0660, "cuaD%d.%d", sc
->res
.unit
, i
);
637 port
->dev
[4] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
638 CALLOUT_MASK
| CONTROL_INIT_STATE
, UID_UUCP
, GID_DIALER
,
639 0660, "cuaiD%d.%d", sc
->res
.unit
, i
);
640 port
->dev
[5] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
641 CALLOUT_MASK
| CONTROL_LOCK_STATE
, UID_UUCP
, GID_DIALER
,
642 0660, "cualD%d.%d", sc
->res
.unit
, i
);
646 callout_reset(&sc
->inttest
, hz
, digi_int_test
, sc
);
647 /* fepcmd_w(&sc->ports[0], 0xff, 0, 0); */
648 sc
->status
= DIGI_STATUS_ENABLED
;
654 digimctl(struct digi_p
*port
, int bits
, int how
)
659 port
->sc
->setwin(port
->sc
, 0);
660 mstat
= port
->bc
->mstat
;
661 port
->sc
->hidewin(port
->sc
);
663 if (mstat
& port
->sc
->csigs
->rts
)
665 if (mstat
& port
->cd
)
667 if (mstat
& port
->dsr
)
669 if (mstat
& port
->sc
->csigs
->cts
)
671 if (mstat
& port
->sc
->csigs
->ri
)
673 if (mstat
& port
->sc
->csigs
->dtr
)
678 /* Only DTR and RTS may be set */
680 if (bits
& TIOCM_DTR
)
681 mstat
|= port
->sc
->csigs
->dtr
;
682 if (bits
& TIOCM_RTS
)
683 mstat
|= port
->sc
->csigs
->rts
;
687 fepcmd_b(port
, SETMODEM
, mstat
, ~mstat
, 0);
690 fepcmd_b(port
, SETMODEM
, mstat
, 0, 0);
693 fepcmd_b(port
, SETMODEM
, 0, mstat
, 0);
701 digi_disc_optim(struct tty
*tp
, struct termios
*t
, struct digi_p
*port
)
703 if (!(t
->c_iflag
& (ICRNL
| IGNCR
| IMAXBEL
| INLCR
| ISTRIP
)) &&
704 (!(t
->c_iflag
& BRKINT
) || (t
->c_iflag
& IGNBRK
)) &&
705 (!(t
->c_iflag
& PARMRK
) ||
706 (t
->c_iflag
& (IGNPAR
| IGNBRK
)) == (IGNPAR
| IGNBRK
)) &&
707 !(t
->c_lflag
& (ECHO
| ICANON
| IEXTEN
| ISIG
| PENDIN
)) &&
708 linesw
[tp
->t_line
].l_rint
== ttyinput
)
709 tp
->t_state
|= TS_CAN_BYPASS_L_RINT
;
711 tp
->t_state
&= ~TS_CAN_BYPASS_L_RINT
;
715 digiopen(struct dev_open_args
*ap
)
717 cdev_t dev
= ap
->a_head
.a_dev
;
718 struct digi_softc
*sc
;
724 volatile struct board_chan
*bc
;
728 unit
= MINOR_TO_UNIT(minor(dev
));
729 pnum
= MINOR_TO_PORT(minor(dev
));
731 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
735 if (sc
->status
!= DIGI_STATUS_ENABLED
) {
736 DLOG(DIGIDB_OPEN
, (sc
->dev
, "Cannot open a disabled card\n"));
739 if (pnum
>= sc
->numports
) {
740 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port%d: Doesn't exist\n", pnum
));
743 if (mynor
& (CTRL_DEV
| CONTROL_MASK
)) {
747 port
= &sc
->ports
[pnum
];
748 tp
= dev
->si_tty
= port
->tp
;
754 while (port
->status
& DIGI_DTR_OFF
) {
756 error
= tsleep(&port
->dtr_wait
, PCATCH
, "digidtr", 0);
762 if (tp
->t_state
& TS_ISOPEN
) {
764 * The device is open, so everything has been initialized.
767 if (mynor
& CALLOUT_MASK
) {
768 if (!port
->active_out
) {
770 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port %d:"
771 " BUSY error = %d\n", pnum
, error
));
774 } else if (port
->active_out
) {
775 if (ap
->a_oflags
& O_NONBLOCK
) {
777 DLOG(DIGIDB_OPEN
, (sc
->dev
,
778 "port %d: BUSY error = %d\n", pnum
, error
));
782 error
= tsleep(&port
->active_out
, PCATCH
, "digibi", 0);
785 DLOG(DIGIDB_OPEN
, (sc
->dev
,
786 "port %d: tsleep(digibi) error = %d\n",
792 if (tp
->t_state
& TS_XCLUDE
&& priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0) != 0) {
798 * The device isn't open, so there are no conflicts.
799 * Initialize it. Initialization is done twice in many
800 * cases: to preempt sleeping callin opens if we are callout,
801 * and to complete a callin open after DCD rises.
803 callout_init(&port
->wakeupco
);
804 tp
->t_oproc
= digistart
;
805 tp
->t_param
= digiparam
;
806 tp
->t_stop
= digistop
;
808 tp
->t_termios
= (mynor
& CALLOUT_MASK
) ?
809 port
->it_out
: port
->it_in
;
812 bc
->rout
= bc
->rin
; /* clear input queue */
816 bc
->mint
= port
->cd
| port
->sc
->csigs
->ri
;
819 port
->cd
= sc
->csigs
->dsr
;
820 port
->dsr
= sc
->csigs
->cd
;
822 port
->cd
= sc
->csigs
->cd
;
823 port
->dsr
= sc
->csigs
->dsr
;
825 port
->wopeners
++; /* XXX required ? */
826 error
= digiparam(tp
, &tp
->t_termios
);
830 DLOG(DIGIDB_OPEN
, (sc
->dev
,
831 "port %d: cxpparam error = %d\n", pnum
, error
));
836 /* handle fake and initial DCD for callout devices */
838 if (bc
->mstat
& port
->cd
|| mynor
& CALLOUT_MASK
)
839 linesw
[tp
->t_line
].l_modem(tp
, 1);
842 /* Wait for DCD if necessary */
843 if (!(tp
->t_state
& TS_CARR_ON
) && !(mynor
& CALLOUT_MASK
) &&
844 !(tp
->t_cflag
& CLOCAL
) && !(ap
->a_oflags
& O_NONBLOCK
)) {
846 error
= tsleep(TSA_CARR_ON(tp
), PCATCH
, "digidcd", 0);
849 DLOG(DIGIDB_OPEN
, (sc
->dev
,
850 "port %d: tsleep(digidcd) error = %d\n",
856 error
= linesw
[tp
->t_line
].l_open(dev
, tp
);
857 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port %d: l_open error = %d\n",
860 digi_disc_optim(tp
, &tp
->t_termios
, port
);
862 if (tp
->t_state
& TS_ISOPEN
&& mynor
& CALLOUT_MASK
)
863 port
->active_out
= TRUE
;
865 if (tp
->t_state
& TS_ISOPEN
)
870 if (!(tp
->t_state
& TS_ISOPEN
))
873 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port %d: open() returns %d\n",
880 digiclose(struct dev_close_args
*ap
)
882 cdev_t dev
= ap
->a_head
.a_dev
;
886 struct digi_softc
*sc
;
890 unit
= MINOR_TO_UNIT(mynor
);
891 pnum
= MINOR_TO_PORT(mynor
);
893 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
894 KASSERT(sc
, ("digi%d: softc not allocated in digiclose\n", unit
));
896 if (mynor
& (CTRL_DEV
| CONTROL_MASK
)) {
901 port
= sc
->ports
+ pnum
;
904 DLOG(DIGIDB_CLOSE
, (sc
->dev
, "port %d: closing\n", pnum
));
907 linesw
[tp
->t_line
].l_close(tp
, ap
->a_fflag
);
908 digi_disc_optim(tp
, &tp
->t_termios
, port
);
909 digistop(tp
, FREAD
| FWRITE
);
918 digidtrwakeup(void *chan
)
920 struct digi_p
*port
= chan
;
922 port
->status
&= ~DIGI_DTR_OFF
;
923 wakeup(&port
->dtr_wait
);
928 digihardclose(struct digi_p
*port
)
930 volatile struct board_chan
*bc
;
935 port
->sc
->setwin(port
->sc
, 0);
940 if ((port
->tp
->t_cflag
& HUPCL
) ||
941 (!port
->active_out
&& !(bc
->mstat
& port
->cd
) &&
942 !(port
->it_in
.c_cflag
& CLOCAL
)) ||
943 !(port
->tp
->t_state
& TS_ISOPEN
)) {
944 digimctl(port
, TIOCM_DTR
| TIOCM_RTS
, DMBIC
);
945 if (port
->dtr_wait
!= 0) {
946 /* Schedule a wakeup of any callin devices */
948 callout_reset(&port
->wakeupco
, port
->dtr_wait
,
949 digidtrwakeup
, port
);
950 port
->status
|= DIGI_DTR_OFF
;
953 port
->active_out
= FALSE
;
954 wakeup(&port
->active_out
);
955 wakeup(TSA_CARR_ON(port
->tp
));
960 digiread(struct dev_read_args
*ap
)
962 cdev_t dev
= ap
->a_head
.a_dev
;
965 int error
, unit
, pnum
;
966 struct digi_softc
*sc
;
969 if (mynor
& CONTROL_MASK
)
972 unit
= MINOR_TO_UNIT(mynor
);
973 pnum
= MINOR_TO_PORT(mynor
);
975 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
976 KASSERT(sc
, ("digi%d: softc not allocated in digiclose\n", unit
));
977 tp
= &sc
->ttys
[pnum
];
979 error
= linesw
[tp
->t_line
].l_read(tp
, ap
->a_uio
, ap
->a_ioflag
);
980 DLOG(DIGIDB_READ
, (sc
->dev
, "port %d: read() returns %d\n",
987 digiwrite(struct dev_write_args
*ap
)
989 cdev_t dev
= ap
->a_head
.a_dev
;
992 int error
, unit
, pnum
;
993 struct digi_softc
*sc
;
996 if (mynor
& CONTROL_MASK
)
999 unit
= MINOR_TO_UNIT(mynor
);
1000 pnum
= MINOR_TO_PORT(mynor
);
1002 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1003 KASSERT(sc
, ("digi%d: softc not allocated in digiclose\n", unit
));
1004 tp
= &sc
->ttys
[pnum
];
1006 error
= linesw
[tp
->t_line
].l_write(tp
, ap
->a_uio
, ap
->a_ioflag
);
1007 DLOG(DIGIDB_WRITE
, (sc
->dev
, "port %d: write() returns %d\n",
1014 * Load module "digi_<mod>.ko" and look for a symbol called digi_mod_<mod>.
1016 * Populate sc->bios, sc->fep, and sc->link from this data.
1018 * sc->fep.data, sc->bios.data and sc->link.data are malloc()d according
1019 * to their respective sizes.
1021 * The module is unloaded when we're done.
1024 digi_loaddata(struct digi_softc
*sc
)
1026 struct digi_bios
*bios
;
1028 KASSERT(sc
->bios
.data
== NULL
, ("Uninitialised BIOS variable"));
1029 KASSERT(sc
->fep
.data
== NULL
, ("Uninitialised FEP variable"));
1030 KASSERT(sc
->link
.data
== NULL
, ("Uninitialised LINK variable"));
1031 KASSERT(sc
->module
!= NULL
, ("Uninitialised module name"));
1033 for (bios
= digi_bioses
; bios
->model
!= NULL
; bios
++) {
1034 if (!strcmp(bios
->model
, sc
->module
))
1037 if (bios
->model
== NULL
) {
1038 kprintf("digi.ko: driver %s not found", sc
->module
);
1042 sc
->bios
.size
= bios
->bios_size
;
1043 if (sc
->bios
.size
!= 0 && bios
->bios
!= NULL
) {
1044 sc
->bios
.data
= kmalloc(sc
->bios
.size
, M_TTYS
, M_WAITOK
);
1045 bcopy(bios
->bios
, sc
->bios
.data
, sc
->bios
.size
);
1048 sc
->fep
.size
= bios
->fep_size
;
1049 if (sc
->fep
.size
!= 0 && bios
->fep
!= NULL
) {
1050 sc
->fep
.data
= kmalloc(sc
->fep
.size
, M_TTYS
, M_WAITOK
);
1051 bcopy(bios
->fep
, sc
->fep
.data
, sc
->fep
.size
);
1058 digiioctl(struct dev_ioctl_args
*ap
)
1060 cdev_t dev
= ap
->a_head
.a_dev
;
1061 u_long cmd
= ap
->a_cmd
;
1062 caddr_t data
= ap
->a_data
;
1063 int unit
, pnum
, mynor
, error
;
1064 struct digi_softc
*sc
;
1065 struct digi_p
*port
;
1067 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1069 struct termios term
;
1073 unit
= MINOR_TO_UNIT(mynor
);
1074 pnum
= MINOR_TO_PORT(mynor
);
1076 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1077 KASSERT(sc
, ("digi%d: softc not allocated in digiioctl\n", unit
));
1079 if (sc
->status
== DIGI_STATUS_DISABLED
)
1082 if (mynor
& CTRL_DEV
) {
1086 digi_debug
= *(int *)data
;
1089 device_printf(sc
->dev
, "DEBUG not defined\n");
1094 error
= digi_init(sc
);
1099 *(enum digi_model
*)data
= sc
->model
;
1103 return (copyout(sc
->name
, *(char **)data
,
1104 strlen(sc
->name
) + 1));
1108 if (pnum
>= sc
->numports
)
1111 port
= sc
->ports
+ pnum
;
1112 if (!(port
->status
& ENABLED
))
1117 if (mynor
& CONTROL_MASK
) {
1120 switch (mynor
& CONTROL_MASK
) {
1121 case CONTROL_INIT_STATE
:
1122 ct
= (mynor
& CALLOUT_MASK
) ?
1123 &port
->it_out
: &port
->it_in
;
1125 case CONTROL_LOCK_STATE
:
1126 ct
= (mynor
& CALLOUT_MASK
) ?
1127 &port
->lt_out
: &port
->lt_in
;
1130 return (ENODEV
); /* /dev/nodev */
1135 error
= priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0);
1138 *ct
= *(struct termios
*)data
;
1142 *(struct termios
*)data
= *ct
;
1146 *(int *)data
= TTYDISC
;
1150 bzero(data
, sizeof(struct winsize
));
1153 case DIGIIO_GETALTPIN
:
1154 switch (mynor
& CONTROL_MASK
) {
1155 case CONTROL_INIT_STATE
:
1156 *(int *)data
= port
->ialtpin
;
1159 case CONTROL_LOCK_STATE
:
1160 *(int *)data
= port
->laltpin
;
1164 panic("Confusion when re-testing minor");
1169 case DIGIIO_SETALTPIN
:
1170 switch (mynor
& CONTROL_MASK
) {
1171 case CONTROL_INIT_STATE
:
1172 if (!port
->laltpin
) {
1173 port
->ialtpin
= !!*(int *)data
;
1174 DLOG(DIGIDB_SET
, (sc
->dev
,
1175 "port%d: initial ALTPIN %s\n", pnum
,
1176 port
->ialtpin
? "set" : "cleared"));
1180 case CONTROL_LOCK_STATE
:
1181 port
->laltpin
= !!*(int *)data
;
1182 DLOG(DIGIDB_SET
, (sc
->dev
,
1183 "port%d: ALTPIN %slocked\n",
1184 pnum
, port
->laltpin
? "" : "un"));
1188 panic("Confusion when re-testing minor");
1199 case DIGIIO_GETALTPIN
:
1200 *(int *)data
= !!(port
->dsr
== sc
->csigs
->cd
);
1203 case DIGIIO_SETALTPIN
:
1204 if (!port
->laltpin
) {
1206 DLOG(DIGIDB_SET
, (sc
->dev
,
1207 "port%d: ALTPIN set\n", pnum
));
1208 port
->cd
= sc
->csigs
->dsr
;
1209 port
->dsr
= sc
->csigs
->cd
;
1211 DLOG(DIGIDB_SET
, (sc
->dev
,
1212 "port%d: ALTPIN cleared\n", pnum
));
1213 port
->cd
= sc
->csigs
->cd
;
1214 port
->dsr
= sc
->csigs
->dsr
;
1221 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1222 term
= tp
->t_termios
;
1224 error
= ttsetcompat(tp
, &cmd
, data
, &term
);
1228 data
= (caddr_t
) & term
;
1230 if (cmd
== TIOCSETA
|| cmd
== TIOCSETAW
|| cmd
== TIOCSETAF
) {
1235 dt
= (struct termios
*)data
;
1236 lt
= (mynor
& CALLOUT_MASK
) ? &port
->lt_out
: &port
->lt_in
;
1239 (tp
->t_iflag
& lt
->c_iflag
) | (dt
->c_iflag
& ~lt
->c_iflag
);
1241 (tp
->t_oflag
& lt
->c_oflag
) | (dt
->c_oflag
& ~lt
->c_oflag
);
1243 (tp
->t_cflag
& lt
->c_cflag
) | (dt
->c_cflag
& ~lt
->c_cflag
);
1245 (tp
->t_lflag
& lt
->c_lflag
) | (dt
->c_lflag
& ~lt
->c_lflag
);
1246 port
->c_iflag
= dt
->c_iflag
& (IXOFF
| IXON
| IXANY
);
1247 dt
->c_iflag
&= ~(IXOFF
| IXON
| IXANY
);
1248 for (cc
= 0; cc
< NCCS
; ++cc
)
1249 if (lt
->c_cc
[cc
] != 0)
1250 dt
->c_cc
[cc
] = tp
->t_cc
[cc
];
1251 if (lt
->c_ispeed
!= 0)
1252 dt
->c_ispeed
= tp
->t_ispeed
;
1253 if (lt
->c_ospeed
!= 0)
1254 dt
->c_ospeed
= tp
->t_ospeed
;
1256 error
= linesw
[tp
->t_line
].l_ioctl(tp
, cmd
, data
,
1257 ap
->a_fflag
, ap
->a_cred
);
1258 if (error
== 0 && cmd
== TIOCGETA
)
1259 ((struct termios
*)data
)->c_iflag
|= port
->c_iflag
;
1261 if (error
>= 0 && error
!= ENOIOCTL
)
1264 error
= ttioctl(tp
, cmd
, data
, ap
->a_fflag
);
1265 if (error
== 0 && cmd
== TIOCGETA
)
1266 ((struct termios
*)data
)->c_iflag
|= port
->c_iflag
;
1268 digi_disc_optim(tp
, &tp
->t_termios
, port
);
1269 if (error
>= 0 && error
!= ENOIOCTL
) {
1276 port
->send_ring
= *(u_char
*)data
;
1280 * now it sends 400 millisecond break because I don't know
1281 * how to send an infinite break
1283 fepcmd_w(port
, SENDBREAK
, 400, 10);
1286 /* now it's empty */
1289 digimctl(port
, TIOCM_DTR
, DMBIS
);
1292 digimctl(port
, TIOCM_DTR
, DMBIC
);
1295 digimctl(port
, *(int *)data
, DMSET
);
1298 digimctl(port
, *(int *)data
, DMBIS
);
1301 digimctl(port
, *(int *)data
, DMBIC
);
1304 *(int *)data
= digimctl(port
, 0, DMGET
);
1307 error
= priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0);
1312 port
->dtr_wait
= *(int *)data
*hz
/ 100;
1316 *(int *)data
= port
->dtr_wait
* 100 / hz
;
1318 #ifdef DIGI_INTERRUPT
1320 *(struct timeval
*)data
= sc
->intr_timestamp
;
1333 digiparam(struct tty
*tp
, struct termios
*t
)
1338 struct digi_softc
*sc
;
1339 struct digi_p
*port
;
1345 mynor
= minor(tp
->t_dev
);
1346 unit
= MINOR_TO_UNIT(mynor
);
1347 pnum
= MINOR_TO_PORT(mynor
);
1349 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1350 KASSERT(sc
, ("digi%d: softc not allocated in digiparam\n", unit
));
1352 port
= &sc
->ports
[pnum
];
1354 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: setting parameters\n", pnum
));
1356 if (t
->c_ispeed
== 0)
1357 t
->c_ispeed
= t
->c_ospeed
;
1359 cflag
= ttspeedtab(t
->c_ospeed
, digispeedtab
);
1361 if (cflag
< 0 || (cflag
> 0 && t
->c_ispeed
!= t
->c_ospeed
))
1366 window
= sc
->window
;
1369 if (cflag
== 0) { /* hangup */
1370 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: hangup\n", pnum
));
1371 digimctl(port
, TIOCM_DTR
| TIOCM_RTS
, DMBIC
);
1373 digimctl(port
, TIOCM_DTR
| TIOCM_RTS
, DMBIS
);
1375 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: CBAUD = %d\n", pnum
,
1379 /* convert flags to sysV-style values */
1380 if (t
->c_cflag
& PARODD
)
1382 if (t
->c_cflag
& PARENB
)
1384 if (t
->c_cflag
& CSTOPB
)
1387 /* convert flags to sysV-style values */
1388 if (t
->c_cflag
& PARODD
)
1389 cflag
|= FEP_PARODD
;
1390 if (t
->c_cflag
& PARENB
)
1391 cflag
|= FEP_PARENB
;
1392 if (t
->c_cflag
& CSTOPB
)
1393 cflag
|= FEP_CSTOPB
;
1394 if (t
->c_cflag
& CLOCAL
)
1395 cflag
|= FEP_CLOCAL
;
1398 cflag
|= (t
->c_cflag
& CSIZE
) >> 4;
1399 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: CFLAG = 0x%x\n", pnum
,
1401 fepcmd_w(port
, SETCFLAGS
, (unsigned)cflag
, 0);
1405 t
->c_iflag
& (IGNBRK
| BRKINT
| IGNPAR
| PARMRK
| INPCK
| ISTRIP
);
1406 if (port
->c_iflag
& IXON
)
1408 if (port
->c_iflag
& IXANY
)
1410 if (port
->c_iflag
& IXOFF
)
1413 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: set iflag = 0x%x\n", pnum
, iflag
));
1414 fepcmd_w(port
, SETIFLAGS
, (unsigned)iflag
, 0);
1417 if (t
->c_cflag
& CDTR_IFLOW
)
1418 hflow
|= sc
->csigs
->dtr
;
1419 if (t
->c_cflag
& CRTS_IFLOW
)
1420 hflow
|= sc
->csigs
->rts
;
1421 if (t
->c_cflag
& CCTS_OFLOW
)
1422 hflow
|= sc
->csigs
->cts
;
1423 if (t
->c_cflag
& CDSR_OFLOW
)
1425 if (t
->c_cflag
& CCAR_OFLOW
)
1428 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: set hflow = 0x%x\n", pnum
, hflow
));
1429 fepcmd_w(port
, SETHFLOW
, 0xff00 | (unsigned)hflow
, 0);
1431 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: set startc(0x%x), stopc(0x%x)\n",
1432 pnum
, t
->c_cc
[VSTART
], t
->c_cc
[VSTOP
]));
1433 fepcmd_b(port
, SONOFFC
, t
->c_cc
[VSTART
], t
->c_cc
[VSTOP
], 0);
1435 if (sc
->window
!= 0)
1438 sc
->towin(sc
, window
);
1447 struct digi_p
*port
;
1449 struct digi_softc
*sc
;
1451 volatile struct board_chan
*bc
;
1465 if (sc
->status
!= DIGI_STATUS_ENABLED
) {
1466 DLOG(DIGIDB_IRQ
, (sc
->dev
, "interrupt on disabled board !\n"));
1470 #ifdef DIGI_INTERRUPT
1471 microtime(&sc
->intr_timestamp
);
1474 window
= sc
->window
;
1477 if (sc
->model
>= PCXEM
&& W(sc
->vmem
+ 0xd00)) {
1478 struct con_bios
*con
= con_bios_list
;
1481 ptr
= sc
->vmem
+ W(sc
->vmem
+ 0xd00);
1483 if (ptr
[1] && W(ptr
+ 2) == W(con
->bios
+ 2))
1484 /* Not first block -- exact match */
1487 if (W(ptr
+ 4) >= W(con
->bios
+ 4) &&
1488 W(ptr
+ 4) <= W(con
->bios
+ 6))
1489 /* Initial search concetrator BIOS */
1494 log(LOG_ERR
, "digi%d: wanted bios LREV = 0x%04x"
1495 " not found!\n", sc
->res
.unit
, W(ptr
+ 4));
1497 W(sc
->vmem
+ 0xd00) = 0;
1501 W(ptr
+ 4) = W(cxcon
+ 4);
1502 W(ptr
+ 6) = W(cxcon
+ 6);
1504 W(ptr
+ 2) = W(cxcon
+ 2);
1505 W(ptr
+ 8) = (ptr
[1] << 6) + W(cxcon
+ 8);
1506 size
= W(cxcon
+ 10) - (ptr
[1] << 10);
1508 W(ptr
+ 8) = W(cxcon
+ 8);
1514 bcopy(cxcon
+ (ptr
[1] << 10), ptr
+ 12, size
);
1516 W(sc
->vmem
+ 0xd00) = 0;
1520 ehead
= sc
->gdata
->ein
;
1521 etail
= sc
->gdata
->eout
;
1522 if (ehead
== etail
) {
1525 if (sc
->intr_count
% 6000 == 0) {
1526 DLOG(DIGIDB_IRQ
, (sc
->dev
,
1527 "6000 useless polls %x %x\n", ehead
, etail
));
1533 while (ehead
!= etail
) {
1534 event
= *(volatile struct event
*)(sc
->memevent
+ etail
);
1536 etail
= (etail
+ 4) & sc
->gdata
->imax
;
1538 if (event
.pnum
>= sc
->numports
) {
1539 log(LOG_ERR
, "digi%d: port %d: got event"
1540 " on nonexisting port\n", sc
->res
.unit
,
1544 port
= &sc
->ports
[event
.pnum
];
1548 if (!(tp
->t_state
& TS_ISOPEN
) && !port
->wopeners
) {
1549 DLOG(DIGIDB_IRQ
, (sc
->dev
,
1550 "port %d: event 0x%x on closed port\n",
1551 event
.pnum
, event
.event
));
1559 if (event
.event
& ~ALL_IND
)
1560 log(LOG_ERR
, "digi%d: port%d: ? event 0x%x mstat 0x%x"
1561 " lstat 0x%x\n", sc
->res
.unit
, event
.pnum
,
1562 event
.event
, event
.mstat
, event
.lstat
);
1564 if (event
.event
& DATA_IND
) {
1565 DLOG(DIGIDB_IRQ
, (sc
->dev
, "port %d: DATA_IND\n",
1567 wrapmask
= port
->rxbufsize
- 1;
1572 if (!(tp
->t_state
& TS_ISOPEN
)) {
1576 while (head
!= tail
) {
1579 DLOG(DIGIDB_INT
, (sc
->dev
,
1580 "port %d: p rx head = %d tail = %d\n",
1581 event
.pnum
, head
, tail
));
1582 top
= (head
> tail
) ? head
: wrapmask
+ 1;
1583 sc
->towin(sc
, port
->rxwin
);
1585 if (tp
->t_state
& TS_CAN_BYPASS_L_RINT
) {
1586 size
= b_to_q((char *)port
->rxbuf
+
1587 tail
, size
, &tp
->t_rawq
);
1590 } else for (; tail
< top
;) {
1592 l_rint(port
->rxbuf
[tail
], tp
);
1593 sc
->towin(sc
, port
->rxwin
);
1596 if (tp
->t_state
& TS_TBLOCK
)
1608 CE_RECORD(port
, CE_OVERRUN
);
1609 log(LOG_ERR
, "digi%d: port%d: %s\n",
1610 sc
->res
.unit
, event
.pnum
,
1611 digi_errortxt(CE_OVERRUN
));
1616 tp
->t_state
|= TS_TBLOCK
;
1617 port
->status
|= PAUSE_RX
;
1618 DLOG(DIGIDB_RX
, (sc
->dev
, "port %d: pause RX\n",
1625 if (event
.event
& MODEMCHG_IND
) {
1626 DLOG(DIGIDB_MODEM
, (sc
->dev
, "port %d: MODEMCHG_IND\n",
1629 if ((event
.mstat
^ event
.lstat
) & port
->cd
) {
1631 linesw
[tp
->t_line
].l_modem
1632 (tp
, event
.mstat
& port
->cd
);
1634 wakeup(TSA_CARR_ON(tp
));
1637 if (event
.mstat
& sc
->csigs
->ri
) {
1638 DLOG(DIGIDB_RI
, (sc
->dev
, "port %d: RING\n",
1640 if (port
->send_ring
) {
1641 linesw
[tp
->t_line
].l_rint('R', tp
);
1642 linesw
[tp
->t_line
].l_rint('I', tp
);
1643 linesw
[tp
->t_line
].l_rint('N', tp
);
1644 linesw
[tp
->t_line
].l_rint('G', tp
);
1645 linesw
[tp
->t_line
].l_rint('\r', tp
);
1646 linesw
[tp
->t_line
].l_rint('\n', tp
);
1650 if (event
.event
& BREAK_IND
) {
1651 DLOG(DIGIDB_MODEM
, (sc
->dev
, "port %d: BREAK_IND\n",
1653 linesw
[tp
->t_line
].l_rint(TTY_BI
, tp
);
1655 if (event
.event
& (LOWTX_IND
| EMPTYTX_IND
)) {
1656 DLOG(DIGIDB_IRQ
, (sc
->dev
, "port %d:%s%s\n",
1658 event
.event
& LOWTX_IND
? " LOWTX" : "",
1659 event
.event
& EMPTYTX_IND
? " EMPTYTX" : ""));
1660 (*linesw
[tp
->t_line
].l_start
)(tp
);
1663 sc
->gdata
->eout
= etail
;
1665 if (sc
->window
!= 0)
1668 sc
->towin(sc
, window
);
1672 digistart(struct tty
*tp
)
1676 struct digi_p
*port
;
1677 struct digi_softc
*sc
;
1678 volatile struct board_chan
*bc
;
1680 int size
, ocount
, totcnt
= 0;
1683 unit
= MINOR_TO_UNIT(minor(tp
->t_dev
));
1684 pnum
= MINOR_TO_PORT(minor(tp
->t_dev
));
1686 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1687 KASSERT(sc
, ("digi%d: softc not allocated in digistart\n", unit
));
1689 port
= &sc
->ports
[pnum
];
1692 wmask
= port
->txbufsize
- 1;
1695 port
->lcc
= tp
->t_outq
.c_cc
;
1697 if (!(tp
->t_state
& TS_TBLOCK
)) {
1698 if (port
->status
& PAUSE_RX
) {
1699 DLOG(DIGIDB_RX
, (sc
->dev
, "port %d: resume RX\n",
1702 * CAREFUL - braces are needed here if the DLOG is
1706 port
->status
&= ~PAUSE_RX
;
1709 if (!(tp
->t_state
& TS_TTSTOP
) && port
->status
& PAUSE_TX
) {
1710 DLOG(DIGIDB_TX
, (sc
->dev
, "port %d: resume TX\n", pnum
));
1711 port
->status
&= ~PAUSE_TX
;
1712 fepcmd_w(port
, RESUMETX
, 0, 10);
1714 if (tp
->t_outq
.c_cc
== 0)
1715 tp
->t_state
&= ~TS_BUSY
;
1717 tp
->t_state
|= TS_BUSY
;
1720 while (tp
->t_outq
.c_cc
!= 0) {
1722 DLOG(DIGIDB_INT
, (sc
->dev
, "port%d: s tx head = %d tail = %d\n",
1726 size
= tail
- head
- 1;
1728 size
= port
->txbufsize
- head
;
1735 sc
->towin(sc
, port
->txwin
);
1736 ocount
= q_to_b(&tp
->t_outq
, port
->txbuf
+ head
, size
);
1745 port
->lostcc
= tp
->t_outq
.c_cc
;
1748 size
= port
->txbufsize
- tail
+ head
;
1753 DLOG(DIGIDB_INT
, (sc
->dev
, "port%d: s total cnt = %d\n", pnum
, totcnt
));
1759 digistop(struct tty
*tp
, int rw
)
1761 struct digi_softc
*sc
;
1764 struct digi_p
*port
;
1766 unit
= MINOR_TO_UNIT(minor(tp
->t_dev
));
1767 pnum
= MINOR_TO_PORT(minor(tp
->t_dev
));
1769 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1770 KASSERT(sc
, ("digi%d: softc not allocated in digistop\n", unit
));
1771 port
= sc
->ports
+ pnum
;
1773 DLOG(DIGIDB_TX
, (sc
->dev
, "port %d: pause TX\n", pnum
));
1774 port
->status
|= PAUSE_TX
;
1775 fepcmd_w(port
, PAUSETX
, 0, 10);
1779 fepcmd(struct digi_p
*port
, int cmd
, int op1
, int ncmds
)
1782 unsigned tail
, head
;
1785 mem
= port
->sc
->memcmd
;
1787 port
->sc
->setwin(port
->sc
, 0);
1789 head
= port
->sc
->gdata
->cin
;
1790 mem
[head
+ 0] = cmd
;
1791 mem
[head
+ 1] = port
->pnum
;
1792 *(u_short
*)(mem
+ head
+ 2) = op1
;
1794 head
= (head
+ 4) & port
->sc
->gdata
->cmax
;
1795 port
->sc
->gdata
->cin
= head
;
1797 for (count
= FEPTIMEOUT
; count
> 0; count
--) {
1798 head
= port
->sc
->gdata
->cin
;
1799 tail
= port
->sc
->gdata
->cout
;
1800 n
= (head
- tail
) & port
->sc
->gdata
->cmax
;
1802 if (n
<= ncmds
* sizeof(short) * 4)
1806 log(LOG_ERR
, "digi%d: port%d: timeout on FEP command\n",
1807 port
->sc
->res
.unit
, port
->pnum
);
1811 digi_errortxt(int id
)
1813 static const char *error_desc
[] = {
1815 "interrupt-level buffer overflow",
1816 "tty-level buffer overflow",
1819 KASSERT(id
>= 0 && id
< sizeof(error_desc
) / sizeof(error_desc
[0]),
1820 ("Unexpected digi error id %d\n", id
));
1822 return (error_desc
[id
]);
1826 digi_attach(struct digi_softc
*sc
)
1828 sc
->res
.ctldev
= make_dev(&digi_ops
,
1829 (sc
->res
.unit
<< 16) | CTRL_DEV
, UID_ROOT
, GID_WHEEL
,
1830 0600, "digi%r.ctl", sc
->res
.unit
);
1840 digi_inuse(struct digi_softc
*sc
)
1844 for (i
= 0; i
< sc
->numports
; i
++)
1845 if (sc
->ttys
[i
].t_state
& TS_ISOPEN
) {
1846 DLOG(DIGIDB_INIT
, (sc
->dev
, "port%d: busy\n", i
));
1848 } else if (sc
->ports
[i
].wopeners
|| sc
->ports
[i
].opencnt
) {
1849 DLOG(DIGIDB_INIT
, (sc
->dev
, "port%d: blocked in open\n",
1857 digi_free_state(struct digi_softc
*sc
)
1861 /* Blow it all away */
1863 for (i
= 0; i
< sc
->numports
; i
++)
1864 for (d
= 0; d
< 6; d
++)
1865 destroy_dev(sc
->ports
[i
].dev
[d
]);
1867 callout_stop(&sc
->callout
);
1868 callout_stop(&sc
->inttest
);
1870 bus_teardown_intr(sc
->dev
, sc
->res
.irq
, sc
->res
.irqHandler
);
1871 #ifdef DIGI_INTERRUPT
1872 if (sc
->res
.irq
!= NULL
) {
1873 bus_release_resource(dev
, SYS_RES_IRQ
, sc
->res
.irqrid
,
1879 KASSERT(sc
->ports
, ("digi%d: Lost my ports ?", sc
->res
.unit
));
1880 KASSERT(sc
->ttys
, ("digi%d: Lost my ttys ?", sc
->res
.unit
));
1881 kfree(sc
->ports
, M_TTYS
);
1883 kfree(sc
->ttys
, M_TTYS
);
1888 sc
->status
= DIGI_STATUS_NOTINIT
;
1892 digi_detach(device_t dev
)
1894 struct digi_softc
*sc
= device_get_softc(dev
);
1896 DLOG(DIGIDB_INIT
, (sc
->dev
, "detaching\n"));
1898 /* If we're INIT'd, numports must be 0 */
1899 KASSERT(sc
->numports
== 0 || sc
->status
!= DIGI_STATUS_NOTINIT
,
1900 ("digi%d: numports(%d) & status(%d) are out of sync",
1901 sc
->res
.unit
, sc
->numports
, (int)sc
->status
));
1906 digi_free_state(sc
);
1908 destroy_dev(sc
->res
.ctldev
);
1910 if (sc
->res
.mem
!= NULL
) {
1911 bus_release_resource(dev
, SYS_RES_MEMORY
, sc
->res
.mrid
,
1915 if (sc
->res
.io
!= NULL
) {
1916 bus_release_resource(dev
, SYS_RES_IOPORT
, sc
->res
.iorid
,
1921 pmap_unmapdev((vm_offset_t
)sc
->vmem
, sc
->msize
);
1929 digi_shutdown(device_t dev
)
1934 MODULE_VERSION(digi
, 1);