2 * dgb.c $FreeBSD: src/sys/gnu/i386/isa/dgb.c,v 1.56.2.1 2001/02/26 04:23:09 jlemon Exp $
3 * dgb.c $DragonFly: src/sys/platform/pc32/gnu/isa/dgb.c,v 1.20 2008/08/02 01:14:43 dillon Exp $
7 * Stage 1. "Better than nothing".
8 * Stage 2. "Gee, it works!".
10 * Based on sio driver by Bruce Evans and on Linux driver by Troy
11 * De Jongh <troyd@digibd.com> or <troyd@skypoint.com>
12 * which is under GNU General Public License version 2 so this driver
13 * is forced to be under GPL 2 too.
15 * Written by Serge Babkin,
16 * Joint Stock Commercial Bank "Chelindbank"
17 * (Chelyabinsk, Russia)
18 * babkin@hq.icb.chel.su
20 * Assorted hacks to make it more functional and working under 3.0-current.
21 * Fixed broken routines to prevent processes hanging on closed (thanks
22 * to Bruce for his patience and assistance). Thanks also to Maxim Bolotin
23 * <max@run.net> for his patches which did most of the work to get this
24 * running under 2.2/3.0-current.
25 * Implemented ioctls: TIOCMSDTRWAIT, TIOCMGDTRWAIT, TIOCTIMESTAMP &
27 * Sysctl debug flag is now a bitflag, to filter noise during debugging.
28 * David L. Nugent <davidn@blaze.net.au>
31 #include "opt_compat.h"
33 #include "opt_deprecated.h"
34 #ifndef I_WANT_DEPRECATED_STUFF
35 #error "Add options I_WANT_DEPRECATED_STUFF to your kernel config and send a mail to kernel@"
40 /* Helg: i.e.25 times per sec board will be polled */
41 #define POLLSPERSEC 25
42 /* How many charactes can we write to input tty rawq */
43 #define DGB_IBUFSIZE (TTYHOG-100)
45 /* the overall number of ports controlled by this driver */
48 # define NDGBPORTS (NDGB*16)
51 #include <sys/param.h>
52 #include <sys/systm.h>
57 #include <sys/dkstat.h>
58 #include <sys/fcntl.h>
59 #include <sys/kernel.h>
60 #include <sys/sysctl.h>
61 #include <sys/thread2.h>
63 #include <machine/clock.h>
68 #include <bus/isa/isa_device.h>
73 #define DGB_DEBUG /* Enable debugging info via sysctl */
76 #define CALLOUT_MASK 0x80
77 #define CONTROL_MASK 0x60
78 #define CONTROL_INIT_STATE 0x20
79 #define CONTROL_LOCK_STATE 0x40
80 #define UNIT_MASK 0x30000
81 #define PORT_MASK 0x1F
82 #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
83 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
84 #define MINOR_TO_UNIT(mynor) (((mynor) & UNIT_MASK)>>16)
85 #define MINOR_TO_PORT(mynor) ((mynor) & PORT_MASK)
87 /* types. XXX - should be elsewhere */
88 typedef u_char bool_t; /* boolean */
90 /* digiboard port structure */
94 u_char unit; /* board unit number */
95 u_char pnum; /* port number */
96 u_char omodem; /* FEP output modem status */
97 u_char imodem; /* FEP input modem status */
98 u_char modemfake; /* Modem values to be forced */
99 u_char modem; /* Force values */
126 volatile u_char *txptr;
127 volatile u_char *rxptr;
128 volatile struct board_chan *brdchan;
131 bool_t active_out; /* nonzero if the callout device is open */
132 u_int wopeners; /* # processes waiting for DCD in open() */
135 struct termios it_in; /* should be in struct tty */
136 struct termios it_out;
139 struct termios lt_in; /* should be in struct tty */
140 struct termios lt_out;
143 bool_t do_dcd_timestamp;
144 struct timeval timestamp;
145 struct timeval dcd_timestamp;
147 /* flags of state, are used in sleep() too */
148 u_char closing; /* port is being closed now */
149 u_char draining; /* port is being drained now */
150 u_char used; /* port is being used now */
151 u_char mustdrain; /* data must be waited to drain in dgbparam() */
154 /* Digiboard per-board structure */
156 /* struct board_info */
157 u_char status; /* status: DISABLED/ENABLED */
158 u_char unit; /* unit number */
159 u_char type; /* type of card: PCXE, PCXI, PCXEVE */
160 u_char altpin; /* do we need alternate pin setting ? */
161 int numports; /* number of ports on card */
162 int port; /* I/O port */
163 u_char *vmem; /* virtual memory address */
164 long pmem; /* physical memory address */
165 int mem_seg; /* internal memory segment */
166 struct dgb_p *ports; /* pointer to array of port descriptors */
167 struct tty *ttys; /* pointer to array of TTY structures */
168 volatile struct global_data *mailbox;
169 struct callout dgb_pause;
170 struct callout dgbpoll;
171 struct callout wakeflush;
175 static struct dgb_softc dgb_softc[NDGB];
176 static struct dgb_p dgb_ports[NDGBPORTS];
177 static struct tty dgb_tty[NDGBPORTS];
180 * The public functions in the com module ought to be declared in a com-driver
184 /* Interrupt handling entry points. */
185 static void dgbpoll (void *unit_c);
187 /* Device switch entry points. */
188 #define dgbreset noreset
189 #define dgbmmap nommap
190 #define dgbstrategy nostrategy
192 static int dgbattach (struct isa_device *dev);
193 static int dgbprobe (struct isa_device *dev);
195 static void fepcmd(struct dgb_p *port, unsigned cmd, unsigned op1, unsigned op2,
196 unsigned ncmds, unsigned bytecmd);
198 static void dgbstart (struct tty *tp);
199 static void dgbstop (struct tty *tp, int rw);
200 static int dgbparam (struct tty *tp, struct termios *t);
201 static void dgbhardclose (struct dgb_p *port);
202 static void dgb_drain_or_flush (struct dgb_p *port);
203 static int dgbdrain (struct dgb_p *port);
204 static void dgb_pause (void *chan);
205 static void wakeflush (void *p);
206 static void disc_optim (struct tty *tp, struct termios *t);
209 struct isa_driver dgbdriver = {
210 dgbprobe, dgbattach, "dgb",0
213 static d_open_t dgbopen;
214 static d_close_t dgbclose;
215 static d_ioctl_t dgbioctl;
217 #define CDEV_MAJOR 58
218 static struct cdevsw dgb_cdevsw = {
220 /* maj */ CDEV_MAJOR,
221 /* flags */ D_TTY | D_KQFILTER,
226 /* close */ dgbclose,
228 /* write */ ttywrite,
229 /* ioctl */ dgbioctl,
232 /* strategy */ nostrategy,
235 /* kqfilter */ ttykqfilter
238 static speed_t dgbdefaultrate = TTYDEF_SPEED;
240 static struct speedtab dgbspeedtab[] = {
241 { 0, FEP_B0 }, /* old (sysV-like) Bx codes */
255 { 19200, FEP_B19200 },
256 { 38400, FEP_B38400 },
257 { 57600, (FEP_FASTBAUD|FEP_B50) }, /* B50 & fast baud table */
258 { 115200, (FEP_FASTBAUD|FEP_B110) }, /* B100 & fast baud table */
262 static struct dbgflagtbl
269 { PARODD, PARODD, FEP_PARODD },
270 { PARENB, PARENB, FEP_PARENB },
271 { CSTOPB, CSTOPB, FEP_CSTOPB },
272 { CSIZE, CS5, FEP_CS6 },
273 { CSIZE, CS6, FEP_CS6 },
274 { CSIZE, CS7, FEP_CS7 },
275 { CSIZE, CS8, FEP_CS8 },
276 { CLOCAL, CLOCAL, FEP_CLOCAL },
280 { IGNBRK, IGNBRK, FEP_IGNBRK },
281 { BRKINT, BRKINT, FEP_BRKINT },
282 { IGNPAR, IGNPAR, FEP_IGNPAR },
283 { PARMRK, PARMRK, FEP_PARMRK },
284 { INPCK, INPCK, FEP_INPCK },
285 { ISTRIP, ISTRIP, FEP_ISTRIP },
286 { IXON, IXON, FEP_IXON },
287 { IXOFF, IXOFF, FEP_IXOFF },
288 { IXANY, IXANY, FEP_IXANY },
292 { CRTSCTS, CRTSCTS, CTS|RTS },
293 { CRTSCTS, CCTS_OFLOW, CTS },
294 { CRTSCTS, CRTS_IFLOW, RTS },
298 /* xlat bsd termios flags to dgb sys-v style */
300 dgbflags(struct dbgflagtbl *tbl, tcflag_t input)
305 for (i=0; tbl[i].in_mask != (tcflag_t)-1; i++)
307 if ((input & tbl[i].in_mask) == tbl[i].in_val)
308 output |= tbl[i].out_val;
314 static int dgbdebug=0;
315 SYSCTL_INT(_debug, OID_AUTO, dgb_debug, CTLFLAG_RW, &dgbdebug, 0, "");
318 static __inline int setwin (struct dgb_softc *sc, unsigned addr);
319 static __inline int setinitwin (struct dgb_softc *sc, unsigned addr);
320 static __inline void hidewin (struct dgb_softc *sc);
321 static __inline void towin (struct dgb_softc *sc, int win);
323 /*Helg: to allow recursive dgb...() calls */
325 { /* If we were called and don't want to disturb we need: */
326 int port; /* write to this port */
327 u_char data; /* this data on exit */
328 /* or DATA_WINOFF to close memory window on entry */
329 } BoardMemWinState; /* so several channels and even boards can coexist */
330 #define DATA_WINOFF 0
331 static BoardMemWinState bmws;
333 /* return current memory window state and close window */
334 static BoardMemWinState
337 BoardMemWinState bmwsRet=bmws;
338 if(bmws.data!=DATA_WINOFF)
339 outb(bmws.port, bmws.data=DATA_WINOFF);
343 /* restore memory window state */
345 bmws_set(BoardMemWinState ws)
347 if(ws.data != bmws.data || ws.port!=bmws.port ) {
348 if(bmws.data!=DATA_WINOFF)
349 outb(bmws.port,DATA_WINOFF);
350 if(ws.data!=DATA_WINOFF)
351 outb(ws.port, ws.data);
358 struct dgb_softc *sc;
361 if(sc->type==PCXEVE) {
362 outb(bmws.port=sc->port+1, bmws.data=FEPWIN|(addr>>13));
363 DPRINT3(DB_WIN,"dgb%d: switched to window 0x%x\n",sc->unit,addr>>13);
364 return (addr & 0x1FFF);
366 outb(bmws.port=sc->port,bmws.data=FEPMEM);
373 struct dgb_softc *sc;
376 if(sc->type==PCXEVE) {
377 outb(bmws.port=sc->port+1, bmws.data=FEPWIN|(addr>>13));
378 DPRINT3(DB_WIN,"dgb%d: switched to window 0x%x\n",sc->unit,addr>>13);
379 return (addr & 0x1FFF);
381 outb(bmws.port=sc->port,bmws.data=inb(sc->port)|FEPMEM);
388 struct dgb_softc *sc;
392 outb(bmws.port=sc->port+1, bmws.data);
394 outb(bmws.port=sc->port, bmws.data);
399 struct dgb_softc *sc;
402 if(sc->type==PCXEVE) {
403 outb(bmws.port=sc->port+1, bmws.data=win);
405 outb(bmws.port=sc->port,bmws.data=FEPMEM);
411 struct isa_device *dev;
413 struct dgb_softc *sc= &dgb_softc[dev->id_unit];
415 u_long win_size; /* size of vizible memory window */
416 int unit=dev->id_unit;
418 sc->unit=dev->id_unit;
419 sc->port=dev->id_iobase;
421 if(dev->id_flags & DGBFLAG_ALTPIN)
426 /* left 24 bits only (ISA address) */
427 sc->pmem=((intptr_t)(void *)dev->id_maddr & 0xFFFFFF);
429 DPRINT4(DB_INFO,"dgb%d: port 0x%x mem 0x%lx\n",unit,sc->port,sc->pmem);
431 outb(sc->port, FEPRST);
434 for(i=0; i< 1000; i++) {
436 if( (inb(sc->port) & FEPMASK) == FEPRST ) {
438 DPRINT3(DB_EXCEPT,"dgb%d: got reset after %d us\n",unit,i);
443 if(sc->status!=ENABLED) {
444 DPRINT2(DB_EXCEPT,"dgb%d: failed to respond\n",dev->id_unit);
448 /* check type of card and get internal memory characteristics */
457 kprintf("dgb%d: PC/Xi 64K\n",dev->id_unit);
462 kprintf("dgb%d: PC/Xi 128K\n",dev->id_unit);
467 kprintf("dgb%d: PC/Xi 256K\n",dev->id_unit);
469 default: /* case 0x30: */
472 kprintf("dgb%d: PC/Xi 512K\n",dev->id_unit);
481 kprintf("dgb%d: PC/Xm isn't supported\n",dev->id_unit);
488 if(dev->id_flags==DGBFLAG_NOWIN || ( v&0xC0 )==0) {
490 kprintf("dgb%d: PC/Xe 64K\n",dev->id_unit);
494 kprintf("dgb%d: PC/Xe 64/8K (windowed)\n",dev->id_unit);
496 if((u_long)sc->pmem & ~0xFFE000) {
497 kprintf("dgb%d: warning: address 0x%lx truncated to 0x%lx\n",
498 dev->id_unit, sc->pmem,
499 sc->pmem & 0xFFE000);
501 dev->id_maddr= (u_char *)(void *)(intptr_t)( sc->pmem & 0xFFE000 );
506 /* save size of vizible memory segment */
507 dev->id_msize=win_size;
510 dev->id_maddr=sc->vmem=pmap_mapdev(sc->pmem,dev->id_msize);
512 outb(sc->port, FEPCLR); /* drop RESET */
513 hidewin(sc); /* Helg: to set initial bmws state */
515 return 4; /* we need I/O space of 4 ports */
520 struct isa_device *dev;
522 int unit=dev->id_unit;
523 struct dgb_softc *sc= &dgb_softc[dev->id_unit];
525 u_char volatile *mem;
526 u_char volatile *ptr;
529 volatile struct board_chan *bc;
532 const volatile ushort *pstat;
537 if(sc->status!=ENABLED) {
538 DPRINT2(DB_EXCEPT,"dbg%d: try to attach a disabled card\n",unit);
542 callout_init(&sc->dgb_pause);
543 callout_init(&sc->dgbpoll);
544 callout_init(&sc->wakeflush);
548 DPRINT3(DB_INFO,"dgb%d: internal memory segment 0x%x\n",unit,sc->mem_seg);
550 outb(sc->port, FEPRST); DELAY(1);
552 for(i=0; (inb(sc->port) & FEPMASK) != FEPRST ; i++) {
554 kprintf("dgb%d: 1st reset failed\n",dev->id_unit);
562 DPRINT3(DB_INFO,"dgb%d: got reset after %d us\n",unit,i);
564 /* for PCXEVE set up interrupt and base address */
566 if(sc->type==PCXEVE) {
567 t=(((u_long)sc->pmem>>8) & 0xFFE0) | 0x10 /* enable windowing */;
569 outb(sc->port+2,t & 0xFF);
570 outb(sc->port+3,t>>8);
571 } else if(sc->type==PCXE) {
572 t=(((u_long)sc->pmem>>8) & 0xFFE0) /* disable windowing */;
573 outb(sc->port+2,t & 0xFF);
574 outb(sc->port+3,t>>8);
578 if(sc->type==PCXI || sc->type==PCXE) {
579 outb(sc->port, FEPRST|FEPMEM); DELAY(1);
581 for(i=0; (inb(sc->port) & FEPMASK) != (FEPRST|FEPMEM) ; i++) {
583 kprintf("dgb%d: 2nd reset failed\n",dev->id_unit);
591 DPRINT3(DB_INFO,"dgb%d: got memory after %d us\n",unit,i);
596 /* very short memory test */
598 addr=setinitwin(sc,BOTWIN);
599 *(u_long volatile *)(mem+addr) = 0xA55A3CC3;
600 if(*(u_long volatile *)(mem+addr)!=0xA55A3CC3) {
601 kprintf("dgb%d: 1st memory test failed\n",dev->id_unit);
607 addr=setinitwin(sc,TOPWIN);
608 *(u_long volatile *)(mem+addr) = 0x5AA5C33C;
609 if(*(u_long volatile *)(mem+addr)!=0x5AA5C33C) {
610 kprintf("dgb%d: 2nd memory test failed\n",dev->id_unit);
616 addr=setinitwin(sc,BIOSCODE+((0xF000-sc->mem_seg)<<4));
617 *(u_long volatile *)(mem+addr) = 0x5AA5C33C;
618 if(*(u_long volatile *)(mem+addr)!=0x5AA5C33C) {
619 kprintf("dgb%d: 3rd (BIOS) memory test failed\n",dev->id_unit);
622 addr=setinitwin(sc,MISCGLOBAL);
623 for(i=0; i<16; i++) {
627 if(sc->type==PCXI || sc->type==PCXE) {
629 addr=BIOSCODE+((0xF000-sc->mem_seg)<<4);
631 DPRINT3(DB_INFO,"dgb%d: BIOS local address=0x%x\n",unit,addr);
635 for(i=0; i<pcxx_nbios; i++, ptr++)
641 for(i=0; i<pcxx_nbios; i++, ptr++)
642 if( *ptr != pcxx_bios[i] ) {
643 DPRINT5(DB_EXCEPT,"dgb%d: wrong code in BIOS at addr 0x%x : \
644 0x%x instead of 0x%x\n", unit, ptr-(mem+addr), *ptr, pcxx_bios[i] );
647 kprintf("dgb%d: 4th memory test (BIOS load) fails\n",unit);
652 outb(sc->port,FEPMEM);
654 for(i=0; (inb(sc->port) & FEPMASK) != FEPMEM ; i++) {
656 kprintf("dgb%d: BIOS start failed\n",dev->id_unit);
664 DPRINT3(DB_INFO,"dgb%d: reset dropped after %d us\n",unit,i);
666 for(i=0; i<200000; i++) {
667 if( *((ushort volatile *)(mem+MISCGLOBAL)) == *((ushort *)"GD") )
671 kprintf("dgb%d: BIOS download failed\n",dev->id_unit);
672 DPRINT4(DB_EXCEPT,"dgb%d: code=0x%x must be 0x%x\n",
674 *((ushort volatile *)(mem+MISCGLOBAL)),
682 if(sc->type==PCXEVE) {
684 outb(sc->port+1,0xFF);
686 ptr= mem+(BIOSCODE & 0x1FFF);
688 for(i=0; i<pcxx_nbios; i++)
689 *ptr++ = pcxx_bios[i];
691 ptr= mem+(BIOSCODE & 0x1FFF);
694 for(i=0; i<pcxx_nbios; i++, ptr++)
695 if( *ptr != pcxx_bios[i] ) {
696 DPRINT5(DB_EXCEPT,"dgb%d: wrong code in BIOS at addr 0x%x : \
697 0x%x instead of 0x%x\n", unit, ptr-(mem+addr), *ptr, pcxx_bios[i] );
700 kprintf("dgb%d: 4th memory test (BIOS load) fails\n",unit);
705 outb(sc->port,FEPCLR);
709 for(i=0; (inb(sc->port) & FEPMASK) != FEPCLR ; i++) {
711 kprintf("dgb%d: BIOS start failed\n",dev->id_unit);
719 DPRINT3(DB_INFO,"dgb%d: reset dropped after %d us\n",unit,i);
721 addr=setwin(sc,MISCGLOBAL);
723 for(i=0; i<200000; i++) {
724 if(*(ushort volatile *)(mem+addr)== *(ushort *)"GD")
728 kprintf("dgb%d: BIOS download failed\n",dev->id_unit);
729 DPRINT5(DB_EXCEPT,"dgb%d: Error#(0x%x,0x%x) code=0x%x\n",
731 *(ushort volatile *)(mem+0xC12),
732 *(ushort volatile *)(mem+0xC14),
733 *(ushort volatile *)(mem+MISCGLOBAL));
741 DPRINT2(DB_INFO,"dgb%d: BIOS loaded\n",dev->id_unit);
743 addr=setwin(sc,FEPCODE);
747 for(i=0; i<pcxx_ncook; i++)
748 *ptr++ = pcxx_cook[i];
750 addr=setwin(sc,MBOX);
751 *(ushort volatile *)(mem+addr+ 0)=2;
752 *(ushort volatile *)(mem+addr+ 2)=sc->mem_seg+FEPCODESEG;
753 *(ushort volatile *)(mem+addr+ 4)=0;
754 *(ushort volatile *)(mem+addr+ 6)=FEPCODESEG;
755 *(ushort volatile *)(mem+addr+ 8)=0;
756 *(ushort volatile *)(mem+addr+10)=pcxx_ncook;
758 outb(sc->port,FEPMEM|FEPINT); /* send interrupt to BIOS */
759 outb(sc->port,FEPMEM);
761 for(i=0; *(ushort volatile *)(mem+addr)!=0; i++) {
763 kprintf("dgb%d: FEP code download failed\n",unit);
764 DPRINT3(DB_EXCEPT,"dgb%d: code=0x%x must be 0\n", unit,
765 *(ushort volatile *)(mem+addr));
772 DPRINT2(DB_INFO,"dgb%d: FEP code loaded\n",unit);
774 *(ushort volatile *)(mem+setwin(sc,FEPSTAT))=0;
775 addr=setwin(sc,MBOX);
776 *(ushort volatile *)(mem+addr+0)=1;
777 *(ushort volatile *)(mem+addr+2)=FEPCODESEG;
778 *(ushort volatile *)(mem+addr+4)=0x4;
780 outb(sc->port,FEPINT); /* send interrupt to BIOS */
781 outb(sc->port,FEPCLR);
783 addr=setwin(sc,FEPSTAT);
784 for(i=0; *(ushort volatile *)(mem+addr)!= *(ushort *)"OS"; i++) {
786 kprintf("dgb%d: FEP/OS start failed\n",dev->id_unit);
793 DPRINT2(DB_INFO,"dgb%d: FEP/OS started\n",dev->id_unit);
795 sc->numports= *(ushort volatile *)(mem+setwin(sc,NPORT));
797 kprintf("dgb%d: %d ports\n",unit,sc->numports);
799 if(sc->numports > MAX_DGB_PORTS) {
800 kprintf("dgb%d: too many ports\n",unit);
806 if(nports+sc->numports>NDGBPORTS) {
807 kprintf("dgb%d: only %d ports are usable\n", unit, NDGBPORTS-nports);
808 sc->numports=NDGBPORTS-nports;
811 /* allocate port and tty structures */
812 sc->ports=&dgb_ports[nports];
813 sc->ttys=&dgb_tty[nports];
814 nports+=sc->numports;
816 addr=setwin(sc,PORTBASE);
817 pstat=(const ushort volatile *)(mem+addr);
819 for(i=0; i<sc->numports && pstat[i]; i++)
821 sc->ports[i].status=ENABLED;
823 sc->ports[i].status=DISABLED;
824 kprintf("dgb%d: port%d is broken\n", unit, i);
827 /* We should now init per-port structures */
828 bc=(volatile struct board_chan *)(mem + CHANSTRUCT);
829 sc->mailbox=(volatile struct global_data *)(mem + FEP_GLOBAL);
836 for(i=0; i<sc->numports; i++, bc++) {
839 port->tty=&sc->ttys[i];
855 DPRINT2(DB_INFO,"dgb%d: shrinking memory\n",unit);
856 fepcmd(port, SETBUFFER, 32, 0, 0, 0);
860 if(sc->type!=PCXEVE) {
861 port->txptr=mem+((bc->tseg-sc->mem_seg)<<4);
862 port->rxptr=mem+((bc->rseg-sc->mem_seg)<<4);
863 port->txwin=port->rxwin=0;
865 port->txptr=mem+( ((bc->tseg-sc->mem_seg)<<4) & 0x1FFF );
866 port->rxptr=mem+( ((bc->rseg-sc->mem_seg)<<4) & 0x1FFF );
867 port->txwin=FEPWIN | ((bc->tseg-sc->mem_seg)>>9);
868 port->rxwin=FEPWIN | ((bc->rseg-sc->mem_seg)>>9);
873 port->txbufsize=bc->tmax+1;
874 port->rxbufsize=bc->rmax+1;
876 lowwater= (port->txbufsize>=2000) ? 1024 : (port->txbufsize/2);
878 fepcmd(port, STXLWATER, lowwater, 0, 10, 0);
879 fepcmd(port, SRXLWATER, port->rxbufsize/4, 0, 10, 0);
880 fepcmd(port, SRXHWATER, 3*port->rxbufsize/4, 0, 10, 0);
885 port->startc=bc->startc;
886 port->startca=bc->startca;
887 port->stopc=bc->stopc;
888 port->stopca=bc->stopca;
890 /*port->close_delay=50;*/
891 port->close_delay=3 * hz;
892 port->do_timestamp=0;
893 port->do_dcd_timestamp=0;
896 * We don't use all the flags from <sys/ttydefaults.h> since they
897 * are only relevant for logins. It's important to have echo off
898 * initially so that the line doesn't start blathering before the
899 * echo flag can be turned off.
901 port->it_in.c_iflag = TTYDEF_IFLAG;
902 port->it_in.c_oflag = TTYDEF_OFLAG;
903 port->it_in.c_cflag = TTYDEF_CFLAG;
904 port->it_in.c_lflag = TTYDEF_LFLAG;
905 termioschars(&port->it_in);
906 port->it_in.c_ispeed = port->it_in.c_ospeed = dgbdefaultrate;
907 port->it_out = port->it_in;
908 /* MAX_DGB_PORTS is 32 => [0-9a-v] */
909 suffix = i < 10 ? '0' + i : 'a' + i - 10;
910 cdevsw_add(&dgb_cdevsw, 0xffff0000, unit << 16);
911 make_dev(&dgb_cdevsw, (unit<<16)+i,
912 UID_ROOT, GID_WHEEL, 0600, "ttyD%d%c", unit, suffix);
914 make_dev(&dgb_cdevsw, (unit<<16)+i+32,
915 UID_ROOT, GID_WHEEL, 0600, "ttyiD%d%c", unit, suffix);
917 make_dev(&dgb_cdevsw, (unit<<16)+i+64,
918 UID_ROOT, GID_WHEEL, 0600, "ttylD%d%c", unit, suffix);
920 make_dev(&dgb_cdevsw, (unit<<16)+i+128,
921 UID_UUCP, GID_DIALER, 0660, "cuaD%d%c", unit, suffix);
923 make_dev(&dgb_cdevsw, (unit<<16)+i+160,
924 UID_UUCP, GID_DIALER, 0660, "cuaiD%d%c", unit, suffix);
926 make_dev(&dgb_cdevsw, (unit<<16)+i+192,
927 UID_UUCP, GID_DIALER, 0660, "cualD%d%c", unit, suffix);
932 /* register the polling function */
933 callout_reset(&sc->dgbpoll, hz / POLLSPERSEC, dgbpoll, (void *)unit);
940 dgbopen(cdev_t dev, int flag, int mode, struct thread *td)
942 struct dgb_softc *sc;
949 volatile struct board_chan *bc;
954 unit=MINOR_TO_UNIT(mynor);
955 pnum=MINOR_TO_PORT(mynor);
958 DPRINT2(DB_EXCEPT,"dgb%d: try to open a nonexisting card\n",unit);
964 if(sc->status!=ENABLED) {
965 DPRINT2(DB_EXCEPT,"dgb%d: try to open a disabled card\n",unit);
969 if(pnum>=sc->numports) {
970 DPRINT3(DB_EXCEPT,"dgb%d: try to open non-existing port %d\n",unit,pnum);
974 if(mynor & CONTROL_MASK)
979 port=&sc->ports[pnum];
986 while(port->closing) {
987 error=tsleep(&port->closing, PCATCH, "dgocl", 0);
990 DPRINT4(DB_OPEN,"dgb%d: port%d: tsleep(dgocl) error=%d\n",unit,pnum,error);
995 if (tp->t_state & TS_ISOPEN) {
997 * The device is open, so everything has been initialized.
1000 if (mynor & CALLOUT_MASK) {
1001 if (!port->active_out) {
1003 DPRINT4(DB_OPEN,"dgb%d: port%d: BUSY error=%d\n",unit,pnum,error);
1007 if (port->active_out) {
1008 if (flag & O_NONBLOCK) {
1010 DPRINT4(DB_OPEN,"dgb%d: port%d: BUSY error=%d\n",unit,pnum,error);
1013 error = tsleep(&port->active_out,
1016 DPRINT4(DB_OPEN,"dgb%d: port%d: tsleep(dgbi) error=%d\n",
1024 if (tp->t_state & TS_XCLUDE && priv_check(td, PRIV_ROOT)) {
1030 * The device isn't open, so there are no conflicts.
1031 * Initialize it. Initialization is done twice in many
1032 * cases: to preempt sleeping callin opens if we are
1033 * callout, and to complete a callin open after DCD rises.
1035 tp->t_oproc=dgbstart;
1036 tp->t_param=dgbparam;
1039 tp->t_termios= (mynor & CALLOUT_MASK) ?
1045 port->imodem=bc->mstat;
1046 bc->rout=bc->rin; /* clear input queue */
1048 #ifdef PRINT_BUFSIZE
1049 kprintf("dgb buffers tx=%x:%x rx=%x:%x\n",bc->tseg,bc->tmax,bc->rseg,bc->rmax);
1056 error=dgbparam(tp, &tp->t_termios);
1060 DPRINT4(DB_OPEN,"dgb%d: port%d: dgbparam error=%d\n",unit,pnum,error);
1064 /* handle fake DCD for callout devices */
1065 /* and initial DCD */
1067 if( (port->imodem & port->dcd) || mynor & CALLOUT_MASK )
1068 linesw[tp->t_line].l_modem(tp,1);
1073 * Wait for DCD if necessary.
1075 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
1076 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
1078 error = tsleep(TSA_CARR_ON(tp), PCATCH, "dgdcd", 0);
1081 DPRINT4(DB_OPEN,"dgb%d: port%d: tsleep(dgdcd) error=%d\n",unit,pnum,error);
1087 error = linesw[tp->t_line].l_open(dev, tp);
1088 disc_optim(tp,&tp->t_termios);
1089 DPRINT4(DB_OPEN,"dgb%d: port%d: l_open error=%d\n",unit,pnum,error);
1091 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
1092 port->active_out = TRUE;
1096 /* If any port is open (i.e. the open() call is completed for it)
1097 * the device is busy
1101 disc_optim(tp,&tp->t_termios);
1104 if( !(tp->t_state & TS_ISOPEN) && port->wopeners==0 )
1107 DPRINT4(DB_OPEN,"dgb%d: port%d: open() returns %d\n",unit,pnum,error);
1114 dgbclose(cdev_t dev, int flag, int mode, struct thread *td)
1118 struct dgb_softc *sc;
1124 if(mynor & CONTROL_MASK)
1126 unit=MINOR_TO_UNIT(mynor);
1127 pnum=MINOR_TO_PORT(mynor);
1129 sc=&dgb_softc[unit];
1131 port=sc->ports+pnum;
1133 DPRINT3(DB_CLOSE,"dgb%d: port%d: closing\n",unit,pnum);
1135 DPRINT3(DB_CLOSE,"dgb%d: port%d: draining port\n",unit,pnum);
1136 dgb_drain_or_flush(port);
1141 DPRINT3(DB_CLOSE,"dgb%d: port%d: closing line disc\n",unit,pnum);
1142 linesw[tp->t_line].l_close(tp,flag);
1143 disc_optim(tp,&tp->t_termios);
1145 DPRINT3(DB_CLOSE,"dgb%d: port%d: hard closing\n",unit,pnum);
1147 DPRINT3(DB_CLOSE,"dgb%d: port%d: closing tty\n",unit,pnum);
1150 wakeup(&port->closing);
1153 /* mark the card idle when all ports are closed */
1155 for(i=0; i<sc->numports; i++)
1156 if(sc->ports[i].used)
1161 DPRINT3(DB_CLOSE,"dgb%d: port%d: closed\n",unit,pnum);
1163 wakeup(TSA_CARR_ON(tp));
1164 wakeup(&port->active_out);
1167 DPRINT3(DB_CLOSE,"dgb%d: port%d: close exit\n",unit,pnum);
1176 struct dgb_softc *sc=&dgb_softc[port->unit];
1177 volatile struct board_chan *bc=port->brdchan;
1180 port->do_timestamp = 0;
1183 bc->idata=0; bc->iempty=0; bc->ilow=0;
1184 if(port->tty->t_cflag & HUPCL) {
1185 port->omodem &= ~(RTS|DTR);
1186 fepcmd(port, SETMODEM, 0, DTR|RTS, 0, 1);
1192 callout_reset(&sc->dgb_pause, hz / 2, dgb_pause, &port->brdchan);
1193 tsleep(&port->brdchan, PCATCH, "dgclo", 0);
1200 wakeup((caddr_t)chan);
1207 int unit=(int)unit_c;
1210 struct dgb_softc *sc=&dgb_softc[unit];
1213 int event, mstat, lstat;
1214 volatile struct board_chan *bc;
1221 int ibuf_full,obuf_full;
1223 BoardMemWinState ws=bmws_get();
1225 if(sc->status==DISABLED) {
1226 kprintf("dgb%d: polling of disabled board stopped\n",unit);
1232 head=sc->mailbox->ein;
1233 tail=sc->mailbox->eout;
1236 if(head >= FEP_IMAX-FEP_ISTART
1237 || tail >= FEP_IMAX-FEP_ISTART
1238 || (head|tail) & 03 ) {
1239 kprintf("dgb%d: event queue's head or tail is wrong! hd=%d,tl=%d\n", unit,head,tail);
1243 eventbuf=sc->vmem+tail+FEP_ISTART;
1249 port=&sc->ports[pnum];
1253 if(pnum>=sc->numports || port->status==DISABLED) {
1254 kprintf("dgb%d: port%d: got event on nonexisting port\n",unit,pnum);
1255 } else if(port->used || port->wopeners>0 ) {
1257 int wrapmask=port->rxbufsize-1;
1259 if( !(event & ALL_IND) )
1260 kprintf("dgb%d: port%d: ? event 0x%x mstat 0x%x lstat 0x%x\n",
1261 unit, pnum, event, mstat, lstat);
1263 if(event & DATA_IND) {
1264 DPRINT3(DB_DATA,"dgb%d: port%d: DATA_IND\n",unit,pnum);
1266 rhead=bc->rin & wrapmask;
1267 rtail=bc->rout & wrapmask;
1269 if( !(tp->t_cflag & CREAD) || !port->used ) {
1275 kprintf("dgb%d: port%d: overrun\n", unit, pnum);
1279 if(!(tp->t_state & TS_ISOPEN))
1282 for(ibuf_full=FALSE;rhead!=rtail && !ibuf_full;) {
1283 DPRINT5(DB_RXDATA,"dgb%d: port%d: p rx head=%d tail=%d\n",
1284 unit,pnum,rhead,rtail);
1289 size=port->rxbufsize-rtail;
1291 ptr=__DEVOLATILE(u_char *, port->rxptr+rtail);
1294 if( tp->t_rawq.c_cc + size > DGB_IBUFSIZE ) {
1295 size=DGB_IBUFSIZE-tp->t_rawq.c_cc;
1296 DPRINT1(DB_RXDATA,"*");
1301 if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1302 DPRINT1(DB_RXDATA,"!");
1303 towin(sc,port->rxwin);
1306 tp->t_rawcc += size;
1307 b_to_q(ptr,size,&tp->t_rawq);
1313 towin(sc,port->rxwin);
1316 (*linesw[tp->t_line].l_rint)(chr, tp);
1321 rtail= (rtail + size) & wrapmask;
1323 rhead=bc->rin & wrapmask;
1331 if(event & MODEMCHG_IND) {
1332 DPRINT3(DB_MODEM,"dgb%d: port%d: MODEMCHG_IND\n",unit,pnum);
1334 if(mstat & port->dcd) {
1336 linesw[tp->t_line].l_modem(tp,1);
1338 wakeup(TSA_CARR_ON(tp));
1341 linesw[tp->t_line].l_modem(tp,0);
1343 if( port->draining) {
1345 wakeup(&port->draining);
1350 if(event & BREAK_IND) {
1351 if((tp->t_state & TS_ISOPEN) && (tp->t_iflag & IGNBRK)) {
1352 DPRINT3(DB_BREAK,"dgb%d: port%d: BREAK_IND\n",unit,pnum);
1354 linesw[tp->t_line].l_rint(TTY_BI, tp);
1359 /* Helg: with output flow control */
1361 if(event & (LOWTX_IND | EMPTYTX_IND) ) {
1362 DPRINT3(DB_TXDATA,"dgb%d: port%d: LOWTX_IND or EMPTYTX_IND\n",unit,pnum);
1364 if( (event & EMPTYTX_IND ) && tp->t_outq.c_cc==0
1365 && port->draining) {
1367 wakeup(&port->draining);
1368 bc->ilow=0; bc->iempty=0;
1371 int wrapmask=port->txbufsize-1;
1373 for(obuf_full=FALSE; tp->t_outq.c_cc!=0 && !obuf_full; ) {
1374 /* add "last-minute" data to write buffer */
1375 if(!(tp->t_state & TS_BUSY)) {
1377 #ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */
1380 if(tp->t_outq.c_cc <= tp->t_lowat) {
1381 if(tp->t_state & TS_ASLEEP) {
1382 tp->t_state &= ~TS_ASLEEP;
1383 wakeup(TSA_OLOWAT(tp));
1385 /* selwakeup(&tp->t_wsel); */
1392 whead=bc->tin & wrapmask;
1393 wtail=bc->tout & wrapmask;
1398 size=port->txbufsize-whead;
1404 DPRINT5(DB_WR,"dgb: head=%d tail=%d size=%d full=%d\n",
1405 whead,wtail,size,obuf_full);
1406 bc->iempty=1; bc->ilow=1;
1412 towin(sc,port->txwin);
1414 ocount=q_to_b(&tp->t_outq, __DEVOLATILE(u_char *, port->txptr+whead), size);
1419 bc->tin=whead & wrapmask;
1424 DPRINT1(DB_WR," +BUSY\n");
1425 tp->t_state|=TS_BUSY;
1427 DPRINT1(DB_WR," -BUSY\n");
1429 #ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */
1430 /* should clear TS_BUSY before ttwwakeup */
1431 if(tp->t_state & TS_BUSY) {
1432 tp->t_state &= ~TS_BUSY;
1433 linesw[tp->t_line].l_start(tp);
1437 if(tp->t_state & TS_ASLEEP) {
1438 tp->t_state &= ~TS_ASLEEP;
1439 wakeup(TSA_OLOWAT(tp));
1441 tp->t_state &= ~TS_BUSY;
1447 bc->idata=1; /* require event on incoming data */
1451 DPRINT4(DB_EXCEPT,"dgb%d: port%d: got event 0x%x on closed port\n",
1454 bc->idata=bc->iempty=bc->ilow=0;
1457 tail= (tail+4) & (FEP_IMAX-FEP_ISTART-4);
1460 sc->mailbox->eout=tail;
1463 callout_reset(&sc->dgbpoll, hz / POLLSPERSEC, dgbpoll, unit_c);
1467 dgbioctl(cdev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
1469 struct dgb_softc *sc;
1474 volatile struct board_chan *bc;
1478 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1480 struct termios term;
1483 BoardMemWinState ws=bmws_get();
1486 unit=MINOR_TO_UNIT(mynor);
1487 pnum=MINOR_TO_PORT(mynor);
1489 sc=&dgb_softc[unit];
1490 port=&sc->ports[pnum];
1494 if (mynor & CONTROL_MASK) {
1497 switch (mynor & CONTROL_MASK) {
1498 case CONTROL_INIT_STATE:
1499 ct = mynor & CALLOUT_MASK ? &port->it_out : &port->it_in;
1501 case CONTROL_LOCK_STATE:
1502 ct = mynor & CALLOUT_MASK ? &port->lt_out : &port->lt_in;
1505 return (ENODEV); /* /dev/nodev */
1509 error = priv_check(td, PRIV_ROOT);
1512 *ct = *(struct termios *)data;
1515 *(struct termios *)data = *ct;
1518 *(int *)data = TTYDISC;
1521 bzero(data, sizeof(struct winsize));
1528 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1529 term = tp->t_termios;
1530 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
1531 DPRINT6(DB_PARAM,"dgb%d: port%d: dgbioctl-ISNOW c=0x%x i=0x%x l=0x%x\n",unit,pnum,term.c_cflag,term.c_iflag,term.c_lflag);
1534 error = ttsetcompat(tp, &cmd, data, &term);
1538 data = (caddr_t)&term;
1541 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
1543 struct termios *dt = (struct termios *)data;
1544 struct termios *lt = mynor & CALLOUT_MASK
1545 ? &port->lt_out : &port->lt_in;
1547 DPRINT6(DB_PARAM,"dgb%d: port%d: dgbioctl-TOSET c=0x%x i=0x%x l=0x%x\n",unit,pnum,dt->c_cflag,dt->c_iflag,dt->c_lflag);
1548 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1549 | (dt->c_iflag & ~lt->c_iflag);
1550 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1551 | (dt->c_oflag & ~lt->c_oflag);
1552 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1553 | (dt->c_cflag & ~lt->c_cflag);
1554 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1555 | (dt->c_lflag & ~lt->c_lflag);
1556 for (cc = 0; cc < NCCS; ++cc)
1557 if (lt->c_cc[cc] != 0)
1558 dt->c_cc[cc] = tp->t_cc[cc];
1559 if (lt->c_ispeed != 0)
1560 dt->c_ispeed = tp->t_ispeed;
1561 if (lt->c_ospeed != 0)
1562 dt->c_ospeed = tp->t_ospeed;
1568 fepcmd(port, PAUSETX, 0, 0, 0, 0);
1572 } else if(cmd==TIOCSTART) {
1575 fepcmd(port, RESUMETX, 0, 0, 0, 0);
1581 if(cmd==TIOCSETAW || cmd==TIOCSETAF)
1584 error = linesw[tp->t_line].l_ioctl(tp, cmd, data, flag, td);
1585 if (error != ENOIOCTL)
1588 error = ttioctl(tp, cmd, data, flag);
1589 disc_optim(tp,&tp->t_termios);
1591 if (error != ENOIOCTL) {
1593 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
1594 DPRINT6(DB_PARAM,"dgb%d: port%d: dgbioctl-RES c=0x%x i=0x%x l=0x%x\n",unit,pnum,tp->t_cflag,tp->t_iflag,tp->t_lflag);
1601 /* Helg: commented */
1602 /* error=dgbdrain(port);*/
1612 /* now it sends 250 millisecond break because I don't know */
1613 /* how to send an infinite break */
1615 fepcmd(port, SENDBREAK, 250, 0, 10, 0);
1620 /* now it's empty */
1623 DPRINT3(DB_MODEM,"dgb%d: port%d: set DTR\n",unit,pnum);
1624 port->omodem |= DTR;
1627 fepcmd(port, SETMODEM, port->omodem, RTS, 0, 1);
1629 if( !(bc->mstat & DTR) ) {
1630 DPRINT3(DB_MODEM,"dgb%d: port%d: DTR is off\n",unit,pnum);
1637 DPRINT3(DB_MODEM,"dgb%d: port%d: reset DTR\n",unit,pnum);
1638 port->omodem &= ~DTR;
1641 fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1);
1643 if( bc->mstat & DTR ) {
1644 DPRINT3(DB_MODEM,"dgb%d: port%d: DTR is on\n",unit,pnum);
1651 if(*(int *)data & TIOCM_DTR)
1654 port->omodem &=~DTR;
1656 if(*(int *)data & TIOCM_RTS)
1659 port->omodem &=~RTS;
1663 fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1);
1668 if(*(int *)data & TIOCM_DTR)
1671 if(*(int *)data & TIOCM_RTS)
1676 fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1);
1681 if(*(int *)data & TIOCM_DTR)
1682 port->omodem &=~DTR;
1684 if(*(int *)data & TIOCM_RTS)
1685 port->omodem &=~RTS;
1689 fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1);
1695 port->imodem=bc->mstat;
1698 tiocm_xxx = TIOCM_LE; /* XXX - always enabled while open */
1700 DPRINT3(DB_MODEM,"dgb%d: port%d: modem stat -- ",unit,pnum);
1702 if (port->imodem & DTR) {
1703 DPRINT1(DB_MODEM,"DTR ");
1704 tiocm_xxx |= TIOCM_DTR;
1706 if (port->imodem & RTS) {
1707 DPRINT1(DB_MODEM,"RTS ");
1708 tiocm_xxx |= TIOCM_RTS;
1710 if (port->imodem & CTS) {
1711 DPRINT1(DB_MODEM,"CTS ");
1712 tiocm_xxx |= TIOCM_CTS;
1714 if (port->imodem & port->dcd) {
1715 DPRINT1(DB_MODEM,"DCD ");
1716 tiocm_xxx |= TIOCM_CD;
1718 if (port->imodem & port->dsr) {
1719 DPRINT1(DB_MODEM,"DSR ");
1720 tiocm_xxx |= TIOCM_DSR;
1722 if (port->imodem & RI) {
1723 DPRINT1(DB_MODEM,"RI ");
1724 tiocm_xxx |= TIOCM_RI;
1726 *(int *)data = tiocm_xxx;
1727 DPRINT1(DB_MODEM,"--\n");
1730 /* must be root since the wait applies to following logins */
1731 error = priv_check(td, PRIV_ROOT);
1736 port->close_delay = *(int *)data * hz / 100;
1739 *(int *)data = port->close_delay * 100 / hz;
1742 port->do_timestamp = TRUE;
1743 *(struct timeval *)data = port->timestamp;
1745 case TIOCDCDTIMESTAMP:
1746 port->do_dcd_timestamp = TRUE;
1747 *(struct timeval *)data = port->dcd_timestamp;
1764 struct dgb_p *port=p;
1766 wakeup(&port->draining);
1769 /* wait for the output to drain */
1775 struct dgb_softc *sc=&dgb_softc[port->unit];
1776 volatile struct board_chan *bc=port->brdchan;
1780 BoardMemWinState ws=bmws_get();
1789 DPRINT5(DB_WR,"dgb%d: port%d: drain: head=%d tail=%d\n",
1790 port->unit, port->pnum, head, tail);
1794 callout_reset(&sc->wakeflush, hz, wakeflush,port);
1795 error=tsleep(&port->draining, PCATCH, "dgdrn", 0);
1800 DPRINT4(DB_WR,"dgb%d: port%d: tsleep(dgdrn) error=%d\n",
1801 port->unit,port->pnum,error);
1811 DPRINT5(DB_WR,"dgb%d: port%d: drain: head=%d tail=%d\n",
1812 port->unit, port->pnum, head, tail);
1817 /* wait for the output to drain */
1818 /* or simply clear the buffer it it's stopped */
1821 dgb_drain_or_flush(port)
1824 struct tty *tp=port->tty;
1825 struct dgb_softc *sc=&dgb_softc[port->unit];
1826 volatile struct board_chan *bc=port->brdchan;
1838 while(tail!=head /* && tail!=lasttail */ ) {
1839 DPRINT5(DB_WR,"dgb%d: port%d: flush: head=%d tail=%d\n",
1840 port->unit, port->pnum, head, tail);
1842 /* if there is no carrier simply clean the buffer */
1843 if( !(tp->t_state & TS_CARR_ON) ) {
1852 callout_reset(&sc->wakeflush, hz, wakeflush, port);
1853 error=tsleep(&port->draining, PCATCH, "dgfls", 0);
1858 DPRINT4(DB_WR,"dgb%d: port%d: tsleep(dgfls) error=%d\n",
1859 port->unit,port->pnum,error);
1861 /* silently clean the buffer */
1874 DPRINT5(DB_WR,"dgb%d: port%d: flush: head=%d tail=%d\n",
1875 port->unit, port->pnum, head, tail);
1883 int unit=MINOR_TO_UNIT(minor(tp->t_dev));
1884 int pnum=MINOR_TO_PORT(minor(tp->t_dev));
1885 struct dgb_softc *sc=&dgb_softc[unit];
1886 struct dgb_p *port=&sc->ports[pnum];
1887 volatile struct board_chan *bc=port->brdchan;
1894 BoardMemWinState ws=bmws_get();
1896 DPRINT6(DB_PARAM,"dgb%d: port%d: dgbparm c=0x%x i=0x%x l=0x%x\n",unit,pnum,t->c_cflag,t->c_iflag,t->c_lflag);
1898 if(port->mustdrain) {
1899 DPRINT3(DB_PARAM,"dgb%d: port%d: must call dgbdrain()\n",unit,pnum);
1903 cflag=ttspeedtab(t->c_ospeed, dgbspeedtab);
1905 if (t->c_ispeed == 0)
1906 t->c_ispeed = t->c_ospeed;
1908 if (cflag < 0 /* || cflag > 0 && t->c_ispeed != t->c_ospeed */) {
1909 DPRINT4(DB_PARAM,"dgb%d: port%d: invalid cflag=0%o\n",unit,pnum,cflag);
1916 if(cflag==0) { /* hangup */
1917 DPRINT3(DB_PARAM,"dgb%d: port%d: hangup\n",unit,pnum);
1921 fepcmd(port, STOUT, (unsigned)head, 0, 0, 0);
1922 mval= port->omodem & ~(DTR|RTS);
1924 cflag |= dgbflags(dgb_cflags, t->c_cflag);
1926 if(cflag!=port->fepcflag) {
1927 port->fepcflag=cflag;
1928 DPRINT5(DB_PARAM,"dgb%d: port%d: set cflag=0x%x c=0x%x\n",
1929 unit,pnum,cflag,t->c_cflag&~CRTSCTS);
1930 fepcmd(port, SETCTRLFLAGS, (unsigned)cflag, 0, 0, 0);
1932 mval= port->omodem | (DTR|RTS);
1935 iflag=dgbflags(dgb_iflags, t->c_iflag);
1936 if(iflag!=port->fepiflag) {
1937 port->fepiflag=iflag;
1938 DPRINT5(DB_PARAM,"dgb%d: port%d: set iflag=0x%x c=0x%x\n",unit,pnum,iflag,t->c_iflag);
1939 fepcmd(port, SETIFLAGS, (unsigned)iflag, 0, 0, 0);
1944 hflow=dgbflags(dgb_flow, t->c_cflag);
1945 if(hflow!=port->hflow) {
1947 DPRINT5(DB_PARAM,"dgb%d: port%d: set hflow=0x%x f=0x%x\n",unit,pnum,hflow,t->c_cflag&CRTSCTS);
1948 fepcmd(port, SETHFLOW, (unsigned)hflow, 0xff, 0, 1);
1951 if(port->omodem != mval) {
1952 DPRINT5(DB_PARAM,"dgb%d: port%d: setting modem parameters 0x%x was 0x%x\n",
1953 unit,pnum,mval,port->omodem);
1955 fepcmd(port, SETMODEM, (unsigned)mval, RTS|DTR, 0, 1);
1958 if(port->fepstartc!=t->c_cc[VSTART] || port->fepstopc!=t->c_cc[VSTOP]) {
1959 DPRINT5(DB_PARAM,"dgb%d: port%d: set startc=%d, stopc=%d\n",unit,pnum,t->c_cc[VSTART],t->c_cc[VSTOP]);
1960 port->fepstartc=t->c_cc[VSTART];
1961 port->fepstopc=t->c_cc[VSTOP];
1962 fepcmd(port, SONOFFC, port->fepstartc, port->fepstopc, 0, 1);
1979 struct dgb_softc *sc;
1980 volatile struct board_chan *bc;
1985 BoardMemWinState ws=bmws_get();
1987 unit=MINOR_TO_UNIT(minor(tp->t_dev));
1988 pnum=MINOR_TO_PORT(minor(tp->t_dev));
1989 sc=&dgb_softc[unit];
1990 port=&sc->ports[pnum];
1993 wmask=port->txbufsize-1;
1997 while( tp->t_outq.c_cc!=0 ) {
1999 #ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */
2002 if(tp->t_outq.c_cc <= tp->t_lowat) {
2003 if(tp->t_state & TS_ASLEEP) {
2004 tp->t_state &= ~TS_ASLEEP;
2005 wakeup(TSA_OLOWAT(tp));
2007 /*selwakeup(&tp->t_wsel);*/
2013 head=bc->tin & wmask;
2015 do { tail=bc->tout; } while (tail != bc->tout);
2016 tail=bc->tout & wmask;
2018 DPRINT5(DB_WR,"dgb%d: port%d: s tx head=%d tail=%d\n",unit,pnum,head,tail);
2020 #ifdef LEAVE_FREE_CHARS
2022 size=tail-head-LEAVE_FREE_CHARS;
2026 size=port->txbufsize-head;
2027 if(tail+port->txbufsize < head)
2035 size=port->txbufsize-head/*-1*/;
2042 bc->iempty=1; bc->ilow=1;
2045 tp->t_state|=TS_BUSY;
2050 towin(sc,port->txwin);
2052 ocount=q_to_b(&tp->t_outq, __DEVOLATILE(u_char *, port->txptr+head), size);
2054 if(head>=port->txbufsize)
2055 head-=port->txbufsize;
2060 DPRINT5(DB_WR,"dgb%d: port%d: tx avail=%d count=%d\n",unit,pnum,size,ocount);
2068 #ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */
2069 if(tp->t_state & TS_BUSY) {
2070 tp->t_state&=~TS_BUSY;
2071 linesw[tp->t_line].l_start(tp);
2075 if(tp->t_state & TS_ASLEEP) {
2076 tp->t_state &= ~TS_ASLEEP;
2077 wakeup(TSA_OLOWAT(tp));
2079 tp->t_state&=~TS_BUSY;
2091 struct dgb_softc *sc;
2092 volatile struct board_chan *bc;
2094 BoardMemWinState ws=bmws_get();
2096 unit=MINOR_TO_UNIT(minor(tp->t_dev));
2097 pnum=MINOR_TO_PORT(minor(tp->t_dev));
2099 sc=&dgb_softc[unit];
2100 port=&sc->ports[pnum];
2103 DPRINT3(DB_WR,"dgb%d: port%d: stop\n",port->unit, port->pnum);
2109 /* clear output queue */
2111 bc->ilow=0;bc->iempty=0;
2114 /* clear input queue */
2125 fepcmd(port, cmd, op1, op2, ncmds, bytecmd)
2127 unsigned cmd, op1, op2, ncmds, bytecmd;
2129 struct dgb_softc *sc=&dgb_softc[port->unit];
2130 u_char *mem=sc->vmem;
2131 unsigned tail, head;
2134 if(port->status==DISABLED) {
2135 kprintf("dgb%d: port%d: FEP command on disabled port\n",
2136 port->unit, port->pnum);
2140 /* setwin(sc,0); Require this to be set by caller */
2141 head=sc->mailbox->cin;
2143 if(head>=(FEP_CMAX-FEP_CSTART) || (head & 3)) {
2144 kprintf("dgb%d: port%d: wrong pointer head of command queue : 0x%x\n",
2145 port->unit, port->pnum, head);
2149 mem[head+FEP_CSTART+0]=cmd;
2150 mem[head+FEP_CSTART+1]=port->pnum;
2152 mem[head+FEP_CSTART+2]=op1;
2153 mem[head+FEP_CSTART+3]=op2;
2155 mem[head+FEP_CSTART+2]=op1&0xff;
2156 mem[head+FEP_CSTART+3]=(op1>>8)&0xff;
2159 DPRINT7(DB_FEP,"dgb%d: port%d: %s cmd=0x%x op1=0x%x op2=0x%x\n", port->unit, port->pnum,
2160 (bytecmd)?"byte":"word", cmd, mem[head+FEP_CSTART+2], mem[head+FEP_CSTART+3]);
2162 head=(head+4) & (FEP_CMAX-FEP_CSTART-4);
2163 sc->mailbox->cin=head;
2167 while (count-- != 0) {
2168 head=sc->mailbox->cin;
2169 tail=sc->mailbox->cout;
2171 n = (head-tail) & (FEP_CMAX-FEP_CSTART-4);
2172 if(n <= ncmds * (sizeof(ushort)*4))
2175 kprintf("dgb%d(%d): timeout on FEP cmd=0x%x\n", port->unit, port->pnum, cmd);
2183 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
2184 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
2185 && (!(t->c_iflag & PARMRK)
2186 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
2187 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
2188 && linesw[tp->t_line].l_rint == ttyinput)
2189 tp->t_state |= TS_CAN_BYPASS_L_RINT;
2191 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;