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.10 2006/12/23 00:26:24 swildner 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>
45 #include <sys/linker.h>
46 #include <sys/kernel.h>
48 #include <sys/malloc.h>
50 #include <sys/syslog.h>
51 #include <sys/fcntl.h>
54 #include <sys/thread2.h>
56 #include <dev/serial/digi/digiio.h>
57 #include <dev/serial/digi/digireg.h>
58 #include <dev/serial/digi/digi.h>
59 #include <dev/serial/digi/digi_pci.h>
60 #include <dev/serial/digi/digi_bios.h>
62 #define CDEV_MAJOR 162
64 #define CTRL_DEV 0x800000
65 #define CALLOUT_MASK 0x400000
66 #define CONTROL_INIT_STATE 0x100000
67 #define CONTROL_LOCK_STATE 0x200000
68 #define CONTROL_MASK (CTRL_DEV|CONTROL_INIT_STATE|CONTROL_LOCK_STATE)
69 #define UNIT_MASK 0x030000
70 #define PORT_MASK 0x0000FF
71 #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
72 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
73 #define MINOR_TO_UNIT(mynor) (((mynor) & UNIT_MASK)>>16)
74 #define MINOR_TO_PORT(mynor) ((mynor) & PORT_MASK)
76 static d_open_t digiopen
;
77 static d_close_t digiclose
;
78 static d_read_t digiread
;
79 static d_write_t digiwrite
;
80 static d_ioctl_t digiioctl
;
82 static void digistop(struct tty
*tp
, int rw
);
83 static int digimctl(struct digi_p
*port
, int bits
, int how
);
84 static void digi_poll(void *ptr
);
85 static void digi_freedata(struct digi_softc
*);
86 static void fepcmd(struct digi_p
*port
, int cmd
, int op
, int ncmds
);
87 static void digistart(struct tty
*tp
);
88 static int digiparam(struct tty
*tp
, struct termios
*t
);
89 static void digihardclose(struct digi_p
*port
);
90 static void digi_intr(void *);
91 static int digi_init(struct digi_softc
*_sc
);
92 static int digi_loaddata(struct digi_softc
*);
93 static int digi_inuse(struct digi_softc
*);
94 static void digi_free_state(struct digi_softc
*);
96 #define fepcmd_b(port, cmd, op1, op2, ncmds) \
97 fepcmd(port, cmd, (op2 << 8) | op1, ncmds)
98 #define fepcmd_w fepcmd
101 static speed_t digidefaultrate
= TTYDEF_SPEED
;
104 struct con_bios
*next
;
109 static struct con_bios
*con_bios_list
;
110 devclass_t digi_devclass
;
111 unsigned digi_debug
= 0;
113 static struct speedtab digispeedtab
[] = {
114 { 0, 0}, /* old (sysV-like) Bx codes */
130 { 57600, (02000 | 1)},
131 { 76800, (02000 | 2)},
132 { 115200, (02000 | 3)},
133 { 230400, (02000 | 6)},
137 const struct digi_control_signals digi_xixe_signals
= {
138 0x02, 0x08, 0x10, 0x20, 0x40, 0x80
141 const struct digi_control_signals digi_normal_signals
= {
142 0x02, 0x80, 0x20, 0x10, 0x40, 0x01
145 static struct dev_ops digi_ops
= {
146 { "dgm", CDEV_MAJOR
, D_TTY
},
148 .d_close
= digiclose
,
150 .d_write
= digiwrite
,
151 .d_ioctl
= digiioctl
,
153 .d_kqfilter
= ttykqfilter
159 struct digi_softc
*sc
;
161 sc
= (struct digi_softc
*)ptr
;
162 callout_init(&sc
->callout
);
164 callout_reset(&sc
->callout
, (hz
>= 200) ? hz
/ 100 : 1, digi_poll
, sc
);
168 digi_int_test(void *v
)
170 struct digi_softc
*sc
= v
;
172 callout_init(&sc
->inttest
);
173 #ifdef DIGI_INTERRUPT
174 if (sc
->intr_timestamp
.tv_sec
|| sc
->intr_timestamp
.tv_usec
) {
178 log(LOG_ERR
, "digi%d: Interrupt didn't work, use polled mode\n", unit
);
180 callout_reset(&sc
->callout
, (hz
>= 200) ? hz
/ 100 : 1, digi_poll
, sc
);
184 digi_freedata(struct digi_softc
*sc
)
186 if (sc
->fep
.data
!= NULL
) {
187 kfree(sc
->fep
.data
, M_TTYS
);
190 if (sc
->link
.data
!= NULL
) {
191 kfree(sc
->link
.data
, M_TTYS
);
192 sc
->link
.data
= NULL
;
194 if (sc
->bios
.data
!= NULL
) {
195 kfree(sc
->bios
.data
, M_TTYS
);
196 sc
->bios
.data
= NULL
;
201 digi_bcopy(const void *vfrom
, void *vto
, size_t sz
)
203 volatile const char *from
= (volatile const char *)vfrom
;
204 volatile char *to
= (volatile char *)vto
;
207 for (i
= 0; i
< sz
; i
++)
210 from
= (const volatile char *)vfrom
;
211 to
= (volatile char *)vto
;
212 for (i
= 0; i
< sz
; i
++)
213 if (*to
++ != *from
++)
219 digi_delay(struct digi_softc
*sc
, const char *txt
, u_long timo
)
222 DELAY(timo
* 1000000 / hz
);
224 tsleep(sc
, PCATCH
, txt
, timo
);
228 digi_init(struct digi_softc
*sc
)
234 volatile struct board_chan
*bc
;
238 if (sc
->status
== DIGI_STATUS_DISABLED
) {
239 log(LOG_ERR
, "digi%d: Cannot init a disabled card\n",
243 if (sc
->bios
.data
== NULL
) {
244 log(LOG_ERR
, "digi%d: Cannot init without BIOS\n",
249 if (sc
->link
.data
== NULL
&& sc
->model
>= PCCX
) {
250 log(LOG_ERR
, "digi%d: Cannot init without link info\n",
255 if (sc
->fep
.data
== NULL
) {
256 log(LOG_ERR
, "digi%d: Cannot init without fep code\n",
260 sc
->status
= DIGI_STATUS_NOTINIT
;
264 * We're re-initialising - maybe because someone's attached
265 * another port module. For now, we just re-initialise
274 ptr
= sc
->setwin(sc
, MISCGLOBAL
);
275 for (i
= 0; i
< 16; i
+= 2)
280 outb(sc
->wport
, 0xff); /* window 7 */
281 ptr
= sc
->vmem
+ (BIOSCODE
& 0x1fff);
283 if (!digi_bcopy(sc
->bios
.data
, ptr
, sc
->bios
.size
)) {
284 device_printf(sc
->dev
, "BIOS upload failed\n");
288 outb(sc
->port
, FEPCLR
);
294 ptr
= sc
->setwin(sc
, BIOSCODE
+ ((0xf000 - sc
->mem_seg
) << 4));
295 if (!digi_bcopy(sc
->bios
.data
, ptr
, sc
->bios
.size
)) {
296 device_printf(sc
->dev
, "BIOS upload failed\n");
307 outb(sc
->port
, FEPRST
| FEPMEM
);
309 for (i
= 0; ((sc
->pcibus
? PCIPORT
: inb(sc
->port
)) &
310 FEPMASK
) != FEPRST
; i
++) {
312 log(LOG_ERR
, "digi%d: %s init reset failed\n",
313 sc
->res
.unit
, sc
->name
);
316 digi_delay(sc
, "digiinit0", 5);
318 DLOG(DIGIDB_INIT
, (sc
->dev
, "Got init reset after %d us\n", i
));
320 /* Now upload the BIOS */
321 cnt
= (sc
->bios
.size
< sc
->win_size
- BIOSOFFSET
) ?
322 sc
->bios
.size
: sc
->win_size
- BIOSOFFSET
;
324 ptr
= sc
->setwin(sc
, BIOSOFFSET
);
325 if (!digi_bcopy(sc
->bios
.data
, ptr
, cnt
)) {
326 device_printf(sc
->dev
, "BIOS upload (1) failed\n");
330 if (cnt
!= sc
->bios
.size
) {
331 /* and the second part */
332 ptr
= sc
->setwin(sc
, sc
->win_size
);
333 if (!digi_bcopy(sc
->bios
.data
+ cnt
, ptr
,
334 sc
->bios
.size
- cnt
)) {
335 device_printf(sc
->dev
, "BIOS upload failed\n");
340 ptr
= sc
->setwin(sc
, 0);
341 vW(ptr
+ 0) = 0x0401;
342 vW(ptr
+ 2) = 0x0bf0;
343 vW(ptr
+ 4) = 0x0000;
344 vW(ptr
+ 6) = 0x0000;
349 DLOG(DIGIDB_INIT
, (sc
->dev
, "BIOS uploaded\n"));
351 ptr
= sc
->setwin(sc
, MISCGLOBAL
);
357 } else if (sc
->model
== PCXEVE
) {
358 outb(sc
->port
, FEPCLR
);
361 outb(sc
->port
, FEPCLR
| FEPMEM
);
362 resp
= FEPRST
| FEPMEM
;
365 for (i
= 0; ((sc
->pcibus
? PCIPORT
: inb(sc
->port
)) & FEPMASK
)
368 log(LOG_ERR
, "digi%d: BIOS start failed\n",
372 digi_delay(sc
, "digibios0", 5);
375 DLOG(DIGIDB_INIT
, (sc
->dev
, "BIOS started after %d us\n", i
));
377 for (i
= 0; vW(ptr
) != *(u_short
*)"GD"; i
++) {
379 log(LOG_ERR
, "digi%d: BIOS boot failed "
380 "(0x%02x != 0x%02x)\n",
381 sc
->res
.unit
, vW(ptr
), *(u_short
*)"GD");
384 digi_delay(sc
, "digibios1", 5);
387 DLOG(DIGIDB_INIT
, (sc
->dev
, "BIOS booted after %d iterations\n", i
));
389 if (sc
->link
.data
!= NULL
) {
390 DLOG(DIGIDB_INIT
, (sc
->dev
, "Loading link data\n"));
391 ptr
= sc
->setwin(sc
, 0xcd0);
392 digi_bcopy(sc
->link
.data
, ptr
, 21); /* XXX 21 ? */
401 ptr
= sc
->setwin(sc
, sc
->model
== PCXI
? 0x2000 : 0x0);
402 digi_bcopy(sc
->fep
.data
, ptr
, sc
->fep
.size
);
404 /* A BIOS request to move our data to 0x2000 */
405 ptr
= sc
->setwin(sc
, MBOX
);
407 vW(ptr
+ 2) = sc
->mem_seg
+ FEPCODESEG
;
409 vW(ptr
+ 6) = FEPCODESEG
;
411 vW(ptr
+ 10) = sc
->fep
.size
;
413 /* Run the BIOS request */
414 outb(sc
->port
, FEPREQ
| FEPMEM
);
415 outb(sc
->port
, FEPCLR
| FEPMEM
);
417 for (i
= 0; W(ptr
); i
++) {
419 log(LOG_ERR
, "digi%d: FEP/OS move failed\n",
424 digi_delay(sc
, "digifep0", 5);
427 (sc
->dev
, "FEP/OS moved after %d iterations\n", i
));
429 /* Clear the confirm word */
430 ptr
= sc
->setwin(sc
, FEPSTAT
);
433 /* A BIOS request to execute the FEP/OS */
434 ptr
= sc
->setwin(sc
, MBOX
);
436 vW(ptr
+ 2) = FEPCODESEG
;
439 /* Run the BIOS request */
440 outb(sc
->port
, FEPREQ
);
441 outb(sc
->port
, FEPCLR
);
443 ptr
= sc
->setwin(sc
, FEPSTAT
);
450 DLOG(DIGIDB_INIT
, (sc
->dev
, "Loading FEP/OS\n"));
452 cnt
= (sc
->fep
.size
< sc
->win_size
- BIOSOFFSET
) ?
453 sc
->fep
.size
: sc
->win_size
- BIOSOFFSET
;
455 ptr
= sc
->setwin(sc
, BIOSOFFSET
);
456 digi_bcopy(sc
->fep
.data
, ptr
, cnt
);
458 if (cnt
!= sc
->fep
.size
) {
459 ptr
= sc
->setwin(sc
, BIOSOFFSET
+ cnt
);
460 digi_bcopy(sc
->fep
.data
+ cnt
, ptr
,
464 DLOG(DIGIDB_INIT
, (sc
->dev
, "FEP/OS loaded\n"));
466 ptr
= sc
->setwin(sc
, 0xc30);
472 /* Clear the confirm word */
473 ptr
= sc
->setwin(sc
, FEPSTAT
);
477 outb(sc
->port
, 0); /* XXX necessary ? */
482 ptr
= sc
->setwin(sc
, 0xd000);
483 digi_bcopy(sc
->fep
.data
, ptr
, sc
->fep
.size
);
485 /* A BIOS request to execute the FEP/OS */
486 ptr
= sc
->setwin(sc
, 0xc40);
488 W(ptr
+ 2) = FEPCODE
>> 4;
491 /* Clear the confirm word */
492 ptr
= sc
->setwin(sc
, FEPSTAT
);
495 /* Run the BIOS request */
496 outb(sc
->port
, FEPREQ
| FEPMEM
); /* send interrupt to BIOS */
497 outb(sc
->port
, FEPCLR
| FEPMEM
);
501 /* Now wait 'till the FEP/OS has booted */
502 for (i
= 0; vW(ptr
) != *(u_short
*)"OS"; i
++) {
504 log(LOG_ERR
, "digi%d: FEP/OS start failed "
505 "(0x%02x != 0x%02x)\n",
506 sc
->res
.unit
, vW(ptr
), *(u_short
*)"OS");
510 digi_delay(sc
, "digifep1", 5);
513 DLOG(DIGIDB_INIT
, (sc
->dev
, "FEP/OS started after %d iterations\n", i
));
515 if (sc
->model
>= PCXEM
) {
516 ptr
= sc
->setwin(sc
, 0xe04);
518 ptr
= sc
->setwin(sc
, 0xc02);
519 sc
->numports
= vW(ptr
);
521 ptr
= sc
->setwin(sc
, 0xc22);
522 sc
->numports
= vW(ptr
);
525 if (sc
->numports
== 0) {
526 device_printf(sc
->dev
, "%s, 0 ports found\n", sc
->name
);
531 if (sc
->numports
> 256) {
532 /* Our minor numbering scheme is broken for more than 256 */
533 device_printf(sc
->dev
, "%s, 256 ports (%d ports found)\n",
534 sc
->name
, sc
->numports
);
537 device_printf(sc
->dev
, "%s, %d ports found\n", sc
->name
,
541 kfree(sc
->ports
, M_TTYS
);
542 sc
->ports
= kmalloc(sizeof(struct digi_p
) * sc
->numports
,
543 M_TTYS
, M_WAITOK
| M_ZERO
);
546 kfree(sc
->ttys
, M_TTYS
);
547 sc
->ttys
= kmalloc(sizeof(struct tty
) * sc
->numports
,
548 M_TTYS
, M_WAITOK
| M_ZERO
);
551 * XXX Should read port 0xc90 for an array of 2byte values, 1 per
552 * port. If the value is 0, the port is broken....
555 ptr
= sc
->setwin(sc
, 0);
557 /* We should now init per-port structures */
558 bc
= (volatile struct board_chan
*)(ptr
+ CHANSTRUCT
);
559 sc
->gdata
= (volatile struct global_data
*)(ptr
+ FEP_GLOBAL
);
561 sc
->memcmd
= ptr
+ sc
->gdata
->cstart
;
562 sc
->memevent
= ptr
+ sc
->gdata
->istart
;
564 for (i
= 0; i
< sc
->numports
; i
++, bc
++) {
565 port
= sc
->ports
+ i
;
568 port
->status
= ENABLED
;
569 port
->tp
= sc
->ttys
+ i
;
572 if (sc
->model
== PCXEVE
) {
574 (((bc
->tseg
- sc
->mem_seg
) << 4) & 0x1fff);
576 (((bc
->rseg
- sc
->mem_seg
) << 4) & 0x1fff);
577 port
->txwin
= FEPWIN
| ((bc
->tseg
- sc
->mem_seg
) >> 9);
578 port
->rxwin
= FEPWIN
| ((bc
->rseg
- sc
->mem_seg
) >> 9);
579 } else if (sc
->model
== PCXI
|| sc
->model
== PCXE
) {
580 port
->txbuf
= ptr
+ ((bc
->tseg
- sc
->mem_seg
) << 4);
581 port
->rxbuf
= ptr
+ ((bc
->rseg
- sc
->mem_seg
) << 4);
582 port
->txwin
= port
->rxwin
= 0;
585 (((bc
->tseg
- sc
->mem_seg
) << 4) % sc
->win_size
);
587 (((bc
->rseg
- sc
->mem_seg
) << 4) % sc
->win_size
);
588 port
->txwin
= FEPWIN
|
589 (((bc
->tseg
- sc
->mem_seg
) << 4) / sc
->win_size
);
590 port
->rxwin
= FEPWIN
|
591 (((bc
->rseg
- sc
->mem_seg
) << 4) / sc
->win_size
);
593 port
->txbufsize
= bc
->tmax
+ 1;
594 port
->rxbufsize
= bc
->rmax
+ 1;
596 lowwater
= port
->txbufsize
>> 2;
600 fepcmd_w(port
, STXLWATER
, lowwater
, 10);
601 fepcmd_w(port
, SRXLWATER
, port
->rxbufsize
>> 2, 10);
602 fepcmd_w(port
, SRXHWATER
, (3 * port
->rxbufsize
) >> 2, 10);
605 port
->dtr_wait
= 3 * hz
;
608 * We don't use all the flags from <sys/ttydefaults.h> since
609 * they are only relevant for logins. It's important to have
610 * echo off initially so that the line doesn't start blathering
611 * before the echo flag can be turned off.
613 port
->it_in
.c_iflag
= 0;
614 port
->it_in
.c_oflag
= 0;
615 port
->it_in
.c_cflag
= TTYDEF_CFLAG
;
616 port
->it_in
.c_lflag
= 0;
617 termioschars(&port
->it_in
);
618 port
->it_in
.c_ispeed
= port
->it_in
.c_ospeed
= digidefaultrate
;
619 port
->it_out
= port
->it_in
;
620 port
->send_ring
= 1; /* Default action on signal RI */
622 port
->dev
[0] = make_dev(&digi_ops
, (sc
->res
.unit
<< 16) + i
,
623 UID_ROOT
, GID_WHEEL
, 0600, "ttyD%d.%d", sc
->res
.unit
, i
);
624 port
->dev
[1] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
625 CONTROL_INIT_STATE
, UID_ROOT
, GID_WHEEL
,
626 0600, "ttyiD%d.%d", sc
->res
.unit
, i
);
627 port
->dev
[2] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
628 CONTROL_LOCK_STATE
, UID_ROOT
, GID_WHEEL
,
629 0600, "ttylD%d.%d", sc
->res
.unit
, i
);
630 port
->dev
[3] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
631 CALLOUT_MASK
, UID_UUCP
, GID_DIALER
,
632 0660, "cuaD%d.%d", sc
->res
.unit
, i
);
633 port
->dev
[4] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
634 CALLOUT_MASK
| CONTROL_INIT_STATE
, UID_UUCP
, GID_DIALER
,
635 0660, "cuaiD%d.%d", sc
->res
.unit
, i
);
636 port
->dev
[5] = make_dev(&digi_ops
, ((sc
->res
.unit
<< 16) + i
) |
637 CALLOUT_MASK
| CONTROL_LOCK_STATE
, UID_UUCP
, GID_DIALER
,
638 0660, "cualD%d.%d", sc
->res
.unit
, i
);
642 callout_reset(&sc
->inttest
, hz
, digi_int_test
, sc
);
643 /* fepcmd_w(&sc->ports[0], 0xff, 0, 0); */
644 sc
->status
= DIGI_STATUS_ENABLED
;
650 digimctl(struct digi_p
*port
, int bits
, int how
)
655 port
->sc
->setwin(port
->sc
, 0);
656 mstat
= port
->bc
->mstat
;
657 port
->sc
->hidewin(port
->sc
);
659 if (mstat
& port
->sc
->csigs
->rts
)
661 if (mstat
& port
->cd
)
663 if (mstat
& port
->dsr
)
665 if (mstat
& port
->sc
->csigs
->cts
)
667 if (mstat
& port
->sc
->csigs
->ri
)
669 if (mstat
& port
->sc
->csigs
->dtr
)
674 /* Only DTR and RTS may be set */
676 if (bits
& TIOCM_DTR
)
677 mstat
|= port
->sc
->csigs
->dtr
;
678 if (bits
& TIOCM_RTS
)
679 mstat
|= port
->sc
->csigs
->rts
;
683 fepcmd_b(port
, SETMODEM
, mstat
, ~mstat
, 0);
686 fepcmd_b(port
, SETMODEM
, mstat
, 0, 0);
689 fepcmd_b(port
, SETMODEM
, 0, mstat
, 0);
697 digi_disc_optim(struct tty
*tp
, struct termios
*t
, struct digi_p
*port
)
699 if (!(t
->c_iflag
& (ICRNL
| IGNCR
| IMAXBEL
| INLCR
| ISTRIP
)) &&
700 (!(t
->c_iflag
& BRKINT
) || (t
->c_iflag
& IGNBRK
)) &&
701 (!(t
->c_iflag
& PARMRK
) ||
702 (t
->c_iflag
& (IGNPAR
| IGNBRK
)) == (IGNPAR
| IGNBRK
)) &&
703 !(t
->c_lflag
& (ECHO
| ICANON
| IEXTEN
| ISIG
| PENDIN
)) &&
704 linesw
[tp
->t_line
].l_rint
== ttyinput
)
705 tp
->t_state
|= TS_CAN_BYPASS_L_RINT
;
707 tp
->t_state
&= ~TS_CAN_BYPASS_L_RINT
;
711 digiopen(struct dev_open_args
*ap
)
713 cdev_t dev
= ap
->a_head
.a_dev
;
714 struct digi_softc
*sc
;
720 volatile struct board_chan
*bc
;
724 unit
= MINOR_TO_UNIT(minor(dev
));
725 pnum
= MINOR_TO_PORT(minor(dev
));
727 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
731 if (sc
->status
!= DIGI_STATUS_ENABLED
) {
732 DLOG(DIGIDB_OPEN
, (sc
->dev
, "Cannot open a disabled card\n"));
735 if (pnum
>= sc
->numports
) {
736 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port%d: Doesn't exist\n", pnum
));
739 if (mynor
& (CTRL_DEV
| CONTROL_MASK
)) {
743 port
= &sc
->ports
[pnum
];
744 tp
= dev
->si_tty
= port
->tp
;
750 while (port
->status
& DIGI_DTR_OFF
) {
752 error
= tsleep(&port
->dtr_wait
, PCATCH
, "digidtr", 0);
758 if (tp
->t_state
& TS_ISOPEN
) {
760 * The device is open, so everything has been initialized.
763 if (mynor
& CALLOUT_MASK
) {
764 if (!port
->active_out
) {
766 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port %d:"
767 " BUSY error = %d\n", pnum
, error
));
770 } else if (port
->active_out
) {
771 if (ap
->a_oflags
& O_NONBLOCK
) {
773 DLOG(DIGIDB_OPEN
, (sc
->dev
,
774 "port %d: BUSY error = %d\n", pnum
, error
));
778 error
= tsleep(&port
->active_out
, PCATCH
, "digibi", 0);
781 DLOG(DIGIDB_OPEN
, (sc
->dev
,
782 "port %d: tsleep(digibi) error = %d\n",
788 if (tp
->t_state
& TS_XCLUDE
&& suser_cred(ap
->a_cred
, 0) != 0) {
794 * The device isn't open, so there are no conflicts.
795 * Initialize it. Initialization is done twice in many
796 * cases: to preempt sleeping callin opens if we are callout,
797 * and to complete a callin open after DCD rises.
799 callout_init(&port
->wakeupco
);
800 tp
->t_oproc
= digistart
;
801 tp
->t_param
= digiparam
;
802 tp
->t_stop
= digistop
;
804 tp
->t_termios
= (mynor
& CALLOUT_MASK
) ?
805 port
->it_out
: port
->it_in
;
808 bc
->rout
= bc
->rin
; /* clear input queue */
812 bc
->mint
= port
->cd
| port
->sc
->csigs
->ri
;
815 port
->cd
= sc
->csigs
->dsr
;
816 port
->dsr
= sc
->csigs
->cd
;
818 port
->cd
= sc
->csigs
->cd
;
819 port
->dsr
= sc
->csigs
->dsr
;
821 port
->wopeners
++; /* XXX required ? */
822 error
= digiparam(tp
, &tp
->t_termios
);
826 DLOG(DIGIDB_OPEN
, (sc
->dev
,
827 "port %d: cxpparam error = %d\n", pnum
, error
));
832 /* handle fake and initial DCD for callout devices */
834 if (bc
->mstat
& port
->cd
|| mynor
& CALLOUT_MASK
)
835 linesw
[tp
->t_line
].l_modem(tp
, 1);
838 /* Wait for DCD if necessary */
839 if (!(tp
->t_state
& TS_CARR_ON
) && !(mynor
& CALLOUT_MASK
) &&
840 !(tp
->t_cflag
& CLOCAL
) && !(ap
->a_oflags
& O_NONBLOCK
)) {
842 error
= tsleep(TSA_CARR_ON(tp
), PCATCH
, "digidcd", 0);
845 DLOG(DIGIDB_OPEN
, (sc
->dev
,
846 "port %d: tsleep(digidcd) error = %d\n",
852 error
= linesw
[tp
->t_line
].l_open(dev
, tp
);
853 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port %d: l_open error = %d\n",
856 digi_disc_optim(tp
, &tp
->t_termios
, port
);
858 if (tp
->t_state
& TS_ISOPEN
&& mynor
& CALLOUT_MASK
)
859 port
->active_out
= TRUE
;
861 if (tp
->t_state
& TS_ISOPEN
)
866 if (!(tp
->t_state
& TS_ISOPEN
))
869 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port %d: open() returns %d\n",
876 digiclose(struct dev_close_args
*ap
)
878 cdev_t dev
= ap
->a_head
.a_dev
;
882 struct digi_softc
*sc
;
886 unit
= MINOR_TO_UNIT(mynor
);
887 pnum
= MINOR_TO_PORT(mynor
);
889 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
890 KASSERT(sc
, ("digi%d: softc not allocated in digiclose\n", unit
));
892 if (mynor
& (CTRL_DEV
| CONTROL_MASK
)) {
897 port
= sc
->ports
+ pnum
;
900 DLOG(DIGIDB_CLOSE
, (sc
->dev
, "port %d: closing\n", pnum
));
903 linesw
[tp
->t_line
].l_close(tp
, ap
->a_fflag
);
904 digi_disc_optim(tp
, &tp
->t_termios
, port
);
905 digistop(tp
, FREAD
| FWRITE
);
914 digidtrwakeup(void *chan
)
916 struct digi_p
*port
= chan
;
918 port
->status
&= ~DIGI_DTR_OFF
;
919 wakeup(&port
->dtr_wait
);
924 digihardclose(struct digi_p
*port
)
926 volatile struct board_chan
*bc
;
931 port
->sc
->setwin(port
->sc
, 0);
936 if ((port
->tp
->t_cflag
& HUPCL
) ||
937 (!port
->active_out
&& !(bc
->mstat
& port
->cd
) &&
938 !(port
->it_in
.c_cflag
& CLOCAL
)) ||
939 !(port
->tp
->t_state
& TS_ISOPEN
)) {
940 digimctl(port
, TIOCM_DTR
| TIOCM_RTS
, DMBIC
);
941 if (port
->dtr_wait
!= 0) {
942 /* Schedule a wakeup of any callin devices */
944 callout_reset(&port
->wakeupco
, port
->dtr_wait
,
945 digidtrwakeup
, port
);
946 port
->status
|= DIGI_DTR_OFF
;
949 port
->active_out
= FALSE
;
950 wakeup(&port
->active_out
);
951 wakeup(TSA_CARR_ON(port
->tp
));
956 digiread(struct dev_read_args
*ap
)
958 cdev_t dev
= ap
->a_head
.a_dev
;
961 int error
, unit
, pnum
;
962 struct digi_softc
*sc
;
965 if (mynor
& CONTROL_MASK
)
968 unit
= MINOR_TO_UNIT(mynor
);
969 pnum
= MINOR_TO_PORT(mynor
);
971 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
972 KASSERT(sc
, ("digi%d: softc not allocated in digiclose\n", unit
));
973 tp
= &sc
->ttys
[pnum
];
975 error
= linesw
[tp
->t_line
].l_read(tp
, ap
->a_uio
, ap
->a_ioflag
);
976 DLOG(DIGIDB_READ
, (sc
->dev
, "port %d: read() returns %d\n",
983 digiwrite(struct dev_write_args
*ap
)
985 cdev_t dev
= ap
->a_head
.a_dev
;
988 int error
, unit
, pnum
;
989 struct digi_softc
*sc
;
992 if (mynor
& CONTROL_MASK
)
995 unit
= MINOR_TO_UNIT(mynor
);
996 pnum
= MINOR_TO_PORT(mynor
);
998 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
999 KASSERT(sc
, ("digi%d: softc not allocated in digiclose\n", unit
));
1000 tp
= &sc
->ttys
[pnum
];
1002 error
= linesw
[tp
->t_line
].l_write(tp
, ap
->a_uio
, ap
->a_ioflag
);
1003 DLOG(DIGIDB_WRITE
, (sc
->dev
, "port %d: write() returns %d\n",
1010 * Load module "digi_<mod>.ko" and look for a symbol called digi_mod_<mod>.
1012 * Populate sc->bios, sc->fep, and sc->link from this data.
1014 * sc->fep.data, sc->bios.data and sc->link.data are malloc()d according
1015 * to their respective sizes.
1017 * The module is unloaded when we're done.
1020 digi_loaddata(struct digi_softc
*sc
)
1022 struct digi_bios
*bios
;
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"));
1029 for (bios
= digi_bioses
; bios
->model
!= NULL
; bios
++) {
1030 if (!strcmp(bios
->model
, sc
->module
))
1033 if (bios
->model
== NULL
) {
1034 kprintf("digi.ko: driver %s not found", sc
->module
);
1038 sc
->bios
.size
= bios
->bios_size
;
1039 if (sc
->bios
.size
!= 0 && bios
->bios
!= NULL
) {
1040 sc
->bios
.data
= kmalloc(sc
->bios
.size
, M_TTYS
, M_WAITOK
);
1041 bcopy(bios
->bios
, sc
->bios
.data
, sc
->bios
.size
);
1044 sc
->fep
.size
= bios
->fep_size
;
1045 if (sc
->fep
.size
!= 0 && bios
->fep
!= NULL
) {
1046 sc
->fep
.data
= kmalloc(sc
->fep
.size
, M_TTYS
, M_WAITOK
);
1047 bcopy(bios
->fep
, sc
->fep
.data
, sc
->fep
.size
);
1054 digiioctl(struct dev_ioctl_args
*ap
)
1056 cdev_t dev
= ap
->a_head
.a_dev
;
1057 u_long cmd
= ap
->a_cmd
;
1058 caddr_t data
= ap
->a_data
;
1059 int unit
, pnum
, mynor
, error
;
1060 struct digi_softc
*sc
;
1061 struct digi_p
*port
;
1063 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1065 struct termios term
;
1069 unit
= MINOR_TO_UNIT(mynor
);
1070 pnum
= MINOR_TO_PORT(mynor
);
1072 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1073 KASSERT(sc
, ("digi%d: softc not allocated in digiioctl\n", unit
));
1075 if (sc
->status
== DIGI_STATUS_DISABLED
)
1078 if (mynor
& CTRL_DEV
) {
1082 digi_debug
= *(int *)data
;
1085 device_printf(sc
->dev
, "DEBUG not defined\n");
1090 error
= digi_init(sc
);
1095 *(enum digi_model
*)data
= sc
->model
;
1099 return (copyout(sc
->name
, *(char **)data
,
1100 strlen(sc
->name
) + 1));
1104 if (pnum
>= sc
->numports
)
1107 port
= sc
->ports
+ pnum
;
1108 if (!(port
->status
& ENABLED
))
1113 if (mynor
& CONTROL_MASK
) {
1116 switch (mynor
& CONTROL_MASK
) {
1117 case CONTROL_INIT_STATE
:
1118 ct
= (mynor
& CALLOUT_MASK
) ?
1119 &port
->it_out
: &port
->it_in
;
1121 case CONTROL_LOCK_STATE
:
1122 ct
= (mynor
& CALLOUT_MASK
) ?
1123 &port
->lt_out
: &port
->lt_in
;
1126 return (ENODEV
); /* /dev/nodev */
1131 error
= suser_cred(ap
->a_cred
, 0);
1134 *ct
= *(struct termios
*)data
;
1138 *(struct termios
*)data
= *ct
;
1142 *(int *)data
= TTYDISC
;
1146 bzero(data
, sizeof(struct winsize
));
1149 case DIGIIO_GETALTPIN
:
1150 switch (mynor
& CONTROL_MASK
) {
1151 case CONTROL_INIT_STATE
:
1152 *(int *)data
= port
->ialtpin
;
1155 case CONTROL_LOCK_STATE
:
1156 *(int *)data
= port
->laltpin
;
1160 panic("Confusion when re-testing minor");
1165 case DIGIIO_SETALTPIN
:
1166 switch (mynor
& CONTROL_MASK
) {
1167 case CONTROL_INIT_STATE
:
1168 if (!port
->laltpin
) {
1169 port
->ialtpin
= !!*(int *)data
;
1170 DLOG(DIGIDB_SET
, (sc
->dev
,
1171 "port%d: initial ALTPIN %s\n", pnum
,
1172 port
->ialtpin
? "set" : "cleared"));
1176 case CONTROL_LOCK_STATE
:
1177 port
->laltpin
= !!*(int *)data
;
1178 DLOG(DIGIDB_SET
, (sc
->dev
,
1179 "port%d: ALTPIN %slocked\n",
1180 pnum
, port
->laltpin
? "" : "un"));
1184 panic("Confusion when re-testing minor");
1195 case DIGIIO_GETALTPIN
:
1196 *(int *)data
= !!(port
->dsr
== sc
->csigs
->cd
);
1199 case DIGIIO_SETALTPIN
:
1200 if (!port
->laltpin
) {
1202 DLOG(DIGIDB_SET
, (sc
->dev
,
1203 "port%d: ALTPIN set\n", pnum
));
1204 port
->cd
= sc
->csigs
->dsr
;
1205 port
->dsr
= sc
->csigs
->cd
;
1207 DLOG(DIGIDB_SET
, (sc
->dev
,
1208 "port%d: ALTPIN cleared\n", pnum
));
1209 port
->cd
= sc
->csigs
->cd
;
1210 port
->dsr
= sc
->csigs
->dsr
;
1217 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1218 term
= tp
->t_termios
;
1220 error
= ttsetcompat(tp
, &cmd
, data
, &term
);
1224 data
= (caddr_t
) & term
;
1226 if (cmd
== TIOCSETA
|| cmd
== TIOCSETAW
|| cmd
== TIOCSETAF
) {
1231 dt
= (struct termios
*)data
;
1232 lt
= (mynor
& CALLOUT_MASK
) ? &port
->lt_out
: &port
->lt_in
;
1235 (tp
->t_iflag
& lt
->c_iflag
) | (dt
->c_iflag
& ~lt
->c_iflag
);
1237 (tp
->t_oflag
& lt
->c_oflag
) | (dt
->c_oflag
& ~lt
->c_oflag
);
1239 (tp
->t_cflag
& lt
->c_cflag
) | (dt
->c_cflag
& ~lt
->c_cflag
);
1241 (tp
->t_lflag
& lt
->c_lflag
) | (dt
->c_lflag
& ~lt
->c_lflag
);
1242 port
->c_iflag
= dt
->c_iflag
& (IXOFF
| IXON
| IXANY
);
1243 dt
->c_iflag
&= ~(IXOFF
| IXON
| IXANY
);
1244 for (cc
= 0; cc
< NCCS
; ++cc
)
1245 if (lt
->c_cc
[cc
] != 0)
1246 dt
->c_cc
[cc
] = tp
->t_cc
[cc
];
1247 if (lt
->c_ispeed
!= 0)
1248 dt
->c_ispeed
= tp
->t_ispeed
;
1249 if (lt
->c_ospeed
!= 0)
1250 dt
->c_ospeed
= tp
->t_ospeed
;
1252 error
= linesw
[tp
->t_line
].l_ioctl(tp
, cmd
, data
,
1253 ap
->a_fflag
, ap
->a_cred
);
1254 if (error
== 0 && cmd
== TIOCGETA
)
1255 ((struct termios
*)data
)->c_iflag
|= port
->c_iflag
;
1257 if (error
>= 0 && error
!= ENOIOCTL
)
1260 error
= ttioctl(tp
, cmd
, data
, ap
->a_fflag
);
1261 if (error
== 0 && cmd
== TIOCGETA
)
1262 ((struct termios
*)data
)->c_iflag
|= port
->c_iflag
;
1264 digi_disc_optim(tp
, &tp
->t_termios
, port
);
1265 if (error
>= 0 && error
!= ENOIOCTL
) {
1272 port
->send_ring
= *(u_char
*)data
;
1276 * now it sends 400 millisecond break because I don't know
1277 * how to send an infinite break
1279 fepcmd_w(port
, SENDBREAK
, 400, 10);
1282 /* now it's empty */
1285 digimctl(port
, TIOCM_DTR
, DMBIS
);
1288 digimctl(port
, TIOCM_DTR
, DMBIC
);
1291 digimctl(port
, *(int *)data
, DMSET
);
1294 digimctl(port
, *(int *)data
, DMBIS
);
1297 digimctl(port
, *(int *)data
, DMBIC
);
1300 *(int *)data
= digimctl(port
, 0, DMGET
);
1303 error
= suser_cred(ap
->a_cred
, 0);
1308 port
->dtr_wait
= *(int *)data
*hz
/ 100;
1312 *(int *)data
= port
->dtr_wait
* 100 / hz
;
1314 #ifdef DIGI_INTERRUPT
1316 *(struct timeval
*)data
= sc
->intr_timestamp
;
1329 digiparam(struct tty
*tp
, struct termios
*t
)
1334 struct digi_softc
*sc
;
1335 struct digi_p
*port
;
1341 mynor
= minor(tp
->t_dev
);
1342 unit
= MINOR_TO_UNIT(mynor
);
1343 pnum
= MINOR_TO_PORT(mynor
);
1345 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1346 KASSERT(sc
, ("digi%d: softc not allocated in digiparam\n", unit
));
1348 port
= &sc
->ports
[pnum
];
1350 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: setting parameters\n", pnum
));
1352 if (t
->c_ispeed
== 0)
1353 t
->c_ispeed
= t
->c_ospeed
;
1355 cflag
= ttspeedtab(t
->c_ospeed
, digispeedtab
);
1357 if (cflag
< 0 || (cflag
> 0 && t
->c_ispeed
!= t
->c_ospeed
))
1362 window
= sc
->window
;
1365 if (cflag
== 0) { /* hangup */
1366 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: hangup\n", pnum
));
1367 digimctl(port
, TIOCM_DTR
| TIOCM_RTS
, DMBIC
);
1369 digimctl(port
, TIOCM_DTR
| TIOCM_RTS
, DMBIS
);
1371 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: CBAUD = %d\n", pnum
,
1375 /* convert flags to sysV-style values */
1376 if (t
->c_cflag
& PARODD
)
1378 if (t
->c_cflag
& PARENB
)
1380 if (t
->c_cflag
& CSTOPB
)
1383 /* convert flags to sysV-style values */
1384 if (t
->c_cflag
& PARODD
)
1385 cflag
|= FEP_PARODD
;
1386 if (t
->c_cflag
& PARENB
)
1387 cflag
|= FEP_PARENB
;
1388 if (t
->c_cflag
& CSTOPB
)
1389 cflag
|= FEP_CSTOPB
;
1390 if (t
->c_cflag
& CLOCAL
)
1391 cflag
|= FEP_CLOCAL
;
1394 cflag
|= (t
->c_cflag
& CSIZE
) >> 4;
1395 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: CFLAG = 0x%x\n", pnum
,
1397 fepcmd_w(port
, SETCFLAGS
, (unsigned)cflag
, 0);
1401 t
->c_iflag
& (IGNBRK
| BRKINT
| IGNPAR
| PARMRK
| INPCK
| ISTRIP
);
1402 if (port
->c_iflag
& IXON
)
1404 if (port
->c_iflag
& IXANY
)
1406 if (port
->c_iflag
& IXOFF
)
1409 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: set iflag = 0x%x\n", pnum
, iflag
));
1410 fepcmd_w(port
, SETIFLAGS
, (unsigned)iflag
, 0);
1413 if (t
->c_cflag
& CDTR_IFLOW
)
1414 hflow
|= sc
->csigs
->dtr
;
1415 if (t
->c_cflag
& CRTS_IFLOW
)
1416 hflow
|= sc
->csigs
->rts
;
1417 if (t
->c_cflag
& CCTS_OFLOW
)
1418 hflow
|= sc
->csigs
->cts
;
1419 if (t
->c_cflag
& CDSR_OFLOW
)
1421 if (t
->c_cflag
& CCAR_OFLOW
)
1424 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: set hflow = 0x%x\n", pnum
, hflow
));
1425 fepcmd_w(port
, SETHFLOW
, 0xff00 | (unsigned)hflow
, 0);
1427 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: set startc(0x%x), stopc(0x%x)\n",
1428 pnum
, t
->c_cc
[VSTART
], t
->c_cc
[VSTOP
]));
1429 fepcmd_b(port
, SONOFFC
, t
->c_cc
[VSTART
], t
->c_cc
[VSTOP
], 0);
1431 if (sc
->window
!= 0)
1434 sc
->towin(sc
, window
);
1443 struct digi_p
*port
;
1445 struct digi_softc
*sc
;
1447 volatile struct board_chan
*bc
;
1461 if (sc
->status
!= DIGI_STATUS_ENABLED
) {
1462 DLOG(DIGIDB_IRQ
, (sc
->dev
, "interrupt on disabled board !\n"));
1466 #ifdef DIGI_INTERRUPT
1467 microtime(&sc
->intr_timestamp
);
1470 window
= sc
->window
;
1473 if (sc
->model
>= PCXEM
&& W(sc
->vmem
+ 0xd00)) {
1474 struct con_bios
*con
= con_bios_list
;
1477 ptr
= sc
->vmem
+ W(sc
->vmem
+ 0xd00);
1479 if (ptr
[1] && W(ptr
+ 2) == W(con
->bios
+ 2))
1480 /* Not first block -- exact match */
1483 if (W(ptr
+ 4) >= W(con
->bios
+ 4) &&
1484 W(ptr
+ 4) <= W(con
->bios
+ 6))
1485 /* Initial search concetrator BIOS */
1490 log(LOG_ERR
, "digi%d: wanted bios LREV = 0x%04x"
1491 " not found!\n", sc
->res
.unit
, W(ptr
+ 4));
1493 W(sc
->vmem
+ 0xd00) = 0;
1497 W(ptr
+ 4) = W(cxcon
+ 4);
1498 W(ptr
+ 6) = W(cxcon
+ 6);
1500 W(ptr
+ 2) = W(cxcon
+ 2);
1501 W(ptr
+ 8) = (ptr
[1] << 6) + W(cxcon
+ 8);
1502 size
= W(cxcon
+ 10) - (ptr
[1] << 10);
1504 W(ptr
+ 8) = W(cxcon
+ 8);
1510 bcopy(cxcon
+ (ptr
[1] << 10), ptr
+ 12, size
);
1512 W(sc
->vmem
+ 0xd00) = 0;
1516 ehead
= sc
->gdata
->ein
;
1517 etail
= sc
->gdata
->eout
;
1518 if (ehead
== etail
) {
1521 if (sc
->intr_count
% 6000 == 0) {
1522 DLOG(DIGIDB_IRQ
, (sc
->dev
,
1523 "6000 useless polls %x %x\n", ehead
, etail
));
1529 while (ehead
!= etail
) {
1530 event
= *(volatile struct event
*)(sc
->memevent
+ etail
);
1532 etail
= (etail
+ 4) & sc
->gdata
->imax
;
1534 if (event
.pnum
>= sc
->numports
) {
1535 log(LOG_ERR
, "digi%d: port %d: got event"
1536 " on nonexisting port\n", sc
->res
.unit
,
1540 port
= &sc
->ports
[event
.pnum
];
1544 if (!(tp
->t_state
& TS_ISOPEN
) && !port
->wopeners
) {
1545 DLOG(DIGIDB_IRQ
, (sc
->dev
,
1546 "port %d: event 0x%x on closed port\n",
1547 event
.pnum
, event
.event
));
1555 if (event
.event
& ~ALL_IND
)
1556 log(LOG_ERR
, "digi%d: port%d: ? event 0x%x mstat 0x%x"
1557 " lstat 0x%x\n", sc
->res
.unit
, event
.pnum
,
1558 event
.event
, event
.mstat
, event
.lstat
);
1560 if (event
.event
& DATA_IND
) {
1561 DLOG(DIGIDB_IRQ
, (sc
->dev
, "port %d: DATA_IND\n",
1563 wrapmask
= port
->rxbufsize
- 1;
1568 if (!(tp
->t_state
& TS_ISOPEN
)) {
1572 while (head
!= tail
) {
1575 DLOG(DIGIDB_INT
, (sc
->dev
,
1576 "port %d: p rx head = %d tail = %d\n",
1577 event
.pnum
, head
, tail
));
1578 top
= (head
> tail
) ? head
: wrapmask
+ 1;
1579 sc
->towin(sc
, port
->rxwin
);
1581 if (tp
->t_state
& TS_CAN_BYPASS_L_RINT
) {
1582 size
= b_to_q((char *)port
->rxbuf
+
1583 tail
, size
, &tp
->t_rawq
);
1586 } else for (; tail
< top
;) {
1588 l_rint(port
->rxbuf
[tail
], tp
);
1589 sc
->towin(sc
, port
->rxwin
);
1592 if (tp
->t_state
& TS_TBLOCK
)
1604 CE_RECORD(port
, CE_OVERRUN
);
1605 log(LOG_ERR
, "digi%d: port%d: %s\n",
1606 sc
->res
.unit
, event
.pnum
,
1607 digi_errortxt(CE_OVERRUN
));
1612 tp
->t_state
|= TS_TBLOCK
;
1613 port
->status
|= PAUSE_RX
;
1614 DLOG(DIGIDB_RX
, (sc
->dev
, "port %d: pause RX\n",
1621 if (event
.event
& MODEMCHG_IND
) {
1622 DLOG(DIGIDB_MODEM
, (sc
->dev
, "port %d: MODEMCHG_IND\n",
1625 if ((event
.mstat
^ event
.lstat
) & port
->cd
) {
1627 linesw
[tp
->t_line
].l_modem
1628 (tp
, event
.mstat
& port
->cd
);
1630 wakeup(TSA_CARR_ON(tp
));
1633 if (event
.mstat
& sc
->csigs
->ri
) {
1634 DLOG(DIGIDB_RI
, (sc
->dev
, "port %d: RING\n",
1636 if (port
->send_ring
) {
1637 linesw
[tp
->t_line
].l_rint('R', tp
);
1638 linesw
[tp
->t_line
].l_rint('I', tp
);
1639 linesw
[tp
->t_line
].l_rint('N', tp
);
1640 linesw
[tp
->t_line
].l_rint('G', tp
);
1641 linesw
[tp
->t_line
].l_rint('\r', tp
);
1642 linesw
[tp
->t_line
].l_rint('\n', tp
);
1646 if (event
.event
& BREAK_IND
) {
1647 DLOG(DIGIDB_MODEM
, (sc
->dev
, "port %d: BREAK_IND\n",
1649 linesw
[tp
->t_line
].l_rint(TTY_BI
, tp
);
1651 if (event
.event
& (LOWTX_IND
| EMPTYTX_IND
)) {
1652 DLOG(DIGIDB_IRQ
, (sc
->dev
, "port %d:%s%s\n",
1654 event
.event
& LOWTX_IND
? " LOWTX" : "",
1655 event
.event
& EMPTYTX_IND
? " EMPTYTX" : ""));
1656 (*linesw
[tp
->t_line
].l_start
)(tp
);
1659 sc
->gdata
->eout
= etail
;
1661 if (sc
->window
!= 0)
1664 sc
->towin(sc
, window
);
1668 digistart(struct tty
*tp
)
1672 struct digi_p
*port
;
1673 struct digi_softc
*sc
;
1674 volatile struct board_chan
*bc
;
1676 int size
, ocount
, totcnt
= 0;
1679 unit
= MINOR_TO_UNIT(minor(tp
->t_dev
));
1680 pnum
= MINOR_TO_PORT(minor(tp
->t_dev
));
1682 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1683 KASSERT(sc
, ("digi%d: softc not allocated in digistart\n", unit
));
1685 port
= &sc
->ports
[pnum
];
1688 wmask
= port
->txbufsize
- 1;
1691 port
->lcc
= tp
->t_outq
.c_cc
;
1693 if (!(tp
->t_state
& TS_TBLOCK
)) {
1694 if (port
->status
& PAUSE_RX
) {
1695 DLOG(DIGIDB_RX
, (sc
->dev
, "port %d: resume RX\n",
1698 * CAREFUL - braces are needed here if the DLOG is
1702 port
->status
&= ~PAUSE_RX
;
1705 if (!(tp
->t_state
& TS_TTSTOP
) && port
->status
& PAUSE_TX
) {
1706 DLOG(DIGIDB_TX
, (sc
->dev
, "port %d: resume TX\n", pnum
));
1707 port
->status
&= ~PAUSE_TX
;
1708 fepcmd_w(port
, RESUMETX
, 0, 10);
1710 if (tp
->t_outq
.c_cc
== 0)
1711 tp
->t_state
&= ~TS_BUSY
;
1713 tp
->t_state
|= TS_BUSY
;
1716 while (tp
->t_outq
.c_cc
!= 0) {
1718 DLOG(DIGIDB_INT
, (sc
->dev
, "port%d: s tx head = %d tail = %d\n",
1722 size
= tail
- head
- 1;
1724 size
= port
->txbufsize
- head
;
1731 sc
->towin(sc
, port
->txwin
);
1732 ocount
= q_to_b(&tp
->t_outq
, port
->txbuf
+ head
, size
);
1741 port
->lostcc
= tp
->t_outq
.c_cc
;
1744 size
= port
->txbufsize
- tail
+ head
;
1749 DLOG(DIGIDB_INT
, (sc
->dev
, "port%d: s total cnt = %d\n", pnum
, totcnt
));
1755 digistop(struct tty
*tp
, int rw
)
1757 struct digi_softc
*sc
;
1760 struct digi_p
*port
;
1762 unit
= MINOR_TO_UNIT(minor(tp
->t_dev
));
1763 pnum
= MINOR_TO_PORT(minor(tp
->t_dev
));
1765 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1766 KASSERT(sc
, ("digi%d: softc not allocated in digistop\n", unit
));
1767 port
= sc
->ports
+ pnum
;
1769 DLOG(DIGIDB_TX
, (sc
->dev
, "port %d: pause TX\n", pnum
));
1770 port
->status
|= PAUSE_TX
;
1771 fepcmd_w(port
, PAUSETX
, 0, 10);
1775 fepcmd(struct digi_p
*port
, int cmd
, int op1
, int ncmds
)
1778 unsigned tail
, head
;
1781 mem
= port
->sc
->memcmd
;
1783 port
->sc
->setwin(port
->sc
, 0);
1785 head
= port
->sc
->gdata
->cin
;
1786 mem
[head
+ 0] = cmd
;
1787 mem
[head
+ 1] = port
->pnum
;
1788 *(u_short
*)(mem
+ head
+ 2) = op1
;
1790 head
= (head
+ 4) & port
->sc
->gdata
->cmax
;
1791 port
->sc
->gdata
->cin
= head
;
1793 for (count
= FEPTIMEOUT
; count
> 0; count
--) {
1794 head
= port
->sc
->gdata
->cin
;
1795 tail
= port
->sc
->gdata
->cout
;
1796 n
= (head
- tail
) & port
->sc
->gdata
->cmax
;
1798 if (n
<= ncmds
* sizeof(short) * 4)
1802 log(LOG_ERR
, "digi%d: port%d: timeout on FEP command\n",
1803 port
->sc
->res
.unit
, port
->pnum
);
1807 digi_errortxt(int id
)
1809 static const char *error_desc
[] = {
1811 "interrupt-level buffer overflow",
1812 "tty-level buffer overflow",
1815 KASSERT(id
>= 0 && id
< sizeof(error_desc
) / sizeof(error_desc
[0]),
1816 ("Unexpected digi error id %d\n", id
));
1818 return (error_desc
[id
]);
1822 digi_attach(struct digi_softc
*sc
)
1824 sc
->res
.ctldev
= make_dev(&digi_ops
,
1825 (sc
->res
.unit
<< 16) | CTRL_DEV
, UID_ROOT
, GID_WHEEL
,
1826 0600, "digi%r.ctl", sc
->res
.unit
);
1836 digi_inuse(struct digi_softc
*sc
)
1840 for (i
= 0; i
< sc
->numports
; i
++)
1841 if (sc
->ttys
[i
].t_state
& TS_ISOPEN
) {
1842 DLOG(DIGIDB_INIT
, (sc
->dev
, "port%d: busy\n", i
));
1844 } else if (sc
->ports
[i
].wopeners
|| sc
->ports
[i
].opencnt
) {
1845 DLOG(DIGIDB_INIT
, (sc
->dev
, "port%d: blocked in open\n",
1853 digi_free_state(struct digi_softc
*sc
)
1857 /* Blow it all away */
1859 for (i
= 0; i
< sc
->numports
; i
++)
1860 for (d
= 0; d
< 6; d
++)
1861 destroy_dev(sc
->ports
[i
].dev
[d
]);
1863 callout_stop(&sc
->callout
);
1864 callout_stop(&sc
->inttest
);
1866 bus_teardown_intr(sc
->dev
, sc
->res
.irq
, sc
->res
.irqHandler
);
1867 #ifdef DIGI_INTERRUPT
1868 if (sc
->res
.irq
!= NULL
) {
1869 bus_release_resource(dev
, SYS_RES_IRQ
, sc
->res
.irqrid
,
1875 KASSERT(sc
->ports
, ("digi%d: Lost my ports ?", sc
->res
.unit
));
1876 KASSERT(sc
->ttys
, ("digi%d: Lost my ttys ?", sc
->res
.unit
));
1877 kfree(sc
->ports
, M_TTYS
);
1879 kfree(sc
->ttys
, M_TTYS
);
1884 sc
->status
= DIGI_STATUS_NOTINIT
;
1888 digi_detach(device_t dev
)
1890 struct digi_softc
*sc
= device_get_softc(dev
);
1892 DLOG(DIGIDB_INIT
, (sc
->dev
, "detaching\n"));
1894 /* If we're INIT'd, numports must be 0 */
1895 KASSERT(sc
->numports
== 0 || sc
->status
!= DIGI_STATUS_NOTINIT
,
1896 ("digi%d: numports(%d) & status(%d) are out of sync",
1897 sc
->res
.unit
, sc
->numports
, (int)sc
->status
));
1902 digi_free_state(sc
);
1904 destroy_dev(sc
->res
.ctldev
);
1906 if (sc
->res
.mem
!= NULL
) {
1907 bus_release_resource(dev
, SYS_RES_MEMORY
, sc
->res
.mrid
,
1911 if (sc
->res
.io
!= NULL
) {
1912 bus_release_resource(dev
, SYS_RES_IOPORT
, sc
->res
.iorid
,
1921 digi_shutdown(device_t dev
)
1926 MODULE_VERSION(digi
, 1);