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