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