gdb/ser-go32.c - gdb

Global variables defined

Data types defined

Functions defined

Macros defined

Source code

  1. /* Remote serial interface for local (hardwired) serial ports for GO32.
  2.    Copyright (C) 1992-2015 Free Software Foundation, Inc.

  3.    Contributed by Nigel Stephens, Algorithmics Ltd. (nigel@algor.co.uk).

  4.    This version uses DPMI interrupts to handle buffered i/o
  5.    without the separate "asynctsr" program.

  6.    This file is part of GDB.

  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 3 of the License, or
  10.    (at your option) any later version.

  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.

  15.    You should have received a copy of the GNU General Public License
  16.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  17. #include "defs.h"
  18. #include "gdbcmd.h"
  19. #include "serial.h"
  20. /*
  21. * NS16550 UART registers
  22. */

  23. #define COM1ADDR        0x3f8
  24. #define COM2ADDR        0x2f8
  25. #define COM3ADDR        0x3e8
  26. #define COM4ADDR        0x3e0

  27. #define        com_data        0        /* data register (R/W) */
  28. #define        com_dlbl        0        /* divisor latch low (W) */
  29. #define        com_ier                1        /* interrupt enable (W) */
  30. #define        com_dlbh        1        /* divisor latch high (W) */
  31. #define        com_iir                2        /* interrupt identification (R) */
  32. #define        com_fifo        2        /* FIFO control (W) */
  33. #define        com_lctl        3        /* line control register (R/W) */
  34. #define        com_cfcr        3        /* line control register (R/W) */
  35. #define        com_mcr                4        /* modem control register (R/W) */
  36. #define        com_lsr                5        /* line status register (R/W) */
  37. #define        com_msr                6        /* modem status register (R/W) */

  38. /*
  39. * Constants for computing 16 bit baud rate divisor (lower byte
  40. * in com_dlbl, upper in com_dlbh) from 1.8432MHz crystal.  Divisor is
  41. * 1.8432 MHz / (16 * X) for X bps.  If the baud rate can't be set
  42. * to within +- (desired_rate*SPEED_TOLERANCE/1000) bps, we fail.
  43. */
  44. #define COMTICK                (1843200/16)
  45. #define SPEED_TOLERANCE        30        /* thousandths; real == desired +- 3.0% */

  46. /* interrupt enable register */
  47. #define        IER_ERXRDY        0x1        /* int on rx ready */
  48. #define        IER_ETXRDY        0x2        /* int on tx ready */
  49. #define        IER_ERLS        0x4        /* int on line status change */
  50. #define        IER_EMSC        0x8        /* int on modem status change */

  51. /* interrupt identification register */
  52. #define        IIR_FIFO_MASK        0xc0        /* set if FIFOs are enabled */
  53. #define        IIR_IMASK        0xf        /* interrupt cause mask */
  54. #define        IIR_NOPEND        0x1        /* nothing pending */
  55. #define        IIR_RLS                0x6        /* receive line status */
  56. #define        IIR_RXRDY        0x4        /* receive ready */
  57. #define        IIR_RXTOUT        0xc        /* receive timeout */
  58. #define        IIR_TXRDY        0x2        /* transmit ready */
  59. #define        IIR_MLSC        0x0        /* modem status */


  60. /* fifo control register */
  61. #define        FIFO_ENABLE        0x01        /* enable fifo */
  62. #define        FIFO_RCV_RST        0x02        /* reset receive fifo */
  63. #define        FIFO_XMT_RST        0x04        /* reset transmit fifo */
  64. #define        FIFO_DMA_MODE        0x08        /* enable dma mode */
  65. #define        FIFO_TRIGGER_1        0x00        /* trigger at 1 char */
  66. #define        FIFO_TRIGGER_4        0x40        /* trigger at 4 chars */
  67. #define        FIFO_TRIGGER_8        0x80        /* trigger at 8 chars */
  68. #define        FIFO_TRIGGER_14        0xc0        /* trigger at 14 chars */

  69. /* character format control register */
  70. #define        CFCR_DLAB        0x80        /* divisor latch */
  71. #define        CFCR_SBREAK        0x40        /* send break */
  72. #define        CFCR_PZERO        0x30        /* zero parity */
  73. #define        CFCR_PONE        0x20        /* one parity */
  74. #define        CFCR_PEVEN        0x10        /* even parity */
  75. #define        CFCR_PODD        0x00        /* odd parity */
  76. #define        CFCR_PENAB        0x08        /* parity enable */
  77. #define        CFCR_STOPB        0x04        /* 2 stop bits */
  78. #define        CFCR_8BITS        0x03        /* 8 data bits */
  79. #define        CFCR_7BITS        0x02        /* 7 data bits */
  80. #define        CFCR_6BITS        0x01        /* 6 data bits */
  81. #define        CFCR_5BITS        0x00        /* 5 data bits */

  82. /* modem control register */
  83. #define        MCR_LOOPBACK        0x10        /* loopback */
  84. #define        MCR_IENABLE        0x08        /* output 2 = int enable */
  85. #define        MCR_DRS                0x04        /* output 1 = xxx */
  86. #define        MCR_RTS                0x02        /* enable RTS */
  87. #define        MCR_DTR                0x01        /* enable DTR */

  88. /* line status register */
  89. #define        LSR_RCV_FIFO        0x80        /* error in receive fifo */
  90. #define        LSR_TSRE        0x40        /* transmitter empty */
  91. #define        LSR_TXRDY        0x20        /* transmitter ready */
  92. #define        LSR_BI                0x10        /* break detected */
  93. #define        LSR_FE                0x08        /* framing error */
  94. #define        LSR_PE                0x04        /* parity error */
  95. #define        LSR_OE                0x02        /* overrun error */
  96. #define        LSR_RXRDY        0x01        /* receiver ready */
  97. #define        LSR_RCV_MASK        0x1f

  98. /* modem status register */
  99. #define        MSR_DCD                0x80
  100. #define        MSR_RI                0x40
  101. #define        MSR_DSR                0x20
  102. #define        MSR_CTS                0x10
  103. #define        MSR_DDCD        0x08
  104. #define        MSR_TERI        0x04
  105. #define        MSR_DDSR        0x02
  106. #define        MSR_DCTS        0x01

  107. #include <time.h>
  108. #include <dos.h>
  109. #include <go32.h>
  110. #include <dpmi.h>
  111. typedef unsigned long u_long;

  112. /* 16550 rx fifo trigger point */
  113. #define FIFO_TRIGGER        FIFO_TRIGGER_4

  114. /* input buffer size */
  115. #define CBSIZE        4096

  116. #define RAWHZ        18

  117. #ifdef DOS_STATS
  118. #define CNT_RX                16
  119. #define CNT_TX                17
  120. #define CNT_STRAY        18
  121. #define CNT_ORUN        19
  122. #define NCNT                20

  123. static int intrcnt;
  124. static size_t cnts[NCNT];
  125. static char *cntnames[NCNT] =
  126. {
  127.   /* h/w interrupt counts.  */
  128.   "mlsc", "nopend", "txrdy", "?3",
  129.   "rxrdy", "?5", "rls", "?7",
  130.   "?8", "?9", "?a", "?b",
  131.   "rxtout", "?d", "?e", "?f",
  132.   /* s/w counts.  */
  133.   "rxcnt", "txcnt", "stray", "swoflo"
  134. };

  135. #define COUNT(x) cnts[x]++
  136. #else
  137. #define COUNT(x)
  138. #endif

  139. /* Main interrupt controller port addresses.  */
  140. #define ICU_BASE        0x20
  141. #define ICU_OCW2        (ICU_BASE + 0)
  142. #define ICU_MASK        (ICU_BASE + 1)

  143. /* Original interrupt controller mask register.  */
  144. unsigned char icu_oldmask;

  145. /* Maximum of 8 interrupts (we don't handle the slave icu yet).  */
  146. #define NINTR        8

  147. static struct intrupt
  148.   {
  149.     char inuse;
  150.     struct dos_ttystate *port;
  151.     _go32_dpmi_seginfo old_rmhandler;
  152.     _go32_dpmi_seginfo old_pmhandler;
  153.     _go32_dpmi_seginfo new_rmhandler;
  154.     _go32_dpmi_seginfo new_pmhandler;
  155.     _go32_dpmi_registers regs;
  156.   }
  157. intrupts[NINTR];


  158. static struct dos_ttystate
  159.   {
  160.     int base;
  161.     int irq;
  162.     int refcnt;
  163.     struct intrupt *intrupt;
  164.     int fifo;
  165.     int baudrate;
  166.     unsigned char cbuf[CBSIZE];
  167.     unsigned int first;
  168.     unsigned int count;
  169.     int txbusy;
  170.     unsigned char old_mcr;
  171.     int ferr;
  172.     int perr;
  173.     int oflo;
  174.     int msr;
  175.   }
  176. ports[4] =
  177. {
  178.   {
  179.     COM1ADDR, 4, 0, NULL, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0
  180.   }
  181.   ,
  182.   {
  183.     COM2ADDR, 3, 0, NULL, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0
  184.   }
  185.   ,
  186.   {
  187.     COM3ADDR, 4, 0, NULL, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0
  188.   }
  189.   ,
  190.   {
  191.     COM4ADDR, 3, 0, NULL, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0
  192.   }
  193. };

  194. static int dos_open (struct serial *scb, const char *name);
  195. static void dos_raw (struct serial *scb);
  196. static int dos_readchar (struct serial *scb, int timeout);
  197. static int dos_setbaudrate (struct serial *scb, int rate);
  198. static int dos_write (struct serial *scb, const void *buf, size_t count);
  199. static void dos_close (struct serial *scb);
  200. static serial_ttystate dos_get_tty_state (struct serial *scb);
  201. static int dos_set_tty_state (struct serial *scb, serial_ttystate state);
  202. static int dos_baudconv (int rate);

  203. #define inb(p,a)        inportb((p)->base + (a))
  204. #define outb(p,a,v)        outportb((p)->base + (a), (v))
  205. #define disable()        asm volatile ("cli");
  206. #define enable()        asm volatile ("sti");


  207. static int
  208. dos_getc (volatile struct dos_ttystate *port)
  209. {
  210.   int c;

  211.   if (port->count == 0)
  212.     return -1;

  213.   c = port->cbuf[port->first];
  214.   disable ();
  215.   port->first = (port->first + 1) & (CBSIZE - 1);
  216.   port->count--;
  217.   enable ();
  218.   return c;
  219. }


  220. static int
  221. dos_putc (int c, struct dos_ttystate *port)
  222. {
  223.   if (port->count >= CBSIZE - 1)
  224.     return -1;
  225.   port->cbuf[(port->first + port->count) & (CBSIZE - 1)] = c;
  226.   port->count++;
  227.   return 0;
  228. }



  229. static void
  230. dos_comisr (int irq)
  231. {
  232.   struct dos_ttystate *port;
  233.   unsigned char iir, lsr, c;

  234.   disable ();                        /* Paranoia */
  235.   outportb (ICU_OCW2, 0x20);        /* End-Of-Interrupt */
  236. #ifdef DOS_STATS
  237.   ++intrcnt;
  238. #endif

  239.   port = intrupts[irq].port;
  240.   if (!port)
  241.     {
  242.       COUNT (CNT_STRAY);
  243.       return;                        /* not open */
  244.     }

  245.   while (1)
  246.     {
  247.       iir = inb (port, com_iir) & IIR_IMASK;
  248.       switch (iir)
  249.         {

  250.         case IIR_RLS:
  251.           lsr = inb (port, com_lsr);
  252.           goto rx;

  253.         case IIR_RXTOUT:
  254.         case IIR_RXRDY:
  255.           lsr = 0;

  256.         rx:
  257.           do
  258.             {
  259.               c = inb (port, com_data);
  260.               if (lsr & (LSR_BI | LSR_FE | LSR_PE | LSR_OE))
  261.                 {
  262.                   if (lsr & (LSR_BI | LSR_FE))
  263.                     port->ferr++;
  264.                   else if (lsr & LSR_PE)
  265.                     port->perr++;
  266.                   if (lsr & LSR_OE)
  267.                     port->oflo++;
  268.                 }

  269.               if (dos_putc (c, port) < 0)
  270.                 {
  271.                   COUNT (CNT_ORUN);
  272.                 }
  273.               else
  274.                 {
  275.                   COUNT (CNT_RX);
  276.                 }
  277.             }
  278.           while ((lsr = inb (port, com_lsr)) & LSR_RXRDY);
  279.           break;

  280.         case IIR_MLSC:
  281.           /* could be used to flowcontrol Tx */
  282.           port->msr = inb (port, com_msr);
  283.           break;

  284.         case IIR_TXRDY:
  285.           port->txbusy = 0;
  286.           break;

  287.         case IIR_NOPEND:
  288.           /* No more pending interrupts, all done.  */
  289.           return;

  290.         default:
  291.           /* Unexpected interrupt, ignore.  */
  292.           break;
  293.         }
  294.       COUNT (iir);
  295.     }
  296. }

  297. #define ISRNAME(x) dos_comisr##x
  298. #define ISR(x) static void ISRNAME(x)(void) {dos_comisr(x);}

  299. ISR (0) ISR (1) ISR (2) ISR (3) /* OK */
  300. ISR (4) ISR (5) ISR (6) ISR (7) /* OK */

  301. typedef void (*isr_t) (void);

  302. static isr_t isrs[NINTR] =
  303.   {
  304.        ISRNAME (0), ISRNAME (1), ISRNAME (2), ISRNAME (3),
  305.        ISRNAME (4), ISRNAME (5), ISRNAME (6), ISRNAME (7)
  306.   };



  307. static struct intrupt *
  308. dos_hookirq (unsigned int irq)
  309. {
  310.   struct intrupt *intr;
  311.   unsigned int vec;
  312.   isr_t isr;

  313.   if (irq >= NINTR)
  314.     return 0;

  315.   intr = &intrupts[irq];
  316.   if (intr->inuse)
  317.     return 0;

  318.   vec = 0x08 + irq;
  319.   isr = isrs[irq];

  320.   /* Setup real mode handler.  */
  321.   _go32_dpmi_get_real_mode_interrupt_vector (vec, &intr->old_rmhandler);

  322.   intr->new_rmhandler.pm_selector = _go32_my_cs ();
  323.   intr->new_rmhandler.pm_offset = (u_long) isr;
  324.   if (_go32_dpmi_allocate_real_mode_callback_iret (&intr->new_rmhandler,
  325.                                                    &intr->regs))
  326.     {
  327.       return 0;
  328.     }

  329.   if (_go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->new_rmhandler))
  330.     {
  331.       return 0;
  332.     }

  333.   /* Setup protected mode handler.  */
  334.   _go32_dpmi_get_protected_mode_interrupt_vector (vec, &intr->old_pmhandler);

  335.   intr->new_pmhandler.pm_selector = _go32_my_cs ();
  336.   intr->new_pmhandler.pm_offset = (u_long) isr;
  337.   _go32_dpmi_allocate_iret_wrapper (&intr->new_pmhandler);

  338.   if (_go32_dpmi_set_protected_mode_interrupt_vector (vec,
  339.                                                       &intr->new_pmhandler))
  340.     {
  341.       return 0;
  342.     }

  343.   /* Setup interrupt controller mask.  */
  344.   disable ();
  345.   outportb (ICU_MASK, inportb (ICU_MASK) & ~(1 << irq));
  346.   enable ();

  347.   intr->inuse = 1;
  348.   return intr;
  349. }


  350. static void
  351. dos_unhookirq (struct intrupt *intr)
  352. {
  353.   unsigned int irq, vec;
  354.   unsigned char mask;

  355.   irq = intr - intrupts;
  356.   vec = 0x08 + irq;

  357.   /* Restore old interrupt mask bit.  */
  358.   mask = 1 << irq;
  359.   disable ();
  360.   outportb (ICU_MASK, inportb (ICU_MASK) | (mask & icu_oldmask));
  361.   enable ();

  362.   /* Remove real mode handler.  */
  363.   _go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->old_rmhandler);
  364.   _go32_dpmi_free_real_mode_callback (&intr->new_rmhandler);

  365.   /* Remove protected mode handler.  */
  366.   _go32_dpmi_set_protected_mode_interrupt_vector (vec, &intr->old_pmhandler);
  367.   _go32_dpmi_free_iret_wrapper (&intr->new_pmhandler);
  368.   intr->inuse = 0;
  369. }



  370. static int
  371. dos_open (struct serial *scb, const char *name)
  372. {
  373.   struct dos_ttystate *port;
  374.   int fd, i;

  375.   if (strncasecmp (name, "/dev/", 5) == 0)
  376.     name += 5;
  377.   else if (strncasecmp (name, "\\dev\\", 5) == 0)
  378.     name += 5;

  379.   if (strlen (name) != 4 || strncasecmp (name, "com", 3) != 0)
  380.     {
  381.       errno = ENOENT;
  382.       return -1;
  383.     }

  384.   if (name[3] < '1' || name[3] > '4')
  385.     {
  386.       errno = ENOENT;
  387.       return -1;
  388.     }

  389.   /* FIXME: this is a Bad Idea (tm)!  One should *never* invent file
  390.      handles, since they might be already used by other files/devices.
  391.      The Right Way to do this is to create a real handle by dup()'ing
  392.      some existing one.  */
  393.   fd = name[3] - '1';
  394.   port = &ports[fd];
  395.   if (port->refcnt++ > 0)
  396.     {
  397.       /* Device already opened another user.  Just point at it.  */
  398.       scb->fd = fd;
  399.       return 0;
  400.     }

  401.   /* Force access to ID reg.  */
  402.   outb (port, com_cfcr, 0);
  403.   outb (port, com_iir, 0);
  404.   for (i = 0; i < 17; i++)
  405.     {
  406.       if ((inb (port, com_iir) & 0x38) == 0)
  407.         goto ok;
  408.       (void) inb (port, com_data);        /* clear recv */
  409.     }
  410.   errno = ENODEV;
  411.   return -1;

  412. ok:
  413.   /* Disable all interrupts in chip.  */
  414.   outb (port, com_ier, 0);

  415.   /* Tentatively enable 16550 fifo, and see if it responds.  */
  416.   outb (port, com_fifo,
  417.         FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER);
  418.   sleep (1);
  419.   port->fifo = ((inb (port, com_iir) & IIR_FIFO_MASK) == IIR_FIFO_MASK);

  420.   /* clear pending status reports.  */
  421.   (void) inb (port, com_lsr);
  422.   (void) inb (port, com_msr);

  423.   /* Enable external interrupt gate (to avoid floating IRQ).  */
  424.   outb (port, com_mcr, MCR_IENABLE);

  425.   /* Hook up interrupt handler and initialise icu.  */
  426.   port->intrupt = dos_hookirq (port->irq);
  427.   if (!port->intrupt)
  428.     {
  429.       outb (port, com_mcr, 0);
  430.       outb (port, com_fifo, 0);
  431.       errno = ENODEV;
  432.       return -1;
  433.     }

  434.   disable ();

  435.   /* record port */
  436.   port->intrupt->port = port;
  437.   scb->fd = fd;

  438.   /* Clear rx buffer, tx busy flag and overflow count.  */
  439.   port->first = port->count = 0;
  440.   port->txbusy = 0;
  441.   port->oflo = 0;

  442.   /* Set default baud rate and mode: 9600,8,n,1 */
  443.   i = dos_baudconv (port->baudrate = 9600);
  444.   outb (port, com_cfcr, CFCR_DLAB);
  445.   outb (port, com_dlbl, i & 0xff);
  446.   outb (port, com_dlbh, i >> 8);
  447.   outb (port, com_cfcr, CFCR_8BITS);

  448.   /* Enable all interrupts.  */
  449.   outb (port, com_ier, IER_ETXRDY | IER_ERXRDY | IER_ERLS | IER_EMSC);

  450.   /* Enable DTR & RTS.  */
  451.   outb (port, com_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);

  452.   enable ();

  453.   return 0;
  454. }


  455. static void
  456. dos_close (struct serial *scb)
  457. {
  458.   struct dos_ttystate *port;
  459.   struct intrupt *intrupt;

  460.   if (!scb)
  461.     return;

  462.   port = &ports[scb->fd];

  463.   if (port->refcnt-- > 1)
  464.     return;

  465.   if (!(intrupt = port->intrupt))
  466.     return;

  467.   /* Disable interrupts, fifo, flow control.  */
  468.   disable ();
  469.   port->intrupt = 0;
  470.   intrupt->port = 0;
  471.   outb (port, com_fifo, 0);
  472.   outb (port, com_ier, 0);
  473.   enable ();

  474.   /* Unhook handler, and disable interrupt gate.  */
  475.   dos_unhookirq (intrupt);
  476.   outb (port, com_mcr, 0);

  477.   /* Check for overflow errors.  */
  478.   if (port->oflo)
  479.     {
  480.       fprintf_unfiltered (gdb_stderr,
  481.                           "Serial input overruns occurred.\n");
  482.       fprintf_unfiltered (gdb_stderr, "This system %s handle %d baud.\n",
  483.                           port->fifo ? "cannot" : "needs a 16550 to",
  484.                           port->baudrate);
  485.     }
  486. }



  487. static int
  488. dos_noop (struct serial *scb)
  489. {
  490.   return 0;
  491. }

  492. static void
  493. dos_raw (struct serial *scb)
  494. {
  495.   /* Always in raw mode.  */
  496. }

  497. static int
  498. dos_readchar (struct serial *scb, int timeout)
  499. {
  500.   struct dos_ttystate *port = &ports[scb->fd];
  501.   long then;
  502.   int c;

  503.   then = rawclock () + (timeout * RAWHZ);
  504.   while ((c = dos_getc (port)) < 0)
  505.     {
  506.       if (timeout >= 0 && (rawclock () - then) >= 0)
  507.         return SERIAL_TIMEOUT;
  508.     }

  509.   return c;
  510. }


  511. static serial_ttystate
  512. dos_get_tty_state (struct serial *scb)
  513. {
  514.   struct dos_ttystate *port = &ports[scb->fd];
  515.   struct dos_ttystate *state;

  516.   /* Are they asking about a port we opened?  */
  517.   if (port->refcnt <= 0)
  518.     {
  519.       /* We've never heard about this port.  We should fail this call,
  520.          unless they are asking about one of the 3 standard handles,
  521.          in which case we pretend the handle was open by us if it is
  522.          connected to a terminal device.  This is beacuse Unix
  523.          terminals use the serial interface, so GDB expects the
  524.          standard handles to go through here.  */
  525.       if (scb->fd >= 3 || !isatty (scb->fd))
  526.         return NULL;
  527.     }

  528.   state = (struct dos_ttystate *) xmalloc (sizeof *state);
  529.   *state = *port;
  530.   return (serial_ttystate) state;
  531. }

  532. static serial_ttystate
  533. dos_copy_tty_state (struct serial *scb, serial_ttystate ttystate)
  534. {
  535.   struct dos_ttystate *state;

  536.   state = (struct dos_ttystate *) xmalloc (sizeof *state);
  537.   *state = *(struct dos_ttystate *) ttystate;

  538.   return (serial_ttystate) state;
  539. }

  540. static int
  541. dos_set_tty_state (struct serial *scb, serial_ttystate ttystate)
  542. {
  543.   struct dos_ttystate *state;

  544.   state = (struct dos_ttystate *) ttystate;
  545.   dos_setbaudrate (scb, state->baudrate);
  546.   return 0;
  547. }

  548. static int
  549. dos_noflush_set_tty_state (struct serial *scb, serial_ttystate new_ttystate,
  550.                            serial_ttystate old_ttystate)
  551. {
  552.   struct dos_ttystate *state;

  553.   state = (struct dos_ttystate *) new_ttystate;
  554.   dos_setbaudrate (scb, state->baudrate);
  555.   return 0;
  556. }

  557. static int
  558. dos_flush_input (struct serial *scb)
  559. {
  560.   struct dos_ttystate *port = &ports[scb->fd];

  561.   disable ();
  562.   port->first = port->count = 0;
  563.   if (port->fifo)
  564.     outb (port, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_TRIGGER);
  565.   enable ();
  566.   return 0;
  567. }

  568. static void
  569. dos_print_tty_state (struct serial *scb, serial_ttystate ttystate,
  570.                      struct ui_file *stream)
  571. {
  572.   /* Nothing to print.  */
  573.   return;
  574. }

  575. static int
  576. dos_baudconv (int rate)
  577. {
  578.   long x, err;

  579.   if (rate <= 0)
  580.     return -1;

  581. #define divrnd(n, q)        (((n) * 2 / (q) + 1) / 2) /* Divide and round off.  */
  582.   x = divrnd (COMTICK, rate);
  583.   if (x <= 0)
  584.     return -1;

  585.   err = divrnd (1000 * COMTICK, x * rate) - 1000;
  586.   if (err < 0)
  587.     err = -err;
  588.   if (err > SPEED_TOLERANCE)
  589.     return -1;
  590. #undef divrnd
  591.   return x;
  592. }


  593. static int
  594. dos_setbaudrate (struct serial *scb, int rate)
  595. {
  596.   struct dos_ttystate *port = &ports[scb->fd];

  597.   if (port->baudrate != rate)
  598.     {
  599.       int x;
  600.       unsigned char cfcr;

  601.       x = dos_baudconv (rate);
  602.       if (x <= 0)
  603.         {
  604.           fprintf_unfiltered (gdb_stderr, "%d: impossible baudrate\n", rate);
  605.           errno = EINVAL;
  606.           return -1;
  607.         }

  608.       disable ();
  609.       cfcr = inb (port, com_cfcr);

  610.       outb (port, com_cfcr, CFCR_DLAB);
  611.       outb (port, com_dlbl, x & 0xff);
  612.       outb (port, com_dlbh, x >> 8);
  613.       outb (port, com_cfcr, cfcr);
  614.       port->baudrate = rate;
  615.       enable ();
  616.     }

  617.   return 0;
  618. }

  619. static int
  620. dos_setstopbits (struct serial *scb, int num)
  621. {
  622.   struct dos_ttystate *port = &ports[scb->fd];
  623.   unsigned char cfcr;

  624.   disable ();
  625.   cfcr = inb (port, com_cfcr);

  626.   switch (num)
  627.     {
  628.     case SERIAL_1_STOPBITS:
  629.       outb (port, com_cfcr, cfcr & ~CFCR_STOPB);
  630.       break;
  631.     case SERIAL_1_AND_A_HALF_STOPBITS:
  632.     case SERIAL_2_STOPBITS:
  633.       outb (port, com_cfcr, cfcr | CFCR_STOPB);
  634.       break;
  635.     default:
  636.       enable ();
  637.       return 1;
  638.     }
  639.   enable ();

  640.   return 0;
  641. }

  642. static int
  643. dos_write (struct serial *scb, const void *buf, size_t count)
  644. {
  645.   volatile struct dos_ttystate *port = &ports[scb->fd];
  646.   size_t fifosize = port->fifo ? 16 : 1;
  647.   long then;
  648.   size_t cnt;
  649.   const char *str = buf;

  650.   while (count > 0)
  651.     {
  652.       /* Send the data, fifosize bytes at a time.  */
  653.       cnt = fifosize > count ? count : fifosize;
  654.       port->txbusy = 1;
  655.       /* Francisco Pastor <fpastor.etra-id@etra.es> says OUTSB messes
  656.          up the communications with UARTs with FIFOs.  */
  657. #ifdef UART_FIFO_WORKS
  658.       outportsb (port->base + com_data, str, cnt);
  659.       str += cnt;
  660.       count -= cnt;
  661. #else
  662.       for ( ; cnt > 0; cnt--, count--)
  663.         outportb (port->base + com_data, *str++);
  664. #endif
  665. #ifdef DOS_STATS
  666.       cnts[CNT_TX] += cnt;
  667. #endif
  668.       /* Wait for transmission to complete (max 1 sec).  */
  669.       then = rawclock () + RAWHZ;
  670.       while (port->txbusy)
  671.         {
  672.           if ((rawclock () - then) >= 0)
  673.             {
  674.               errno = EIO;
  675.               return SERIAL_ERROR;
  676.             }
  677.         }
  678.     }
  679.   return 0;
  680. }


  681. static int
  682. dos_sendbreak (struct serial *scb)
  683. {
  684.   volatile struct dos_ttystate *port = &ports[scb->fd];
  685.   unsigned char cfcr;
  686.   long then;

  687.   cfcr = inb (port, com_cfcr);
  688.   outb (port, com_cfcr, cfcr | CFCR_SBREAK);

  689.   /* 0.25 sec delay */
  690.   then = rawclock () + RAWHZ / 4;
  691.   while ((rawclock () - then) < 0)
  692.     continue;

  693.   outb (port, com_cfcr, cfcr);
  694.   return 0;
  695. }


  696. static const struct serial_ops dos_ops =
  697. {
  698.   "hardwire",
  699.   dos_open,
  700.   dos_close,
  701.   NULL,                                /* fdopen, not implemented */
  702.   dos_readchar,
  703.   dos_write,
  704.   dos_noop,                        /* flush output */
  705.   dos_flush_input,
  706.   dos_sendbreak,
  707.   dos_raw,
  708.   dos_get_tty_state,
  709.   dos_copy_tty_state,
  710.   dos_set_tty_state,
  711.   dos_print_tty_state,
  712.   dos_noflush_set_tty_state,
  713.   dos_setbaudrate,
  714.   dos_setstopbits,
  715.   dos_noop,                        /* Wait for output to drain.  */
  716.   (void (*)(struct serial *, int))NULL        /* Change into async mode.  */
  717. };

  718. int
  719. gdb_pipe (int pdes[2])
  720. {
  721.   /* No support for pipes.  */
  722.   errno = ENOSYS;
  723.   return -1;
  724. }

  725. static void
  726. dos_info (char *arg, int from_tty)
  727. {
  728.   struct dos_ttystate *port;
  729. #ifdef DOS_STATS
  730.   int i;
  731. #endif

  732.   for (port = ports; port < &ports[4]; port++)
  733.     {
  734.       if (port->baudrate == 0)
  735.         continue;
  736.       printf_filtered ("Port:\tCOM%ld (%sactive)\n", (long)(port - ports) + 1,
  737.                        port->intrupt ? "" : "not ");
  738.       printf_filtered ("Addr:\t0x%03x (irq %d)\n", port->base, port->irq);
  739.       printf_filtered ("16550:\t%s\n", port->fifo ? "yes" : "no");
  740.       printf_filtered ("Speed:\t%d baud\n", port->baudrate);
  741.       printf_filtered ("Errs:\tframing %d parity %d overflow %d\n\n",
  742.                        port->ferr, port->perr, port->oflo);
  743.     }

  744. #ifdef DOS_STATS
  745.   printf_filtered ("\nTotal interrupts: %d\n", intrcnt);
  746.   for (i = 0; i < NCNT; i++)
  747.     if (cnts[i])
  748.       printf_filtered ("%s:\t%lu\n", cntnames[i], (unsigned long) cnts[i]);
  749. #endif
  750. }

  751. /* -Wmissing-prototypes */
  752. extern initialize_file_ftype _initialize_ser_dos;

  753. void
  754. _initialize_ser_dos (void)
  755. {
  756.   serial_add_interface (&dos_ops);

  757.   /* Save original interrupt mask register.  */
  758.   icu_oldmask = inportb (ICU_MASK);

  759.   /* Mark fixed motherboard irqs as inuse.  */
  760.   intrupts[0].inuse =                /* timer tick */
  761.     intrupts[1].inuse =                /* keyboard */
  762.     intrupts[2].inuse = 1;        /* slave icu */

  763.   add_setshow_zinteger_cmd ("com1base", class_obscure, &ports[0].base, _("\
  764. Set COM1 base i/o port address."), _("\
  765. Show COM1 base i/o port address."), NULL,
  766.                             NULL,
  767.                             NULL, /* FIXME: i18n: */
  768.                             &setlist, &showlist);

  769.   add_setshow_zinteger_cmd ("com1irq", class_obscure, &ports[0].irq, _("\
  770. Set COM1 interrupt request."), _("\
  771. Show COM1 interrupt request."), NULL,
  772.                             NULL,
  773.                             NULL, /* FIXME: i18n: */
  774.                             &setlist, &showlist);

  775.   add_setshow_zinteger_cmd ("com2base", class_obscure, &ports[1].base, _("\
  776. Set COM2 base i/o port address."), _("\
  777. Show COM2 base i/o port address."), NULL,
  778.                             NULL,
  779.                             NULL, /* FIXME: i18n: */
  780.                             &setlist, &showlist);

  781.   add_setshow_zinteger_cmd ("com2irq", class_obscure, &ports[1].irq, _("\
  782. Set COM2 interrupt request."), _("\
  783. Show COM2 interrupt request."), NULL,
  784.                             NULL,
  785.                             NULL, /* FIXME: i18n: */
  786.                             &setlist, &showlist);

  787.   add_setshow_zinteger_cmd ("com3base", class_obscure, &ports[2].base, _("\
  788. Set COM3 base i/o port address."), _("\
  789. Show COM3 base i/o port address."), NULL,
  790.                             NULL,
  791.                             NULL, /* FIXME: i18n: */
  792.                             &setlist, &showlist);

  793.   add_setshow_zinteger_cmd ("com3irq", class_obscure, &ports[2].irq, _("\
  794. Set COM3 interrupt request."), _("\
  795. Show COM3 interrupt request."), NULL,
  796.                             NULL,
  797.                             NULL, /* FIXME: i18n: */
  798.                             &setlist, &showlist);

  799.   add_setshow_zinteger_cmd ("com4base", class_obscure, &ports[3].base, _("\
  800. Set COM4 base i/o port address."), _("\
  801. Show COM4 base i/o port address."), NULL,
  802.                             NULL,
  803.                             NULL, /* FIXME: i18n: */
  804.                             &setlist, &showlist);

  805.   add_setshow_zinteger_cmd ("com4irq", class_obscure, &ports[3].irq, _("\
  806. Set COM4 interrupt request."), _("\
  807. Show COM4 interrupt request."), NULL,
  808.                             NULL,
  809.                             NULL, /* FIXME: i18n: */
  810.                             &setlist, &showlist);

  811.   add_info ("serial", dos_info,
  812.             _("Print DOS serial port status."));
  813. }