Home | History | Annotate | Line # | Download | only in gdb
ser-go32.c revision 1.1
      1  1.1  christos /* Remote serial interface for local (hardwired) serial ports for GO32.
      2  1.1  christos    Copyright (C) 1992-2014 Free Software Foundation, Inc.
      3  1.1  christos 
      4  1.1  christos    Contributed by Nigel Stephens, Algorithmics Ltd. (nigel (at) algor.co.uk).
      5  1.1  christos 
      6  1.1  christos    This version uses DPMI interrupts to handle buffered i/o
      7  1.1  christos    without the separate "asynctsr" program.
      8  1.1  christos 
      9  1.1  christos    This file is part of GDB.
     10  1.1  christos 
     11  1.1  christos    This program is free software; you can redistribute it and/or modify
     12  1.1  christos    it under the terms of the GNU General Public License as published by
     13  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     14  1.1  christos    (at your option) any later version.
     15  1.1  christos 
     16  1.1  christos    This program is distributed in the hope that it will be useful,
     17  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     18  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19  1.1  christos    GNU General Public License for more details.
     20  1.1  christos 
     21  1.1  christos    You should have received a copy of the GNU General Public License
     22  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     23  1.1  christos 
     24  1.1  christos #include "defs.h"
     25  1.1  christos #include "gdbcmd.h"
     26  1.1  christos #include "serial.h"
     27  1.1  christos #include <string.h>
     28  1.1  christos 
     29  1.1  christos 
     30  1.1  christos /*
     31  1.1  christos  * NS16550 UART registers
     32  1.1  christos  */
     33  1.1  christos 
     34  1.1  christos #define COM1ADDR	0x3f8
     35  1.1  christos #define COM2ADDR	0x2f8
     36  1.1  christos #define COM3ADDR	0x3e8
     37  1.1  christos #define COM4ADDR	0x3e0
     38  1.1  christos 
     39  1.1  christos #define	com_data	0	/* data register (R/W) */
     40  1.1  christos #define	com_dlbl	0	/* divisor latch low (W) */
     41  1.1  christos #define	com_ier		1	/* interrupt enable (W) */
     42  1.1  christos #define	com_dlbh	1	/* divisor latch high (W) */
     43  1.1  christos #define	com_iir		2	/* interrupt identification (R) */
     44  1.1  christos #define	com_fifo	2	/* FIFO control (W) */
     45  1.1  christos #define	com_lctl	3	/* line control register (R/W) */
     46  1.1  christos #define	com_cfcr	3	/* line control register (R/W) */
     47  1.1  christos #define	com_mcr		4	/* modem control register (R/W) */
     48  1.1  christos #define	com_lsr		5	/* line status register (R/W) */
     49  1.1  christos #define	com_msr		6	/* modem status register (R/W) */
     50  1.1  christos 
     51  1.1  christos /*
     52  1.1  christos  * Constants for computing 16 bit baud rate divisor (lower byte
     53  1.1  christos  * in com_dlbl, upper in com_dlbh) from 1.8432MHz crystal.  Divisor is
     54  1.1  christos  * 1.8432 MHz / (16 * X) for X bps.  If the baud rate can't be set
     55  1.1  christos  * to within +- (desired_rate*SPEED_TOLERANCE/1000) bps, we fail.
     56  1.1  christos  */
     57  1.1  christos #define COMTICK		(1843200/16)
     58  1.1  christos #define SPEED_TOLERANCE	30	/* thousandths; real == desired +- 3.0% */
     59  1.1  christos 
     60  1.1  christos /* interrupt enable register */
     61  1.1  christos #define	IER_ERXRDY	0x1	/* int on rx ready */
     62  1.1  christos #define	IER_ETXRDY	0x2	/* int on tx ready */
     63  1.1  christos #define	IER_ERLS	0x4	/* int on line status change */
     64  1.1  christos #define	IER_EMSC	0x8	/* int on modem status change */
     65  1.1  christos 
     66  1.1  christos /* interrupt identification register */
     67  1.1  christos #define	IIR_FIFO_MASK	0xc0	/* set if FIFOs are enabled */
     68  1.1  christos #define	IIR_IMASK	0xf	/* interrupt cause mask */
     69  1.1  christos #define	IIR_NOPEND	0x1	/* nothing pending */
     70  1.1  christos #define	IIR_RLS		0x6	/* receive line status */
     71  1.1  christos #define	IIR_RXRDY	0x4	/* receive ready */
     72  1.1  christos #define	IIR_RXTOUT	0xc	/* receive timeout */
     73  1.1  christos #define	IIR_TXRDY	0x2	/* transmit ready */
     74  1.1  christos #define	IIR_MLSC	0x0	/* modem status */
     75  1.1  christos 
     76  1.1  christos 
     77  1.1  christos /* fifo control register */
     78  1.1  christos #define	FIFO_ENABLE	0x01	/* enable fifo */
     79  1.1  christos #define	FIFO_RCV_RST	0x02	/* reset receive fifo */
     80  1.1  christos #define	FIFO_XMT_RST	0x04	/* reset transmit fifo */
     81  1.1  christos #define	FIFO_DMA_MODE	0x08	/* enable dma mode */
     82  1.1  christos #define	FIFO_TRIGGER_1	0x00	/* trigger at 1 char */
     83  1.1  christos #define	FIFO_TRIGGER_4	0x40	/* trigger at 4 chars */
     84  1.1  christos #define	FIFO_TRIGGER_8	0x80	/* trigger at 8 chars */
     85  1.1  christos #define	FIFO_TRIGGER_14	0xc0	/* trigger at 14 chars */
     86  1.1  christos 
     87  1.1  christos /* character format control register */
     88  1.1  christos #define	CFCR_DLAB	0x80	/* divisor latch */
     89  1.1  christos #define	CFCR_SBREAK	0x40	/* send break */
     90  1.1  christos #define	CFCR_PZERO	0x30	/* zero parity */
     91  1.1  christos #define	CFCR_PONE	0x20	/* one parity */
     92  1.1  christos #define	CFCR_PEVEN	0x10	/* even parity */
     93  1.1  christos #define	CFCR_PODD	0x00	/* odd parity */
     94  1.1  christos #define	CFCR_PENAB	0x08	/* parity enable */
     95  1.1  christos #define	CFCR_STOPB	0x04	/* 2 stop bits */
     96  1.1  christos #define	CFCR_8BITS	0x03	/* 8 data bits */
     97  1.1  christos #define	CFCR_7BITS	0x02	/* 7 data bits */
     98  1.1  christos #define	CFCR_6BITS	0x01	/* 6 data bits */
     99  1.1  christos #define	CFCR_5BITS	0x00	/* 5 data bits */
    100  1.1  christos 
    101  1.1  christos /* modem control register */
    102  1.1  christos #define	MCR_LOOPBACK	0x10	/* loopback */
    103  1.1  christos #define	MCR_IENABLE	0x08	/* output 2 = int enable */
    104  1.1  christos #define	MCR_DRS		0x04	/* output 1 = xxx */
    105  1.1  christos #define	MCR_RTS		0x02	/* enable RTS */
    106  1.1  christos #define	MCR_DTR		0x01	/* enable DTR */
    107  1.1  christos 
    108  1.1  christos /* line status register */
    109  1.1  christos #define	LSR_RCV_FIFO	0x80	/* error in receive fifo */
    110  1.1  christos #define	LSR_TSRE	0x40	/* transmitter empty */
    111  1.1  christos #define	LSR_TXRDY	0x20	/* transmitter ready */
    112  1.1  christos #define	LSR_BI		0x10	/* break detected */
    113  1.1  christos #define	LSR_FE		0x08	/* framing error */
    114  1.1  christos #define	LSR_PE		0x04	/* parity error */
    115  1.1  christos #define	LSR_OE		0x02	/* overrun error */
    116  1.1  christos #define	LSR_RXRDY	0x01	/* receiver ready */
    117  1.1  christos #define	LSR_RCV_MASK	0x1f
    118  1.1  christos 
    119  1.1  christos /* modem status register */
    120  1.1  christos #define	MSR_DCD		0x80
    121  1.1  christos #define	MSR_RI		0x40
    122  1.1  christos #define	MSR_DSR		0x20
    123  1.1  christos #define	MSR_CTS		0x10
    124  1.1  christos #define	MSR_DDCD	0x08
    125  1.1  christos #define	MSR_TERI	0x04
    126  1.1  christos #define	MSR_DDSR	0x02
    127  1.1  christos #define	MSR_DCTS	0x01
    128  1.1  christos 
    129  1.1  christos #include <time.h>
    130  1.1  christos #include <dos.h>
    131  1.1  christos #include <go32.h>
    132  1.1  christos #include <dpmi.h>
    133  1.1  christos typedef unsigned long u_long;
    134  1.1  christos 
    135  1.1  christos /* 16550 rx fifo trigger point */
    136  1.1  christos #define FIFO_TRIGGER	FIFO_TRIGGER_4
    137  1.1  christos 
    138  1.1  christos /* input buffer size */
    139  1.1  christos #define CBSIZE	4096
    140  1.1  christos 
    141  1.1  christos #define RAWHZ	18
    142  1.1  christos 
    143  1.1  christos #ifdef DOS_STATS
    144  1.1  christos #define CNT_RX		16
    145  1.1  christos #define CNT_TX		17
    146  1.1  christos #define CNT_STRAY	18
    147  1.1  christos #define CNT_ORUN	19
    148  1.1  christos #define NCNT		20
    149  1.1  christos 
    150  1.1  christos static int intrcnt;
    151  1.1  christos static size_t cnts[NCNT];
    152  1.1  christos static char *cntnames[NCNT] =
    153  1.1  christos {
    154  1.1  christos   /* h/w interrupt counts.  */
    155  1.1  christos   "mlsc", "nopend", "txrdy", "?3",
    156  1.1  christos   "rxrdy", "?5", "rls", "?7",
    157  1.1  christos   "?8", "?9", "?a", "?b",
    158  1.1  christos   "rxtout", "?d", "?e", "?f",
    159  1.1  christos   /* s/w counts.  */
    160  1.1  christos   "rxcnt", "txcnt", "stray", "swoflo"
    161  1.1  christos };
    162  1.1  christos 
    163  1.1  christos #define COUNT(x) cnts[x]++
    164  1.1  christos #else
    165  1.1  christos #define COUNT(x)
    166  1.1  christos #endif
    167  1.1  christos 
    168  1.1  christos /* Main interrupt controller port addresses.  */
    169  1.1  christos #define ICU_BASE	0x20
    170  1.1  christos #define ICU_OCW2	(ICU_BASE + 0)
    171  1.1  christos #define ICU_MASK	(ICU_BASE + 1)
    172  1.1  christos 
    173  1.1  christos /* Original interrupt controller mask register.  */
    174  1.1  christos unsigned char icu_oldmask;
    175  1.1  christos 
    176  1.1  christos /* Maximum of 8 interrupts (we don't handle the slave icu yet).  */
    177  1.1  christos #define NINTR	8
    178  1.1  christos 
    179  1.1  christos static struct intrupt
    180  1.1  christos   {
    181  1.1  christos     char inuse;
    182  1.1  christos     struct dos_ttystate *port;
    183  1.1  christos     _go32_dpmi_seginfo old_rmhandler;
    184  1.1  christos     _go32_dpmi_seginfo old_pmhandler;
    185  1.1  christos     _go32_dpmi_seginfo new_rmhandler;
    186  1.1  christos     _go32_dpmi_seginfo new_pmhandler;
    187  1.1  christos     _go32_dpmi_registers regs;
    188  1.1  christos   }
    189  1.1  christos intrupts[NINTR];
    190  1.1  christos 
    191  1.1  christos 
    192  1.1  christos static struct dos_ttystate
    193  1.1  christos   {
    194  1.1  christos     int base;
    195  1.1  christos     int irq;
    196  1.1  christos     int refcnt;
    197  1.1  christos     struct intrupt *intrupt;
    198  1.1  christos     int fifo;
    199  1.1  christos     int baudrate;
    200  1.1  christos     unsigned char cbuf[CBSIZE];
    201  1.1  christos     unsigned int first;
    202  1.1  christos     unsigned int count;
    203  1.1  christos     int txbusy;
    204  1.1  christos     unsigned char old_mcr;
    205  1.1  christos     int ferr;
    206  1.1  christos     int perr;
    207  1.1  christos     int oflo;
    208  1.1  christos     int msr;
    209  1.1  christos   }
    210  1.1  christos ports[4] =
    211  1.1  christos {
    212  1.1  christos   {
    213  1.1  christos     COM1ADDR, 4, 0, NULL, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0
    214  1.1  christos   }
    215  1.1  christos   ,
    216  1.1  christos   {
    217  1.1  christos     COM2ADDR, 3, 0, NULL, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0
    218  1.1  christos   }
    219  1.1  christos   ,
    220  1.1  christos   {
    221  1.1  christos     COM3ADDR, 4, 0, NULL, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0
    222  1.1  christos   }
    223  1.1  christos   ,
    224  1.1  christos   {
    225  1.1  christos     COM4ADDR, 3, 0, NULL, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0
    226  1.1  christos   }
    227  1.1  christos };
    228  1.1  christos 
    229  1.1  christos static int dos_open (struct serial *scb, const char *name);
    230  1.1  christos static void dos_raw (struct serial *scb);
    231  1.1  christos static int dos_readchar (struct serial *scb, int timeout);
    232  1.1  christos static int dos_setbaudrate (struct serial *scb, int rate);
    233  1.1  christos static int dos_write (struct serial *scb, const void *buf, size_t count);
    234  1.1  christos static void dos_close (struct serial *scb);
    235  1.1  christos static serial_ttystate dos_get_tty_state (struct serial *scb);
    236  1.1  christos static int dos_set_tty_state (struct serial *scb, serial_ttystate state);
    237  1.1  christos static int dos_baudconv (int rate);
    238  1.1  christos 
    239  1.1  christos #define inb(p,a)	inportb((p)->base + (a))
    240  1.1  christos #define outb(p,a,v)	outportb((p)->base + (a), (v))
    241  1.1  christos #define disable()	asm volatile ("cli");
    242  1.1  christos #define enable()	asm volatile ("sti");
    243  1.1  christos 
    244  1.1  christos 
    245  1.1  christos static int
    246  1.1  christos dos_getc (volatile struct dos_ttystate *port)
    247  1.1  christos {
    248  1.1  christos   int c;
    249  1.1  christos 
    250  1.1  christos   if (port->count == 0)
    251  1.1  christos     return -1;
    252  1.1  christos 
    253  1.1  christos   c = port->cbuf[port->first];
    254  1.1  christos   disable ();
    255  1.1  christos   port->first = (port->first + 1) & (CBSIZE - 1);
    256  1.1  christos   port->count--;
    257  1.1  christos   enable ();
    258  1.1  christos   return c;
    259  1.1  christos }
    260  1.1  christos 
    261  1.1  christos 
    262  1.1  christos static int
    263  1.1  christos dos_putc (int c, struct dos_ttystate *port)
    264  1.1  christos {
    265  1.1  christos   if (port->count >= CBSIZE - 1)
    266  1.1  christos     return -1;
    267  1.1  christos   port->cbuf[(port->first + port->count) & (CBSIZE - 1)] = c;
    268  1.1  christos   port->count++;
    269  1.1  christos   return 0;
    270  1.1  christos }
    271  1.1  christos 
    272  1.1  christos 
    274  1.1  christos 
    275  1.1  christos static void
    276  1.1  christos dos_comisr (int irq)
    277  1.1  christos {
    278  1.1  christos   struct dos_ttystate *port;
    279  1.1  christos   unsigned char iir, lsr, c;
    280  1.1  christos 
    281  1.1  christos   disable ();			/* Paranoia */
    282  1.1  christos   outportb (ICU_OCW2, 0x20);	/* End-Of-Interrupt */
    283  1.1  christos #ifdef DOS_STATS
    284  1.1  christos   ++intrcnt;
    285  1.1  christos #endif
    286  1.1  christos 
    287  1.1  christos   port = intrupts[irq].port;
    288  1.1  christos   if (!port)
    289  1.1  christos     {
    290  1.1  christos       COUNT (CNT_STRAY);
    291  1.1  christos       return;			/* not open */
    292  1.1  christos     }
    293  1.1  christos 
    294  1.1  christos   while (1)
    295  1.1  christos     {
    296  1.1  christos       iir = inb (port, com_iir) & IIR_IMASK;
    297  1.1  christos       switch (iir)
    298  1.1  christos 	{
    299  1.1  christos 
    300  1.1  christos 	case IIR_RLS:
    301  1.1  christos 	  lsr = inb (port, com_lsr);
    302  1.1  christos 	  goto rx;
    303  1.1  christos 
    304  1.1  christos 	case IIR_RXTOUT:
    305  1.1  christos 	case IIR_RXRDY:
    306  1.1  christos 	  lsr = 0;
    307  1.1  christos 
    308  1.1  christos 	rx:
    309  1.1  christos 	  do
    310  1.1  christos 	    {
    311  1.1  christos 	      c = inb (port, com_data);
    312  1.1  christos 	      if (lsr & (LSR_BI | LSR_FE | LSR_PE | LSR_OE))
    313  1.1  christos 		{
    314  1.1  christos 		  if (lsr & (LSR_BI | LSR_FE))
    315  1.1  christos 		    port->ferr++;
    316  1.1  christos 		  else if (lsr & LSR_PE)
    317  1.1  christos 		    port->perr++;
    318  1.1  christos 		  if (lsr & LSR_OE)
    319  1.1  christos 		    port->oflo++;
    320  1.1  christos 		}
    321  1.1  christos 
    322  1.1  christos 	      if (dos_putc (c, port) < 0)
    323  1.1  christos 		{
    324  1.1  christos 		  COUNT (CNT_ORUN);
    325  1.1  christos 		}
    326  1.1  christos 	      else
    327  1.1  christos 		{
    328  1.1  christos 		  COUNT (CNT_RX);
    329  1.1  christos 		}
    330  1.1  christos 	    }
    331  1.1  christos 	  while ((lsr = inb (port, com_lsr)) & LSR_RXRDY);
    332  1.1  christos 	  break;
    333  1.1  christos 
    334  1.1  christos 	case IIR_MLSC:
    335  1.1  christos 	  /* could be used to flowcontrol Tx */
    336  1.1  christos 	  port->msr = inb (port, com_msr);
    337  1.1  christos 	  break;
    338  1.1  christos 
    339  1.1  christos 	case IIR_TXRDY:
    340  1.1  christos 	  port->txbusy = 0;
    341  1.1  christos 	  break;
    342  1.1  christos 
    343  1.1  christos 	case IIR_NOPEND:
    344  1.1  christos 	  /* No more pending interrupts, all done.  */
    345  1.1  christos 	  return;
    346  1.1  christos 
    347  1.1  christos 	default:
    348  1.1  christos 	  /* Unexpected interrupt, ignore.  */
    349  1.1  christos 	  break;
    350  1.1  christos 	}
    351  1.1  christos       COUNT (iir);
    352  1.1  christos     }
    353  1.1  christos }
    354  1.1  christos 
    355  1.1  christos #define ISRNAME(x) dos_comisr##x
    356  1.1  christos #define ISR(x) static void ISRNAME(x)(void) {dos_comisr(x);}
    357  1.1  christos 
    358  1.1  christos ISR (0) ISR (1) ISR (2) ISR (3) /* OK */
    359  1.1  christos ISR (4) ISR (5) ISR (6) ISR (7) /* OK */
    360  1.1  christos 
    361  1.1  christos typedef void (*isr_t) (void);
    362  1.1  christos 
    363  1.1  christos static isr_t isrs[NINTR] =
    364  1.1  christos   {
    365  1.1  christos        ISRNAME (0), ISRNAME (1), ISRNAME (2), ISRNAME (3),
    366  1.1  christos        ISRNAME (4), ISRNAME (5), ISRNAME (6), ISRNAME (7)
    367  1.1  christos   };
    368  1.1  christos 
    369  1.1  christos 
    371  1.1  christos 
    372  1.1  christos static struct intrupt *
    373  1.1  christos dos_hookirq (unsigned int irq)
    374  1.1  christos {
    375  1.1  christos   struct intrupt *intr;
    376  1.1  christos   unsigned int vec;
    377  1.1  christos   isr_t isr;
    378  1.1  christos 
    379  1.1  christos   if (irq >= NINTR)
    380  1.1  christos     return 0;
    381  1.1  christos 
    382  1.1  christos   intr = &intrupts[irq];
    383  1.1  christos   if (intr->inuse)
    384  1.1  christos     return 0;
    385  1.1  christos 
    386  1.1  christos   vec = 0x08 + irq;
    387  1.1  christos   isr = isrs[irq];
    388  1.1  christos 
    389  1.1  christos   /* Setup real mode handler.  */
    390  1.1  christos   _go32_dpmi_get_real_mode_interrupt_vector (vec, &intr->old_rmhandler);
    391  1.1  christos 
    392  1.1  christos   intr->new_rmhandler.pm_selector = _go32_my_cs ();
    393  1.1  christos   intr->new_rmhandler.pm_offset = (u_long) isr;
    394  1.1  christos   if (_go32_dpmi_allocate_real_mode_callback_iret (&intr->new_rmhandler,
    395  1.1  christos 						   &intr->regs))
    396  1.1  christos     {
    397  1.1  christos       return 0;
    398  1.1  christos     }
    399  1.1  christos 
    400  1.1  christos   if (_go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->new_rmhandler))
    401  1.1  christos     {
    402  1.1  christos       return 0;
    403  1.1  christos     }
    404  1.1  christos 
    405  1.1  christos   /* Setup protected mode handler.  */
    406  1.1  christos   _go32_dpmi_get_protected_mode_interrupt_vector (vec, &intr->old_pmhandler);
    407  1.1  christos 
    408  1.1  christos   intr->new_pmhandler.pm_selector = _go32_my_cs ();
    409  1.1  christos   intr->new_pmhandler.pm_offset = (u_long) isr;
    410  1.1  christos   _go32_dpmi_allocate_iret_wrapper (&intr->new_pmhandler);
    411  1.1  christos 
    412  1.1  christos   if (_go32_dpmi_set_protected_mode_interrupt_vector (vec,
    413  1.1  christos 						      &intr->new_pmhandler))
    414  1.1  christos     {
    415  1.1  christos       return 0;
    416  1.1  christos     }
    417  1.1  christos 
    418  1.1  christos   /* Setup interrupt controller mask.  */
    419  1.1  christos   disable ();
    420  1.1  christos   outportb (ICU_MASK, inportb (ICU_MASK) & ~(1 << irq));
    421  1.1  christos   enable ();
    422  1.1  christos 
    423  1.1  christos   intr->inuse = 1;
    424  1.1  christos   return intr;
    425  1.1  christos }
    426  1.1  christos 
    427  1.1  christos 
    428  1.1  christos static void
    429  1.1  christos dos_unhookirq (struct intrupt *intr)
    430  1.1  christos {
    431  1.1  christos   unsigned int irq, vec;
    432  1.1  christos   unsigned char mask;
    433  1.1  christos 
    434  1.1  christos   irq = intr - intrupts;
    435  1.1  christos   vec = 0x08 + irq;
    436  1.1  christos 
    437  1.1  christos   /* Restore old interrupt mask bit.  */
    438  1.1  christos   mask = 1 << irq;
    439  1.1  christos   disable ();
    440  1.1  christos   outportb (ICU_MASK, inportb (ICU_MASK) | (mask & icu_oldmask));
    441  1.1  christos   enable ();
    442  1.1  christos 
    443  1.1  christos   /* Remove real mode handler.  */
    444  1.1  christos   _go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->old_rmhandler);
    445  1.1  christos   _go32_dpmi_free_real_mode_callback (&intr->new_rmhandler);
    446  1.1  christos 
    447  1.1  christos   /* Remove protected mode handler.  */
    448  1.1  christos   _go32_dpmi_set_protected_mode_interrupt_vector (vec, &intr->old_pmhandler);
    449  1.1  christos   _go32_dpmi_free_iret_wrapper (&intr->new_pmhandler);
    450  1.1  christos   intr->inuse = 0;
    451  1.1  christos }
    452  1.1  christos 
    453  1.1  christos 
    455  1.1  christos 
    456  1.1  christos static int
    457  1.1  christos dos_open (struct serial *scb, const char *name)
    458  1.1  christos {
    459  1.1  christos   struct dos_ttystate *port;
    460  1.1  christos   int fd, i;
    461  1.1  christos 
    462  1.1  christos   if (strncasecmp (name, "/dev/", 5) == 0)
    463  1.1  christos     name += 5;
    464  1.1  christos   else if (strncasecmp (name, "\\dev\\", 5) == 0)
    465  1.1  christos     name += 5;
    466  1.1  christos 
    467  1.1  christos   if (strlen (name) != 4 || strncasecmp (name, "com", 3) != 0)
    468  1.1  christos     {
    469  1.1  christos       errno = ENOENT;
    470  1.1  christos       return -1;
    471  1.1  christos     }
    472  1.1  christos 
    473  1.1  christos   if (name[3] < '1' || name[3] > '4')
    474  1.1  christos     {
    475  1.1  christos       errno = ENOENT;
    476  1.1  christos       return -1;
    477  1.1  christos     }
    478  1.1  christos 
    479  1.1  christos   /* FIXME: this is a Bad Idea (tm)!  One should *never* invent file
    480  1.1  christos      handles, since they might be already used by other files/devices.
    481  1.1  christos      The Right Way to do this is to create a real handle by dup()'ing
    482  1.1  christos      some existing one.  */
    483  1.1  christos   fd = name[3] - '1';
    484  1.1  christos   port = &ports[fd];
    485  1.1  christos   if (port->refcnt++ > 0)
    486  1.1  christos     {
    487  1.1  christos       /* Device already opened another user.  Just point at it.  */
    488  1.1  christos       scb->fd = fd;
    489  1.1  christos       return 0;
    490  1.1  christos     }
    491  1.1  christos 
    492  1.1  christos   /* Force access to ID reg.  */
    493  1.1  christos   outb (port, com_cfcr, 0);
    494  1.1  christos   outb (port, com_iir, 0);
    495  1.1  christos   for (i = 0; i < 17; i++)
    496  1.1  christos     {
    497  1.1  christos       if ((inb (port, com_iir) & 0x38) == 0)
    498  1.1  christos 	goto ok;
    499  1.1  christos       (void) inb (port, com_data);	/* clear recv */
    500  1.1  christos     }
    501  1.1  christos   errno = ENODEV;
    502  1.1  christos   return -1;
    503  1.1  christos 
    504  1.1  christos ok:
    505  1.1  christos   /* Disable all interrupts in chip.  */
    506  1.1  christos   outb (port, com_ier, 0);
    507  1.1  christos 
    508  1.1  christos   /* Tentatively enable 16550 fifo, and see if it responds.  */
    509  1.1  christos   outb (port, com_fifo,
    510  1.1  christos 	FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER);
    511  1.1  christos   sleep (1);
    512  1.1  christos   port->fifo = ((inb (port, com_iir) & IIR_FIFO_MASK) == IIR_FIFO_MASK);
    513  1.1  christos 
    514  1.1  christos   /* clear pending status reports.  */
    515  1.1  christos   (void) inb (port, com_lsr);
    516  1.1  christos   (void) inb (port, com_msr);
    517  1.1  christos 
    518  1.1  christos   /* Enable external interrupt gate (to avoid floating IRQ).  */
    519  1.1  christos   outb (port, com_mcr, MCR_IENABLE);
    520  1.1  christos 
    521  1.1  christos   /* Hook up interrupt handler and initialise icu.  */
    522  1.1  christos   port->intrupt = dos_hookirq (port->irq);
    523  1.1  christos   if (!port->intrupt)
    524  1.1  christos     {
    525  1.1  christos       outb (port, com_mcr, 0);
    526  1.1  christos       outb (port, com_fifo, 0);
    527  1.1  christos       errno = ENODEV;
    528  1.1  christos       return -1;
    529  1.1  christos     }
    530  1.1  christos 
    531  1.1  christos   disable ();
    532  1.1  christos 
    533  1.1  christos   /* record port */
    534  1.1  christos   port->intrupt->port = port;
    535  1.1  christos   scb->fd = fd;
    536  1.1  christos 
    537  1.1  christos   /* Clear rx buffer, tx busy flag and overflow count.  */
    538  1.1  christos   port->first = port->count = 0;
    539  1.1  christos   port->txbusy = 0;
    540  1.1  christos   port->oflo = 0;
    541  1.1  christos 
    542  1.1  christos   /* Set default baud rate and mode: 9600,8,n,1 */
    543  1.1  christos   i = dos_baudconv (port->baudrate = 9600);
    544  1.1  christos   outb (port, com_cfcr, CFCR_DLAB);
    545  1.1  christos   outb (port, com_dlbl, i & 0xff);
    546  1.1  christos   outb (port, com_dlbh, i >> 8);
    547  1.1  christos   outb (port, com_cfcr, CFCR_8BITS);
    548  1.1  christos 
    549  1.1  christos   /* Enable all interrupts.  */
    550  1.1  christos   outb (port, com_ier, IER_ETXRDY | IER_ERXRDY | IER_ERLS | IER_EMSC);
    551  1.1  christos 
    552  1.1  christos   /* Enable DTR & RTS.  */
    553  1.1  christos   outb (port, com_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);
    554  1.1  christos 
    555  1.1  christos   enable ();
    556  1.1  christos 
    557  1.1  christos   return 0;
    558  1.1  christos }
    559  1.1  christos 
    560  1.1  christos 
    561  1.1  christos static void
    562  1.1  christos dos_close (struct serial *scb)
    563  1.1  christos {
    564  1.1  christos   struct dos_ttystate *port;
    565  1.1  christos   struct intrupt *intrupt;
    566  1.1  christos 
    567  1.1  christos   if (!scb)
    568  1.1  christos     return;
    569  1.1  christos 
    570  1.1  christos   port = &ports[scb->fd];
    571  1.1  christos 
    572  1.1  christos   if (port->refcnt-- > 1)
    573  1.1  christos     return;
    574  1.1  christos 
    575  1.1  christos   if (!(intrupt = port->intrupt))
    576  1.1  christos     return;
    577  1.1  christos 
    578  1.1  christos   /* Disable interrupts, fifo, flow control.  */
    579  1.1  christos   disable ();
    580  1.1  christos   port->intrupt = 0;
    581  1.1  christos   intrupt->port = 0;
    582  1.1  christos   outb (port, com_fifo, 0);
    583  1.1  christos   outb (port, com_ier, 0);
    584  1.1  christos   enable ();
    585  1.1  christos 
    586  1.1  christos   /* Unhook handler, and disable interrupt gate.  */
    587  1.1  christos   dos_unhookirq (intrupt);
    588  1.1  christos   outb (port, com_mcr, 0);
    589  1.1  christos 
    590  1.1  christos   /* Check for overflow errors.  */
    591  1.1  christos   if (port->oflo)
    592  1.1  christos     {
    593  1.1  christos       fprintf_unfiltered (gdb_stderr,
    594  1.1  christos 			  "Serial input overruns occurred.\n");
    595  1.1  christos       fprintf_unfiltered (gdb_stderr, "This system %s handle %d baud.\n",
    596  1.1  christos 			  port->fifo ? "cannot" : "needs a 16550 to",
    597  1.1  christos 			  port->baudrate);
    598  1.1  christos     }
    599  1.1  christos }
    600  1.1  christos 
    601  1.1  christos 
    603  1.1  christos 
    604  1.1  christos static int
    605  1.1  christos dos_noop (struct serial *scb)
    606  1.1  christos {
    607  1.1  christos   return 0;
    608  1.1  christos }
    609  1.1  christos 
    610  1.1  christos static void
    611  1.1  christos dos_raw (struct serial *scb)
    612  1.1  christos {
    613  1.1  christos   /* Always in raw mode.  */
    614  1.1  christos }
    615  1.1  christos 
    616  1.1  christos static int
    617  1.1  christos dos_readchar (struct serial *scb, int timeout)
    618  1.1  christos {
    619  1.1  christos   struct dos_ttystate *port = &ports[scb->fd];
    620  1.1  christos   long then;
    621  1.1  christos   int c;
    622  1.1  christos 
    623  1.1  christos   then = rawclock () + (timeout * RAWHZ);
    624  1.1  christos   while ((c = dos_getc (port)) < 0)
    625  1.1  christos     {
    626  1.1  christos       if (timeout >= 0 && (rawclock () - then) >= 0)
    627  1.1  christos 	return SERIAL_TIMEOUT;
    628  1.1  christos     }
    629  1.1  christos 
    630  1.1  christos   return c;
    631  1.1  christos }
    632  1.1  christos 
    633  1.1  christos 
    634  1.1  christos static serial_ttystate
    635  1.1  christos dos_get_tty_state (struct serial *scb)
    636  1.1  christos {
    637  1.1  christos   struct dos_ttystate *port = &ports[scb->fd];
    638  1.1  christos   struct dos_ttystate *state;
    639  1.1  christos 
    640  1.1  christos   /* Are they asking about a port we opened?  */
    641  1.1  christos   if (port->refcnt <= 0)
    642  1.1  christos     {
    643  1.1  christos       /* We've never heard about this port.  We should fail this call,
    644  1.1  christos 	 unless they are asking about one of the 3 standard handles,
    645  1.1  christos 	 in which case we pretend the handle was open by us if it is
    646  1.1  christos 	 connected to a terminal device.  This is beacuse Unix
    647  1.1  christos 	 terminals use the serial interface, so GDB expects the
    648  1.1  christos 	 standard handles to go through here.  */
    649  1.1  christos       if (scb->fd >= 3 || !isatty (scb->fd))
    650  1.1  christos 	return NULL;
    651  1.1  christos     }
    652  1.1  christos 
    653  1.1  christos   state = (struct dos_ttystate *) xmalloc (sizeof *state);
    654  1.1  christos   *state = *port;
    655  1.1  christos   return (serial_ttystate) state;
    656  1.1  christos }
    657  1.1  christos 
    658  1.1  christos static serial_ttystate
    659  1.1  christos dos_copy_tty_state (struct serial *scb, serial_ttystate ttystate)
    660  1.1  christos {
    661  1.1  christos   struct dos_ttystate *state;
    662  1.1  christos 
    663  1.1  christos   state = (struct dos_ttystate *) xmalloc (sizeof *state);
    664  1.1  christos   *state = *(struct dos_ttystate *) ttystate;
    665  1.1  christos 
    666  1.1  christos   return (serial_ttystate) state;
    667  1.1  christos }
    668  1.1  christos 
    669  1.1  christos static int
    670  1.1  christos dos_set_tty_state (struct serial *scb, serial_ttystate ttystate)
    671  1.1  christos {
    672  1.1  christos   struct dos_ttystate *state;
    673  1.1  christos 
    674  1.1  christos   state = (struct dos_ttystate *) ttystate;
    675  1.1  christos   dos_setbaudrate (scb, state->baudrate);
    676  1.1  christos   return 0;
    677  1.1  christos }
    678  1.1  christos 
    679  1.1  christos static int
    680  1.1  christos dos_noflush_set_tty_state (struct serial *scb, serial_ttystate new_ttystate,
    681  1.1  christos 			   serial_ttystate old_ttystate)
    682  1.1  christos {
    683  1.1  christos   struct dos_ttystate *state;
    684  1.1  christos 
    685  1.1  christos   state = (struct dos_ttystate *) new_ttystate;
    686  1.1  christos   dos_setbaudrate (scb, state->baudrate);
    687  1.1  christos   return 0;
    688  1.1  christos }
    689  1.1  christos 
    690  1.1  christos static int
    691  1.1  christos dos_flush_input (struct serial *scb)
    692  1.1  christos {
    693  1.1  christos   struct dos_ttystate *port = &ports[scb->fd];
    694  1.1  christos 
    695  1.1  christos   disable ();
    696  1.1  christos   port->first = port->count = 0;
    697  1.1  christos   if (port->fifo)
    698  1.1  christos     outb (port, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_TRIGGER);
    699  1.1  christos   enable ();
    700  1.1  christos   return 0;
    701  1.1  christos }
    702  1.1  christos 
    703  1.1  christos static void
    704  1.1  christos dos_print_tty_state (struct serial *scb, serial_ttystate ttystate,
    705  1.1  christos 		     struct ui_file *stream)
    706  1.1  christos {
    707  1.1  christos   /* Nothing to print.  */
    708  1.1  christos   return;
    709  1.1  christos }
    710  1.1  christos 
    711  1.1  christos static int
    712  1.1  christos dos_baudconv (int rate)
    713  1.1  christos {
    714  1.1  christos   long x, err;
    715  1.1  christos 
    716  1.1  christos   if (rate <= 0)
    717  1.1  christos     return -1;
    718  1.1  christos 
    719  1.1  christos #define divrnd(n, q)	(((n) * 2 / (q) + 1) / 2) /* Divide and round off.  */
    720  1.1  christos   x = divrnd (COMTICK, rate);
    721  1.1  christos   if (x <= 0)
    722  1.1  christos     return -1;
    723  1.1  christos 
    724  1.1  christos   err = divrnd (1000 * COMTICK, x * rate) - 1000;
    725  1.1  christos   if (err < 0)
    726  1.1  christos     err = -err;
    727  1.1  christos   if (err > SPEED_TOLERANCE)
    728  1.1  christos     return -1;
    729  1.1  christos #undef divrnd
    730  1.1  christos   return x;
    731  1.1  christos }
    732  1.1  christos 
    733  1.1  christos 
    734  1.1  christos static int
    735  1.1  christos dos_setbaudrate (struct serial *scb, int rate)
    736  1.1  christos {
    737  1.1  christos   struct dos_ttystate *port = &ports[scb->fd];
    738  1.1  christos 
    739  1.1  christos   if (port->baudrate != rate)
    740  1.1  christos     {
    741  1.1  christos       int x;
    742  1.1  christos       unsigned char cfcr;
    743  1.1  christos 
    744  1.1  christos       x = dos_baudconv (rate);
    745  1.1  christos       if (x <= 0)
    746  1.1  christos 	{
    747  1.1  christos 	  fprintf_unfiltered (gdb_stderr, "%d: impossible baudrate\n", rate);
    748  1.1  christos 	  errno = EINVAL;
    749  1.1  christos 	  return -1;
    750  1.1  christos 	}
    751  1.1  christos 
    752  1.1  christos       disable ();
    753  1.1  christos       cfcr = inb (port, com_cfcr);
    754  1.1  christos 
    755  1.1  christos       outb (port, com_cfcr, CFCR_DLAB);
    756  1.1  christos       outb (port, com_dlbl, x & 0xff);
    757  1.1  christos       outb (port, com_dlbh, x >> 8);
    758  1.1  christos       outb (port, com_cfcr, cfcr);
    759  1.1  christos       port->baudrate = rate;
    760  1.1  christos       enable ();
    761  1.1  christos     }
    762  1.1  christos 
    763  1.1  christos   return 0;
    764  1.1  christos }
    765  1.1  christos 
    766  1.1  christos static int
    767  1.1  christos dos_setstopbits (struct serial *scb, int num)
    768  1.1  christos {
    769  1.1  christos   struct dos_ttystate *port = &ports[scb->fd];
    770  1.1  christos   unsigned char cfcr;
    771  1.1  christos 
    772  1.1  christos   disable ();
    773  1.1  christos   cfcr = inb (port, com_cfcr);
    774  1.1  christos 
    775  1.1  christos   switch (num)
    776  1.1  christos     {
    777  1.1  christos     case SERIAL_1_STOPBITS:
    778  1.1  christos       outb (port, com_cfcr, cfcr & ~CFCR_STOPB);
    779  1.1  christos       break;
    780  1.1  christos     case SERIAL_1_AND_A_HALF_STOPBITS:
    781  1.1  christos     case SERIAL_2_STOPBITS:
    782  1.1  christos       outb (port, com_cfcr, cfcr | CFCR_STOPB);
    783  1.1  christos       break;
    784  1.1  christos     default:
    785  1.1  christos       enable ();
    786  1.1  christos       return 1;
    787  1.1  christos     }
    788  1.1  christos   enable ();
    789  1.1  christos 
    790  1.1  christos   return 0;
    791  1.1  christos }
    792  1.1  christos 
    793  1.1  christos static int
    794  1.1  christos dos_write (struct serial *scb, const void *buf, size_t count)
    795  1.1  christos {
    796  1.1  christos   volatile struct dos_ttystate *port = &ports[scb->fd];
    797  1.1  christos   size_t fifosize = port->fifo ? 16 : 1;
    798  1.1  christos   long then;
    799  1.1  christos   size_t cnt;
    800  1.1  christos   const char *str = buf;
    801  1.1  christos 
    802  1.1  christos   while (count > 0)
    803  1.1  christos     {
    804  1.1  christos       /* Send the data, fifosize bytes at a time.  */
    805  1.1  christos       cnt = fifosize > count ? count : fifosize;
    806  1.1  christos       port->txbusy = 1;
    807  1.1  christos       /* Francisco Pastor <fpastor.etra-id (at) etra.es> says OUTSB messes
    808  1.1  christos 	 up the communications with UARTs with FIFOs.  */
    809  1.1  christos #ifdef UART_FIFO_WORKS
    810  1.1  christos       outportsb (port->base + com_data, str, cnt);
    811  1.1  christos       str += cnt;
    812  1.1  christos       count -= cnt;
    813  1.1  christos #else
    814  1.1  christos       for ( ; cnt > 0; cnt--, count--)
    815  1.1  christos 	outportb (port->base + com_data, *str++);
    816  1.1  christos #endif
    817  1.1  christos #ifdef DOS_STATS
    818  1.1  christos       cnts[CNT_TX] += cnt;
    819  1.1  christos #endif
    820  1.1  christos       /* Wait for transmission to complete (max 1 sec).  */
    821  1.1  christos       then = rawclock () + RAWHZ;
    822  1.1  christos       while (port->txbusy)
    823  1.1  christos 	{
    824  1.1  christos 	  if ((rawclock () - then) >= 0)
    825  1.1  christos 	    {
    826  1.1  christos 	      errno = EIO;
    827  1.1  christos 	      return SERIAL_ERROR;
    828  1.1  christos 	    }
    829  1.1  christos 	}
    830  1.1  christos     }
    831  1.1  christos   return 0;
    832  1.1  christos }
    833  1.1  christos 
    834  1.1  christos 
    835  1.1  christos static int
    836  1.1  christos dos_sendbreak (struct serial *scb)
    837  1.1  christos {
    838  1.1  christos   volatile struct dos_ttystate *port = &ports[scb->fd];
    839  1.1  christos   unsigned char cfcr;
    840  1.1  christos   long then;
    841  1.1  christos 
    842  1.1  christos   cfcr = inb (port, com_cfcr);
    843  1.1  christos   outb (port, com_cfcr, cfcr | CFCR_SBREAK);
    844  1.1  christos 
    845  1.1  christos   /* 0.25 sec delay */
    846  1.1  christos   then = rawclock () + RAWHZ / 4;
    847  1.1  christos   while ((rawclock () - then) < 0)
    848  1.1  christos     continue;
    849  1.1  christos 
    850  1.1  christos   outb (port, com_cfcr, cfcr);
    851  1.1  christos   return 0;
    852  1.1  christos }
    853  1.1  christos 
    854  1.1  christos 
    855  1.1  christos static const struct serial_ops dos_ops =
    856  1.1  christos {
    857  1.1  christos   "hardwire",
    858  1.1  christos   dos_open,
    859  1.1  christos   dos_close,
    860  1.1  christos   NULL,				/* fdopen, not implemented */
    861  1.1  christos   dos_readchar,
    862  1.1  christos   dos_write,
    863  1.1  christos   dos_noop,			/* flush output */
    864  1.1  christos   dos_flush_input,
    865  1.1  christos   dos_sendbreak,
    866  1.1  christos   dos_raw,
    867  1.1  christos   dos_get_tty_state,
    868  1.1  christos   dos_copy_tty_state,
    869  1.1  christos   dos_set_tty_state,
    870  1.1  christos   dos_print_tty_state,
    871  1.1  christos   dos_noflush_set_tty_state,
    872  1.1  christos   dos_setbaudrate,
    873  1.1  christos   dos_setstopbits,
    874  1.1  christos   dos_noop,			/* Wait for output to drain.  */
    875  1.1  christos   (void (*)(struct serial *, int))NULL	/* Change into async mode.  */
    876  1.1  christos };
    877  1.1  christos 
    878  1.1  christos int
    879  1.1  christos gdb_pipe (int pdes[2])
    880  1.1  christos {
    881  1.1  christos   /* No support for pipes.  */
    882  1.1  christos   errno = ENOSYS;
    883  1.1  christos   return -1;
    884  1.1  christos }
    885  1.1  christos 
    886  1.1  christos static void
    887  1.1  christos dos_info (char *arg, int from_tty)
    888  1.1  christos {
    889  1.1  christos   struct dos_ttystate *port;
    890  1.1  christos #ifdef DOS_STATS
    891  1.1  christos   int i;
    892  1.1  christos #endif
    893  1.1  christos 
    894  1.1  christos   for (port = ports; port < &ports[4]; port++)
    895  1.1  christos     {
    896  1.1  christos       if (port->baudrate == 0)
    897  1.1  christos 	continue;
    898  1.1  christos       printf_filtered ("Port:\tCOM%ld (%sactive)\n", (long)(port - ports) + 1,
    899  1.1  christos 		       port->intrupt ? "" : "not ");
    900  1.1  christos       printf_filtered ("Addr:\t0x%03x (irq %d)\n", port->base, port->irq);
    901  1.1  christos       printf_filtered ("16550:\t%s\n", port->fifo ? "yes" : "no");
    902  1.1  christos       printf_filtered ("Speed:\t%d baud\n", port->baudrate);
    903  1.1  christos       printf_filtered ("Errs:\tframing %d parity %d overflow %d\n\n",
    904  1.1  christos 		       port->ferr, port->perr, port->oflo);
    905  1.1  christos     }
    906  1.1  christos 
    907  1.1  christos #ifdef DOS_STATS
    908  1.1  christos   printf_filtered ("\nTotal interrupts: %d\n", intrcnt);
    909  1.1  christos   for (i = 0; i < NCNT; i++)
    910  1.1  christos     if (cnts[i])
    911  1.1  christos       printf_filtered ("%s:\t%lu\n", cntnames[i], (unsigned long) cnts[i]);
    912  1.1  christos #endif
    913  1.1  christos }
    914  1.1  christos 
    915  1.1  christos /* -Wmissing-prototypes */
    916  1.1  christos extern initialize_file_ftype _initialize_ser_dos;
    917  1.1  christos 
    918  1.1  christos void
    919  1.1  christos _initialize_ser_dos (void)
    920  1.1  christos {
    921  1.1  christos   serial_add_interface (&dos_ops);
    922  1.1  christos 
    923  1.1  christos   /* Save original interrupt mask register.  */
    924  1.1  christos   icu_oldmask = inportb (ICU_MASK);
    925  1.1  christos 
    926  1.1  christos   /* Mark fixed motherboard irqs as inuse.  */
    927  1.1  christos   intrupts[0].inuse =		/* timer tick */
    928  1.1  christos     intrupts[1].inuse =		/* keyboard */
    929  1.1  christos     intrupts[2].inuse = 1;	/* slave icu */
    930  1.1  christos 
    931  1.1  christos   add_setshow_zinteger_cmd ("com1base", class_obscure, &ports[0].base, _("\
    932  1.1  christos Set COM1 base i/o port address."), _("\
    933  1.1  christos Show COM1 base i/o port address."), NULL,
    934  1.1  christos 			    NULL,
    935  1.1  christos 			    NULL, /* FIXME: i18n: */
    936  1.1  christos 			    &setlist, &showlist);
    937  1.1  christos 
    938  1.1  christos   add_setshow_zinteger_cmd ("com1irq", class_obscure, &ports[0].irq, _("\
    939  1.1  christos Set COM1 interrupt request."), _("\
    940  1.1  christos Show COM1 interrupt request."), NULL,
    941  1.1  christos 			    NULL,
    942  1.1  christos 			    NULL, /* FIXME: i18n: */
    943  1.1  christos 			    &setlist, &showlist);
    944  1.1  christos 
    945  1.1  christos   add_setshow_zinteger_cmd ("com2base", class_obscure, &ports[1].base, _("\
    946  1.1  christos Set COM2 base i/o port address."), _("\
    947  1.1  christos Show COM2 base i/o port address."), NULL,
    948  1.1  christos 			    NULL,
    949  1.1  christos 			    NULL, /* FIXME: i18n: */
    950  1.1  christos 			    &setlist, &showlist);
    951  1.1  christos 
    952  1.1  christos   add_setshow_zinteger_cmd ("com2irq", class_obscure, &ports[1].irq, _("\
    953  1.1  christos Set COM2 interrupt request."), _("\
    954  1.1  christos Show COM2 interrupt request."), NULL,
    955  1.1  christos 			    NULL,
    956  1.1  christos 			    NULL, /* FIXME: i18n: */
    957  1.1  christos 			    &setlist, &showlist);
    958  1.1  christos 
    959  1.1  christos   add_setshow_zinteger_cmd ("com3base", class_obscure, &ports[2].base, _("\
    960  1.1  christos Set COM3 base i/o port address."), _("\
    961  1.1  christos Show COM3 base i/o port address."), NULL,
    962  1.1  christos 			    NULL,
    963  1.1  christos 			    NULL, /* FIXME: i18n: */
    964  1.1  christos 			    &setlist, &showlist);
    965  1.1  christos 
    966  1.1  christos   add_setshow_zinteger_cmd ("com3irq", class_obscure, &ports[2].irq, _("\
    967  1.1  christos Set COM3 interrupt request."), _("\
    968  1.1  christos Show COM3 interrupt request."), NULL,
    969  1.1  christos 			    NULL,
    970  1.1  christos 			    NULL, /* FIXME: i18n: */
    971  1.1  christos 			    &setlist, &showlist);
    972  1.1  christos 
    973  1.1  christos   add_setshow_zinteger_cmd ("com4base", class_obscure, &ports[3].base, _("\
    974  1.1  christos Set COM4 base i/o port address."), _("\
    975  1.1  christos Show COM4 base i/o port address."), NULL,
    976  1.1  christos 			    NULL,
    977  1.1  christos 			    NULL, /* FIXME: i18n: */
    978  1.1  christos 			    &setlist, &showlist);
    979  1.1  christos 
    980  1.1  christos   add_setshow_zinteger_cmd ("com4irq", class_obscure, &ports[3].irq, _("\
    981  1.1  christos Set COM4 interrupt request."), _("\
    982  1.1  christos Show COM4 interrupt request."), NULL,
    983  1.1  christos 			    NULL,
    984  1.1  christos 			    NULL, /* FIXME: i18n: */
    985  1.1  christos 			    &setlist, &showlist);
    986                
    987                  add_info ("serial", dos_info,
    988                	    _("Print DOS serial port status."));
    989                }
    990