4 * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
5 * based on work by Slawa Olhovchenkov
6 * John Prince <johnp@knight-trosoft.com>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * $FreeBSD: src/sys/dev/digi/digi.c,v 1.36 2003/09/26 09:05:57 phk Exp $
36 * Figure out what the con bios stuff is supposed to do
37 * Test with *LOTS* more cards - I only have a PCI8r and an ISA Xem.
40 #include <sys/param.h>
41 #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>
53 #include <sys/thread2.h>
58 #include <dev/serial/digi/digiio.h>
59 #include <dev/serial/digi/digireg.h>
60 #include <dev/serial/digi/digi.h>
61 #include <dev/serial/digi/digi_pci.h>
62 #include <dev/serial/digi/digi_bios.h>
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
= {
148 .d_close
= digiclose
,
150 .d_write
= digiwrite
,
151 .d_ioctl
= digiioctl
,
152 .d_kqfilter
= ttykqfilter
,
153 .d_revoke
= ttyrevoke
159 struct digi_softc
*sc
;
161 sc
= (struct digi_softc
*)ptr
;
162 callout_init_mp(&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_mp(&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 * NOTE: Must be called with tty_token held
231 digi_init(struct digi_softc
*sc
)
237 volatile struct board_chan
*bc
;
239 ASSERT_LWKT_TOKEN_HELD(&tty_token
);
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 * NOTE: Must be called with tty_token held
657 digimctl(struct digi_p
*port
, int bits
, int how
)
661 ASSERT_LWKT_TOKEN_HELD(&tty_token
);
663 port
->sc
->setwin(port
->sc
, 0);
664 mstat
= port
->bc
->mstat
;
665 port
->sc
->hidewin(port
->sc
);
667 if (mstat
& port
->sc
->csigs
->rts
)
669 if (mstat
& port
->cd
)
671 if (mstat
& port
->dsr
)
673 if (mstat
& port
->sc
->csigs
->cts
)
675 if (mstat
& port
->sc
->csigs
->ri
)
677 if (mstat
& port
->sc
->csigs
->dtr
)
682 /* Only DTR and RTS may be set */
684 if (bits
& TIOCM_DTR
)
685 mstat
|= port
->sc
->csigs
->dtr
;
686 if (bits
& TIOCM_RTS
)
687 mstat
|= port
->sc
->csigs
->rts
;
691 fepcmd_b(port
, SETMODEM
, mstat
, ~mstat
, 0);
694 fepcmd_b(port
, SETMODEM
, mstat
, 0, 0);
697 fepcmd_b(port
, SETMODEM
, 0, mstat
, 0);
705 digi_disc_optim(struct tty
*tp
, struct termios
*t
, struct digi_p
*port
)
707 lwkt_gettoken(&tty_token
);
708 if (!(t
->c_iflag
& (ICRNL
| IGNCR
| IMAXBEL
| INLCR
| ISTRIP
)) &&
709 (!(t
->c_iflag
& BRKINT
) || (t
->c_iflag
& IGNBRK
)) &&
710 (!(t
->c_iflag
& PARMRK
) ||
711 (t
->c_iflag
& (IGNPAR
| IGNBRK
)) == (IGNPAR
| IGNBRK
)) &&
712 !(t
->c_lflag
& (ECHO
| ICANON
| IEXTEN
| ISIG
| PENDIN
)) &&
713 linesw
[tp
->t_line
].l_rint
== ttyinput
)
714 tp
->t_state
|= TS_CAN_BYPASS_L_RINT
;
716 tp
->t_state
&= ~TS_CAN_BYPASS_L_RINT
;
717 lwkt_reltoken(&tty_token
);
721 digiopen(struct dev_open_args
*ap
)
723 cdev_t dev
= ap
->a_head
.a_dev
;
724 struct digi_softc
*sc
;
730 volatile struct board_chan
*bc
;
734 unit
= MINOR_TO_UNIT(minor(dev
));
735 pnum
= MINOR_TO_PORT(minor(dev
));
737 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
741 lwkt_gettoken(&tty_token
);
742 if (sc
->status
!= DIGI_STATUS_ENABLED
) {
743 DLOG(DIGIDB_OPEN
, (sc
->dev
, "Cannot open a disabled card\n"));
744 lwkt_reltoken(&tty_token
);
747 if (pnum
>= sc
->numports
) {
748 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port%d: Doesn't exist\n", pnum
));
749 lwkt_reltoken(&tty_token
);
752 if (mynor
& (CTRL_DEV
| CONTROL_MASK
)) {
754 lwkt_reltoken(&tty_token
);
757 port
= &sc
->ports
[pnum
];
758 tp
= dev
->si_tty
= port
->tp
;
764 while (port
->status
& DIGI_DTR_OFF
) {
766 error
= tsleep(&port
->dtr_wait
, PCATCH
, "digidtr", 0);
772 if (tp
->t_state
& TS_ISOPEN
) {
774 * The device is open, so everything has been initialized.
777 if (mynor
& CALLOUT_MASK
) {
778 if (!port
->active_out
) {
780 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port %d:"
781 " BUSY error = %d\n", pnum
, error
));
784 } else if (port
->active_out
) {
785 if (ap
->a_oflags
& O_NONBLOCK
) {
787 DLOG(DIGIDB_OPEN
, (sc
->dev
,
788 "port %d: BUSY error = %d\n", pnum
, error
));
792 error
= tsleep(&port
->active_out
, PCATCH
, "digibi", 0);
795 DLOG(DIGIDB_OPEN
, (sc
->dev
,
796 "port %d: tsleep(digibi) error = %d\n",
802 if (tp
->t_state
& TS_XCLUDE
&& priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0) != 0) {
808 * The device isn't open, so there are no conflicts.
809 * Initialize it. Initialization is done twice in many
810 * cases: to preempt sleeping callin opens if we are callout,
811 * and to complete a callin open after DCD rises.
813 callout_init_mp(&port
->wakeupco
);
814 tp
->t_oproc
= digistart
;
815 tp
->t_param
= digiparam
;
816 tp
->t_stop
= digistop
;
818 tp
->t_termios
= (mynor
& CALLOUT_MASK
) ?
819 port
->it_out
: port
->it_in
;
822 bc
->rout
= bc
->rin
; /* clear input queue */
826 bc
->mint
= port
->cd
| port
->sc
->csigs
->ri
;
829 port
->cd
= sc
->csigs
->dsr
;
830 port
->dsr
= sc
->csigs
->cd
;
832 port
->cd
= sc
->csigs
->cd
;
833 port
->dsr
= sc
->csigs
->dsr
;
835 port
->wopeners
++; /* XXX required ? */
836 error
= digiparam(tp
, &tp
->t_termios
);
840 DLOG(DIGIDB_OPEN
, (sc
->dev
,
841 "port %d: cxpparam error = %d\n", pnum
, error
));
846 /* handle fake and initial DCD for callout devices */
848 if (bc
->mstat
& port
->cd
|| mynor
& CALLOUT_MASK
)
849 linesw
[tp
->t_line
].l_modem(tp
, 1);
852 /* Wait for DCD if necessary */
853 if (!(tp
->t_state
& TS_CARR_ON
) && !(mynor
& CALLOUT_MASK
) &&
854 !(tp
->t_cflag
& CLOCAL
) && !(ap
->a_oflags
& O_NONBLOCK
)) {
856 error
= tsleep(TSA_CARR_ON(tp
), PCATCH
, "digidcd", 0);
859 DLOG(DIGIDB_OPEN
, (sc
->dev
,
860 "port %d: tsleep(digidcd) error = %d\n",
866 error
= linesw
[tp
->t_line
].l_open(dev
, tp
);
867 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port %d: l_open error = %d\n",
870 digi_disc_optim(tp
, &tp
->t_termios
, port
);
872 if (tp
->t_state
& TS_ISOPEN
&& mynor
& CALLOUT_MASK
)
873 port
->active_out
= TRUE
;
875 if (tp
->t_state
& TS_ISOPEN
)
880 if (!(tp
->t_state
& TS_ISOPEN
))
883 DLOG(DIGIDB_OPEN
, (sc
->dev
, "port %d: open() returns %d\n",
886 lwkt_reltoken(&tty_token
);
891 digiclose(struct dev_close_args
*ap
)
893 cdev_t dev
= ap
->a_head
.a_dev
;
897 struct digi_softc
*sc
;
900 lwkt_gettoken(&tty_token
);
902 unit
= MINOR_TO_UNIT(mynor
);
903 pnum
= MINOR_TO_PORT(mynor
);
905 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
906 KASSERT(sc
, ("digi%d: softc not allocated in digiclose", unit
));
908 if (mynor
& (CTRL_DEV
| CONTROL_MASK
)) {
910 lwkt_reltoken(&tty_token
);
914 port
= sc
->ports
+ pnum
;
917 DLOG(DIGIDB_CLOSE
, (sc
->dev
, "port %d: closing\n", pnum
));
920 linesw
[tp
->t_line
].l_close(tp
, ap
->a_fflag
);
921 digi_disc_optim(tp
, &tp
->t_termios
, port
);
922 digistop(tp
, FREAD
| FWRITE
);
927 lwkt_reltoken(&tty_token
);
932 digidtrwakeup(void *chan
)
934 struct digi_p
*port
= chan
;
936 lwkt_gettoken(&tty_token
);
937 port
->status
&= ~DIGI_DTR_OFF
;
938 wakeup(&port
->dtr_wait
);
940 lwkt_reltoken(&tty_token
);
944 * NOTE: Must be called with tty_token held
947 digihardclose(struct digi_p
*port
)
949 volatile struct board_chan
*bc
;
951 ASSERT_LWKT_TOKEN_HELD(&tty_token
);
955 port
->sc
->setwin(port
->sc
, 0);
960 if ((port
->tp
->t_cflag
& HUPCL
) ||
961 (!port
->active_out
&& !(bc
->mstat
& port
->cd
) &&
962 !(port
->it_in
.c_cflag
& CLOCAL
)) ||
963 !(port
->tp
->t_state
& TS_ISOPEN
)) {
964 digimctl(port
, TIOCM_DTR
| TIOCM_RTS
, DMBIC
);
965 if (port
->dtr_wait
!= 0) {
966 /* Schedule a wakeup of any callin devices */
968 callout_reset(&port
->wakeupco
, port
->dtr_wait
,
969 digidtrwakeup
, port
);
970 port
->status
|= DIGI_DTR_OFF
;
973 port
->active_out
= FALSE
;
974 wakeup(&port
->active_out
);
975 wakeup(TSA_CARR_ON(port
->tp
));
980 digiread(struct dev_read_args
*ap
)
982 cdev_t dev
= ap
->a_head
.a_dev
;
985 int error
, unit
, pnum
;
986 struct digi_softc
*sc
;
989 if (mynor
& CONTROL_MASK
)
992 lwkt_gettoken(&tty_token
);
993 unit
= MINOR_TO_UNIT(mynor
);
994 pnum
= MINOR_TO_PORT(mynor
);
996 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
997 KASSERT(sc
, ("digi%d: softc not allocated in digiclose", unit
));
998 tp
= &sc
->ttys
[pnum
];
1000 error
= linesw
[tp
->t_line
].l_read(tp
, ap
->a_uio
, ap
->a_ioflag
);
1001 DLOG(DIGIDB_READ
, (sc
->dev
, "port %d: read() returns %d\n",
1004 lwkt_reltoken(&tty_token
);
1009 digiwrite(struct dev_write_args
*ap
)
1011 cdev_t dev
= ap
->a_head
.a_dev
;
1014 int error
, unit
, pnum
;
1015 struct digi_softc
*sc
;
1018 if (mynor
& CONTROL_MASK
)
1021 lwkt_gettoken(&tty_token
);
1022 unit
= MINOR_TO_UNIT(mynor
);
1023 pnum
= MINOR_TO_PORT(mynor
);
1025 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1026 KASSERT(sc
, ("digi%d: softc not allocated in digiclose", unit
));
1027 tp
= &sc
->ttys
[pnum
];
1029 error
= linesw
[tp
->t_line
].l_write(tp
, ap
->a_uio
, ap
->a_ioflag
);
1030 DLOG(DIGIDB_WRITE
, (sc
->dev
, "port %d: write() returns %d\n",
1033 lwkt_reltoken(&tty_token
);
1038 * Load module "digi_<mod>.ko" and look for a symbol called digi_mod_<mod>.
1040 * Populate sc->bios, sc->fep, and sc->link from this data.
1042 * sc->fep.data, sc->bios.data and sc->link.data are malloc()d according
1043 * to their respective sizes.
1045 * The module is unloaded when we're done.
1048 digi_loaddata(struct digi_softc
*sc
)
1050 struct digi_bios
*bios
;
1052 KASSERT(sc
->bios
.data
== NULL
, ("Uninitialised BIOS variable"));
1053 KASSERT(sc
->fep
.data
== NULL
, ("Uninitialised FEP variable"));
1054 KASSERT(sc
->link
.data
== NULL
, ("Uninitialised LINK variable"));
1055 KASSERT(sc
->module
!= NULL
, ("Uninitialised module name"));
1057 for (bios
= digi_bioses
; bios
->model
!= NULL
; bios
++) {
1058 if (!strcmp(bios
->model
, sc
->module
))
1061 if (bios
->model
== NULL
) {
1062 kprintf("digi.ko: driver %s not found", sc
->module
);
1066 sc
->bios
.size
= bios
->bios_size
;
1067 if (sc
->bios
.size
!= 0 && bios
->bios
!= NULL
) {
1068 sc
->bios
.data
= kmalloc(sc
->bios
.size
, M_TTYS
, M_WAITOK
);
1069 bcopy(bios
->bios
, sc
->bios
.data
, sc
->bios
.size
);
1072 sc
->fep
.size
= bios
->fep_size
;
1073 if (sc
->fep
.size
!= 0 && bios
->fep
!= NULL
) {
1074 sc
->fep
.data
= kmalloc(sc
->fep
.size
, M_TTYS
, M_WAITOK
);
1075 bcopy(bios
->fep
, sc
->fep
.data
, sc
->fep
.size
);
1082 digiioctl(struct dev_ioctl_args
*ap
)
1084 cdev_t dev
= ap
->a_head
.a_dev
;
1085 u_long cmd
= ap
->a_cmd
;
1086 caddr_t data
= ap
->a_data
;
1087 int unit
, pnum
, mynor
, error
, ret
;
1088 struct digi_softc
*sc
;
1089 struct digi_p
*port
;
1093 unit
= MINOR_TO_UNIT(mynor
);
1094 pnum
= MINOR_TO_PORT(mynor
);
1096 lwkt_gettoken(&tty_token
);
1097 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1098 KASSERT(sc
, ("digi%d: softc not allocated in digiioctl", unit
));
1100 if (sc
->status
== DIGI_STATUS_DISABLED
) {
1101 lwkt_reltoken(&tty_token
);
1105 if (mynor
& CTRL_DEV
) {
1109 digi_debug
= *(int *)data
;
1110 lwkt_reltoken(&tty_token
);
1113 device_printf(sc
->dev
, "DEBUG not defined\n");
1114 lwkt_reltoken(&tty_token
);
1119 error
= digi_init(sc
);
1121 lwkt_reltoken(&tty_token
);
1125 *(enum digi_model
*)data
= sc
->model
;
1126 lwkt_reltoken(&tty_token
);
1130 ret
= copyout(sc
->name
, *(char **)data
,
1131 strlen(sc
->name
) + 1);
1132 lwkt_reltoken(&tty_token
);
1137 if (pnum
>= sc
->numports
) {
1138 lwkt_reltoken(&tty_token
);
1142 port
= sc
->ports
+ pnum
;
1143 if (!(port
->status
& ENABLED
)) {
1144 lwkt_reltoken(&tty_token
);
1150 if (mynor
& CONTROL_MASK
) {
1153 switch (mynor
& CONTROL_MASK
) {
1154 case CONTROL_INIT_STATE
:
1155 ct
= (mynor
& CALLOUT_MASK
) ?
1156 &port
->it_out
: &port
->it_in
;
1158 case CONTROL_LOCK_STATE
:
1159 ct
= (mynor
& CALLOUT_MASK
) ?
1160 &port
->lt_out
: &port
->lt_in
;
1163 lwkt_reltoken(&tty_token
);
1164 return (ENODEV
); /* /dev/nodev */
1169 error
= priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0);
1171 lwkt_reltoken(&tty_token
);
1174 *ct
= *(struct termios
*)data
;
1175 lwkt_reltoken(&tty_token
);
1179 *(struct termios
*)data
= *ct
;
1180 lwkt_reltoken(&tty_token
);
1184 *(int *)data
= TTYDISC
;
1185 lwkt_reltoken(&tty_token
);
1189 bzero(data
, sizeof(struct winsize
));
1190 lwkt_reltoken(&tty_token
);
1193 case DIGIIO_GETALTPIN
:
1194 switch (mynor
& CONTROL_MASK
) {
1195 case CONTROL_INIT_STATE
:
1196 *(int *)data
= port
->ialtpin
;
1199 case CONTROL_LOCK_STATE
:
1200 *(int *)data
= port
->laltpin
;
1204 panic("Confusion when re-testing minor");
1205 lwkt_reltoken(&tty_token
);
1208 lwkt_reltoken(&tty_token
);
1211 case DIGIIO_SETALTPIN
:
1212 switch (mynor
& CONTROL_MASK
) {
1213 case CONTROL_INIT_STATE
:
1214 if (!port
->laltpin
) {
1215 port
->ialtpin
= !!*(int *)data
;
1216 DLOG(DIGIDB_SET
, (sc
->dev
,
1217 "port%d: initial ALTPIN %s\n", pnum
,
1218 port
->ialtpin
? "set" : "cleared"));
1222 case CONTROL_LOCK_STATE
:
1223 port
->laltpin
= !!*(int *)data
;
1224 DLOG(DIGIDB_SET
, (sc
->dev
,
1225 "port%d: ALTPIN %slocked\n",
1226 pnum
, port
->laltpin
? "" : "un"));
1230 panic("Confusion when re-testing minor");
1231 lwkt_reltoken(&tty_token
);
1234 lwkt_reltoken(&tty_token
);
1238 lwkt_reltoken(&tty_token
);
1244 case DIGIIO_GETALTPIN
:
1245 *(int *)data
= !!(port
->dsr
== sc
->csigs
->cd
);
1246 lwkt_reltoken(&tty_token
);
1249 case DIGIIO_SETALTPIN
:
1250 if (!port
->laltpin
) {
1252 DLOG(DIGIDB_SET
, (sc
->dev
,
1253 "port%d: ALTPIN set\n", pnum
));
1254 port
->cd
= sc
->csigs
->dsr
;
1255 port
->dsr
= sc
->csigs
->cd
;
1257 DLOG(DIGIDB_SET
, (sc
->dev
,
1258 "port%d: ALTPIN cleared\n", pnum
));
1259 port
->cd
= sc
->csigs
->cd
;
1260 port
->dsr
= sc
->csigs
->dsr
;
1263 lwkt_reltoken(&tty_token
);
1268 if (cmd
== TIOCSETA
|| cmd
== TIOCSETAW
|| cmd
== TIOCSETAF
) {
1273 dt
= (struct termios
*)data
;
1274 lt
= (mynor
& CALLOUT_MASK
) ? &port
->lt_out
: &port
->lt_in
;
1277 (tp
->t_iflag
& lt
->c_iflag
) | (dt
->c_iflag
& ~lt
->c_iflag
);
1279 (tp
->t_oflag
& lt
->c_oflag
) | (dt
->c_oflag
& ~lt
->c_oflag
);
1281 (tp
->t_cflag
& lt
->c_cflag
) | (dt
->c_cflag
& ~lt
->c_cflag
);
1283 (tp
->t_lflag
& lt
->c_lflag
) | (dt
->c_lflag
& ~lt
->c_lflag
);
1284 port
->c_iflag
= dt
->c_iflag
& (IXOFF
| IXON
| IXANY
);
1285 dt
->c_iflag
&= ~(IXOFF
| IXON
| IXANY
);
1286 for (cc
= 0; cc
< NCCS
; ++cc
)
1287 if (lt
->c_cc
[cc
] != 0)
1288 dt
->c_cc
[cc
] = tp
->t_cc
[cc
];
1289 if (lt
->c_ispeed
!= 0)
1290 dt
->c_ispeed
= tp
->t_ispeed
;
1291 if (lt
->c_ospeed
!= 0)
1292 dt
->c_ospeed
= tp
->t_ospeed
;
1294 error
= linesw
[tp
->t_line
].l_ioctl(tp
, cmd
, data
,
1295 ap
->a_fflag
, ap
->a_cred
);
1296 if (error
== 0 && cmd
== TIOCGETA
)
1297 ((struct termios
*)data
)->c_iflag
|= port
->c_iflag
;
1299 if (error
>= 0 && error
!= ENOIOCTL
) {
1300 lwkt_reltoken(&tty_token
);
1304 error
= ttioctl(tp
, cmd
, data
, ap
->a_fflag
);
1305 if (error
== 0 && cmd
== TIOCGETA
)
1306 ((struct termios
*)data
)->c_iflag
|= port
->c_iflag
;
1308 digi_disc_optim(tp
, &tp
->t_termios
, port
);
1309 if (error
>= 0 && error
!= ENOIOCTL
) {
1311 lwkt_reltoken(&tty_token
);
1317 port
->send_ring
= *(u_char
*)data
;
1321 * now it sends 400 millisecond break because I don't know
1322 * how to send an infinite break
1324 fepcmd_w(port
, SENDBREAK
, 400, 10);
1327 /* now it's empty */
1330 digimctl(port
, TIOCM_DTR
, DMBIS
);
1333 digimctl(port
, TIOCM_DTR
, DMBIC
);
1336 digimctl(port
, *(int *)data
, DMSET
);
1339 digimctl(port
, *(int *)data
, DMBIS
);
1342 digimctl(port
, *(int *)data
, DMBIC
);
1345 *(int *)data
= digimctl(port
, 0, DMGET
);
1348 error
= priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0);
1351 lwkt_reltoken(&tty_token
);
1354 port
->dtr_wait
= *(int *)data
*hz
/ 100;
1358 *(int *)data
= port
->dtr_wait
* 100 / hz
;
1360 #ifdef DIGI_INTERRUPT
1362 *(struct timeval
*)data
= sc
->intr_timestamp
;
1368 lwkt_reltoken(&tty_token
);
1372 lwkt_reltoken(&tty_token
);
1377 digiparam(struct tty
*tp
, struct termios
*t
)
1382 struct digi_softc
*sc
;
1383 struct digi_p
*port
;
1389 lwkt_gettoken(&tty_token
);
1390 mynor
= minor(tp
->t_dev
);
1391 unit
= MINOR_TO_UNIT(mynor
);
1392 pnum
= MINOR_TO_PORT(mynor
);
1394 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1395 KASSERT(sc
, ("digi%d: softc not allocated in digiparam", unit
));
1397 port
= &sc
->ports
[pnum
];
1399 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: setting parameters\n", pnum
));
1401 if (t
->c_ispeed
== 0)
1402 t
->c_ispeed
= t
->c_ospeed
;
1404 cflag
= ttspeedtab(t
->c_ospeed
, digispeedtab
);
1406 if (cflag
< 0 || (cflag
> 0 && t
->c_ispeed
!= t
->c_ospeed
)) {
1407 lwkt_reltoken(&tty_token
);
1413 window
= sc
->window
;
1416 if (cflag
== 0) { /* hangup */
1417 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: hangup\n", pnum
));
1418 digimctl(port
, TIOCM_DTR
| TIOCM_RTS
, DMBIC
);
1420 digimctl(port
, TIOCM_DTR
| TIOCM_RTS
, DMBIS
);
1422 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: CBAUD = %d\n", pnum
,
1426 /* convert flags to sysV-style values */
1427 if (t
->c_cflag
& PARODD
)
1429 if (t
->c_cflag
& PARENB
)
1431 if (t
->c_cflag
& CSTOPB
)
1434 /* convert flags to sysV-style values */
1435 if (t
->c_cflag
& PARODD
)
1436 cflag
|= FEP_PARODD
;
1437 if (t
->c_cflag
& PARENB
)
1438 cflag
|= FEP_PARENB
;
1439 if (t
->c_cflag
& CSTOPB
)
1440 cflag
|= FEP_CSTOPB
;
1441 if (t
->c_cflag
& CLOCAL
)
1442 cflag
|= FEP_CLOCAL
;
1445 cflag
|= (t
->c_cflag
& CSIZE
) >> 4;
1446 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: CFLAG = 0x%x\n", pnum
,
1448 fepcmd_w(port
, SETCFLAGS
, (unsigned)cflag
, 0);
1452 t
->c_iflag
& (IGNBRK
| BRKINT
| IGNPAR
| PARMRK
| INPCK
| ISTRIP
);
1453 if (port
->c_iflag
& IXON
)
1455 if (port
->c_iflag
& IXANY
)
1457 if (port
->c_iflag
& IXOFF
)
1460 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: set iflag = 0x%x\n", pnum
, iflag
));
1461 fepcmd_w(port
, SETIFLAGS
, (unsigned)iflag
, 0);
1464 if (t
->c_cflag
& CDTR_IFLOW
)
1465 hflow
|= sc
->csigs
->dtr
;
1466 if (t
->c_cflag
& CRTS_IFLOW
)
1467 hflow
|= sc
->csigs
->rts
;
1468 if (t
->c_cflag
& CCTS_OFLOW
)
1469 hflow
|= sc
->csigs
->cts
;
1470 if (t
->c_cflag
& CDSR_OFLOW
)
1472 if (t
->c_cflag
& CCAR_OFLOW
)
1475 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: set hflow = 0x%x\n", pnum
, hflow
));
1476 fepcmd_w(port
, SETHFLOW
, 0xff00 | (unsigned)hflow
, 0);
1478 DLOG(DIGIDB_SET
, (sc
->dev
, "port%d: set startc(0x%x), stopc(0x%x)\n",
1479 pnum
, t
->c_cc
[VSTART
], t
->c_cc
[VSTOP
]));
1480 fepcmd_b(port
, SONOFFC
, t
->c_cc
[VSTART
], t
->c_cc
[VSTOP
], 0);
1482 if (sc
->window
!= 0)
1485 sc
->towin(sc
, window
);
1488 lwkt_reltoken(&tty_token
);
1495 struct digi_p
*port
;
1497 struct digi_softc
*sc
;
1499 volatile struct board_chan
*bc
;
1511 lwkt_gettoken(&tty_token
);
1514 if (sc
->status
!= DIGI_STATUS_ENABLED
) {
1515 DLOG(DIGIDB_IRQ
, (sc
->dev
, "interrupt on disabled board !\n"));
1516 lwkt_reltoken(&tty_token
);
1520 #ifdef DIGI_INTERRUPT
1521 microtime(&sc
->intr_timestamp
);
1524 window
= sc
->window
;
1527 if (sc
->model
>= PCXEM
&& W(sc
->vmem
+ 0xd00)) {
1528 struct con_bios
*con
= con_bios_list
;
1531 ptr
= sc
->vmem
+ W(sc
->vmem
+ 0xd00);
1533 if (ptr
[1] && W(ptr
+ 2) == W(con
->bios
+ 2))
1534 /* Not first block -- exact match */
1537 if (W(ptr
+ 4) >= W(con
->bios
+ 4) &&
1538 W(ptr
+ 4) <= W(con
->bios
+ 6))
1539 /* Initial search concetrator BIOS */
1544 log(LOG_ERR
, "digi%d: wanted bios LREV = 0x%04x"
1545 " not found!\n", sc
->res
.unit
, W(ptr
+ 4));
1547 W(sc
->vmem
+ 0xd00) = 0;
1551 W(ptr
+ 4) = W(cxcon
+ 4);
1552 W(ptr
+ 6) = W(cxcon
+ 6);
1554 W(ptr
+ 2) = W(cxcon
+ 2);
1555 W(ptr
+ 8) = (ptr
[1] << 6) + W(cxcon
+ 8);
1556 size
= W(cxcon
+ 10) - (ptr
[1] << 10);
1558 W(ptr
+ 8) = W(cxcon
+ 8);
1564 bcopy(cxcon
+ (ptr
[1] << 10), ptr
+ 12, size
);
1566 W(sc
->vmem
+ 0xd00) = 0;
1570 ehead
= sc
->gdata
->ein
;
1571 etail
= sc
->gdata
->eout
;
1572 if (ehead
== etail
) {
1575 if (sc
->intr_count
% 6000 == 0) {
1576 DLOG(DIGIDB_IRQ
, (sc
->dev
,
1577 "6000 useless polls %x %x\n", ehead
, etail
));
1583 while (ehead
!= etail
) {
1584 event
= *(volatile struct event
*)(sc
->memevent
+ etail
);
1586 etail
= (etail
+ 4) & sc
->gdata
->imax
;
1588 if (event
.pnum
>= sc
->numports
) {
1589 log(LOG_ERR
, "digi%d: port %d: got event"
1590 " on nonexisting port\n", sc
->res
.unit
,
1594 port
= &sc
->ports
[event
.pnum
];
1598 if (!(tp
->t_state
& TS_ISOPEN
) && !port
->wopeners
) {
1599 DLOG(DIGIDB_IRQ
, (sc
->dev
,
1600 "port %d: event 0x%x on closed port\n",
1601 event
.pnum
, event
.event
));
1609 if (event
.event
& ~ALL_IND
)
1610 log(LOG_ERR
, "digi%d: port%d: ? event 0x%x mstat 0x%x"
1611 " lstat 0x%x\n", sc
->res
.unit
, event
.pnum
,
1612 event
.event
, event
.mstat
, event
.lstat
);
1614 if (event
.event
& DATA_IND
) {
1615 DLOG(DIGIDB_IRQ
, (sc
->dev
, "port %d: DATA_IND\n",
1617 wrapmask
= port
->rxbufsize
- 1;
1622 if (!(tp
->t_state
& TS_ISOPEN
)) {
1626 while (head
!= tail
) {
1629 DLOG(DIGIDB_INT
, (sc
->dev
,
1630 "port %d: p rx head = %d tail = %d\n",
1631 event
.pnum
, head
, tail
));
1632 top
= (head
> tail
) ? head
: wrapmask
+ 1;
1633 sc
->towin(sc
, port
->rxwin
);
1635 if (tp
->t_state
& TS_CAN_BYPASS_L_RINT
) {
1636 size
= b_to_q((char *)port
->rxbuf
+
1637 tail
, size
, &tp
->t_rawq
);
1640 } else for (; tail
< top
;) {
1642 l_rint(port
->rxbuf
[tail
], tp
);
1643 sc
->towin(sc
, port
->rxwin
);
1646 if (tp
->t_state
& TS_TBLOCK
)
1658 CE_RECORD(port
, CE_OVERRUN
);
1659 log(LOG_ERR
, "digi%d: port%d: %s\n",
1660 sc
->res
.unit
, event
.pnum
,
1661 digi_errortxt(CE_OVERRUN
));
1666 tp
->t_state
|= TS_TBLOCK
;
1667 port
->status
|= PAUSE_RX
;
1668 DLOG(DIGIDB_RX
, (sc
->dev
, "port %d: pause RX\n",
1675 if (event
.event
& MODEMCHG_IND
) {
1676 DLOG(DIGIDB_MODEM
, (sc
->dev
, "port %d: MODEMCHG_IND\n",
1679 if ((event
.mstat
^ event
.lstat
) & port
->cd
) {
1681 linesw
[tp
->t_line
].l_modem
1682 (tp
, event
.mstat
& port
->cd
);
1684 wakeup(TSA_CARR_ON(tp
));
1687 if (event
.mstat
& sc
->csigs
->ri
) {
1688 DLOG(DIGIDB_RI
, (sc
->dev
, "port %d: RING\n",
1690 if (port
->send_ring
) {
1691 linesw
[tp
->t_line
].l_rint('R', tp
);
1692 linesw
[tp
->t_line
].l_rint('I', tp
);
1693 linesw
[tp
->t_line
].l_rint('N', tp
);
1694 linesw
[tp
->t_line
].l_rint('G', tp
);
1695 linesw
[tp
->t_line
].l_rint('\r', tp
);
1696 linesw
[tp
->t_line
].l_rint('\n', tp
);
1700 if (event
.event
& BREAK_IND
) {
1701 DLOG(DIGIDB_MODEM
, (sc
->dev
, "port %d: BREAK_IND\n",
1703 linesw
[tp
->t_line
].l_rint(TTY_BI
, tp
);
1705 if (event
.event
& (LOWTX_IND
| EMPTYTX_IND
)) {
1706 DLOG(DIGIDB_IRQ
, (sc
->dev
, "port %d:%s%s\n",
1708 event
.event
& LOWTX_IND
? " LOWTX" : "",
1709 event
.event
& EMPTYTX_IND
? " EMPTYTX" : ""));
1710 (*linesw
[tp
->t_line
].l_start
)(tp
);
1713 sc
->gdata
->eout
= etail
;
1715 if (sc
->window
!= 0)
1718 sc
->towin(sc
, window
);
1719 lwkt_reltoken(&tty_token
);
1723 digistart(struct tty
*tp
)
1727 struct digi_p
*port
;
1728 struct digi_softc
*sc
;
1729 volatile struct board_chan
*bc
;
1731 int size
, ocount
, totcnt
= 0;
1734 lwkt_gettoken(&tty_token
);
1735 unit
= MINOR_TO_UNIT(minor(tp
->t_dev
));
1736 pnum
= MINOR_TO_PORT(minor(tp
->t_dev
));
1738 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1739 KASSERT(sc
, ("digi%d: softc not allocated in digistart", unit
));
1741 port
= &sc
->ports
[pnum
];
1744 wmask
= port
->txbufsize
- 1;
1747 port
->lcc
= tp
->t_outq
.c_cc
;
1749 if (!(tp
->t_state
& TS_TBLOCK
)) {
1750 if (port
->status
& PAUSE_RX
) {
1751 DLOG(DIGIDB_RX
, (sc
->dev
, "port %d: resume RX\n",
1754 * CAREFUL - braces are needed here if the DLOG is
1758 port
->status
&= ~PAUSE_RX
;
1761 if (!(tp
->t_state
& TS_TTSTOP
) && port
->status
& PAUSE_TX
) {
1762 DLOG(DIGIDB_TX
, (sc
->dev
, "port %d: resume TX\n", pnum
));
1763 port
->status
&= ~PAUSE_TX
;
1764 fepcmd_w(port
, RESUMETX
, 0, 10);
1766 if (tp
->t_outq
.c_cc
== 0)
1767 tp
->t_state
&= ~TS_BUSY
;
1769 tp
->t_state
|= TS_BUSY
;
1772 while (tp
->t_outq
.c_cc
!= 0) {
1774 DLOG(DIGIDB_INT
, (sc
->dev
, "port%d: s tx head = %d tail = %d\n",
1778 size
= tail
- head
- 1;
1780 size
= port
->txbufsize
- head
;
1787 sc
->towin(sc
, port
->txwin
);
1788 ocount
= q_to_b(&tp
->t_outq
, port
->txbuf
+ head
, size
);
1797 port
->lostcc
= tp
->t_outq
.c_cc
;
1800 size
= port
->txbufsize
- tail
+ head
;
1805 DLOG(DIGIDB_INT
, (sc
->dev
, "port%d: s total cnt = %d\n", pnum
, totcnt
));
1808 lwkt_reltoken(&tty_token
);
1812 digistop(struct tty
*tp
, int rw
)
1814 struct digi_softc
*sc
;
1817 struct digi_p
*port
;
1819 lwkt_gettoken(&tty_token
);
1820 unit
= MINOR_TO_UNIT(minor(tp
->t_dev
));
1821 pnum
= MINOR_TO_PORT(minor(tp
->t_dev
));
1823 sc
= (struct digi_softc
*)devclass_get_softc(digi_devclass
, unit
);
1824 KASSERT(sc
, ("digi%d: softc not allocated in digistop", unit
));
1825 port
= sc
->ports
+ pnum
;
1827 DLOG(DIGIDB_TX
, (sc
->dev
, "port %d: pause TX\n", pnum
));
1828 port
->status
|= PAUSE_TX
;
1829 fepcmd_w(port
, PAUSETX
, 0, 10);
1830 lwkt_reltoken(&tty_token
);
1834 * NOTE: Must be called with tty_token held
1837 fepcmd(struct digi_p
*port
, int cmd
, int op1
, int ncmds
)
1840 unsigned tail
, head
;
1843 ASSERT_LWKT_TOKEN_HELD(&tty_token
);
1844 mem
= port
->sc
->memcmd
;
1846 port
->sc
->setwin(port
->sc
, 0);
1848 head
= port
->sc
->gdata
->cin
;
1849 mem
[head
+ 0] = cmd
;
1850 mem
[head
+ 1] = port
->pnum
;
1851 *(u_short
*)(mem
+ head
+ 2) = op1
;
1853 head
= (head
+ 4) & port
->sc
->gdata
->cmax
;
1854 port
->sc
->gdata
->cin
= head
;
1856 for (count
= FEPTIMEOUT
; count
> 0; count
--) {
1857 head
= port
->sc
->gdata
->cin
;
1858 tail
= port
->sc
->gdata
->cout
;
1859 n
= (head
- tail
) & port
->sc
->gdata
->cmax
;
1861 if (n
<= ncmds
* sizeof(short) * 4)
1865 log(LOG_ERR
, "digi%d: port%d: timeout on FEP command\n",
1866 port
->sc
->res
.unit
, port
->pnum
);
1870 digi_errortxt(int id
)
1872 static const char *error_desc
[] = {
1874 "interrupt-level buffer overflow",
1875 "tty-level buffer overflow",
1878 KASSERT(id
>= 0 && id
< NELEM(error_desc
),
1879 ("Unexpected digi error id %d\n", id
));
1881 return (error_desc
[id
]);
1885 digi_attach(struct digi_softc
*sc
)
1887 lwkt_gettoken(&tty_token
);
1888 sc
->res
.ctldev
= make_dev(&digi_ops
,
1889 (sc
->res
.unit
<< 16) | CTRL_DEV
, UID_ROOT
, GID_WHEEL
,
1890 0600, "digi%r.ctl", sc
->res
.unit
);
1896 lwkt_reltoken(&tty_token
);
1901 * NOTE: Must be called with tty_token held
1904 digi_inuse(struct digi_softc
*sc
)
1908 ASSERT_LWKT_TOKEN_HELD(&tty_token
);
1909 for (i
= 0; i
< sc
->numports
; i
++)
1910 if (sc
->ttys
[i
].t_state
& TS_ISOPEN
) {
1911 DLOG(DIGIDB_INIT
, (sc
->dev
, "port%d: busy\n", i
));
1913 } else if (sc
->ports
[i
].wopeners
|| sc
->ports
[i
].opencnt
) {
1914 DLOG(DIGIDB_INIT
, (sc
->dev
, "port%d: blocked in open\n",
1922 * NOTE: Must be called with tty_token held
1925 digi_free_state(struct digi_softc
*sc
)
1929 ASSERT_LWKT_TOKEN_HELD(&tty_token
);
1930 /* Blow it all away */
1932 for (i
= 0; i
< sc
->numports
; i
++)
1933 for (d
= 0; d
< 6; d
++)
1934 destroy_dev(sc
->ports
[i
].dev
[d
]);
1936 callout_stop(&sc
->callout
);
1937 callout_stop(&sc
->inttest
);
1939 bus_teardown_intr(sc
->dev
, sc
->res
.irq
, sc
->res
.irqHandler
);
1940 #ifdef DIGI_INTERRUPT
1941 if (sc
->res
.irq
!= NULL
) {
1942 bus_release_resource(dev
, SYS_RES_IRQ
, sc
->res
.irqrid
,
1948 KASSERT(sc
->ports
, ("digi%d: Lost my ports ?", sc
->res
.unit
));
1949 KASSERT(sc
->ttys
, ("digi%d: Lost my ttys ?", sc
->res
.unit
));
1950 kfree(sc
->ports
, M_TTYS
);
1952 kfree(sc
->ttys
, M_TTYS
);
1957 sc
->status
= DIGI_STATUS_NOTINIT
;
1961 digi_detach(device_t dev
)
1963 struct digi_softc
*sc
= device_get_softc(dev
);
1965 lwkt_gettoken(&tty_token
);
1966 DLOG(DIGIDB_INIT
, (sc
->dev
, "detaching\n"));
1968 /* If we're INIT'd, numports must be 0 */
1969 KASSERT(sc
->numports
== 0 || sc
->status
!= DIGI_STATUS_NOTINIT
,
1970 ("digi%d: numports(%d) & status(%d) are out of sync",
1971 sc
->res
.unit
, sc
->numports
, (int)sc
->status
));
1973 if (digi_inuse(sc
)) {
1974 lwkt_reltoken(&tty_token
);
1978 digi_free_state(sc
);
1980 destroy_dev(sc
->res
.ctldev
);
1982 if (sc
->res
.mem
!= NULL
) {
1983 bus_release_resource(dev
, SYS_RES_MEMORY
, sc
->res
.mrid
,
1987 if (sc
->res
.io
!= NULL
) {
1988 bus_release_resource(dev
, SYS_RES_IOPORT
, sc
->res
.iorid
,
1993 pmap_unmapdev((vm_offset_t
)sc
->vmem
, sc
->msize
);
1997 lwkt_reltoken(&tty_token
);
2002 digi_shutdown(device_t dev
)
2007 MODULE_VERSION(digi
, 1);