Watt-32 tcp/ip  2.2 dev-rel.10
rs232.c
Go to the documentation of this file.
1 
8 #include <stdio.h>
9 #include <stdarg.h>
10 
11 #include "wattcp.h"
12 #include "strings.h"
13 #include "language.h"
14 #include "ioport.h"
15 #include "misc.h"
16 #include "timer.h"
17 #include "rs232.h"
18 
19 #if defined(USE_RS232_DBG)
20 
21 /* Offsets from base address 'trace2com_base'
22  */
23 #define TXRX_REG 0 /* Transmit/Receive Register */
24 #define IER_REG 1 /* Interrupt Enable Register */
25 #define BAUD_LSB_REG 0 /* LSB baudrate when LCR bit 7 is set */
26 #define BAUD_MSB_REG 1 /* MSB baudrate when LCR bit 7 is set */
27 #define IIR_REG 2 /* Interrupt Identification Register */
28 #define FIFO_REG 2 /* 16550 FIFO control Register */
29 
30 #define LCR_REG 3 /* Line Control Register */
31 #define MCR_REG 4 /* Modem Control Register */
32 #define LSR_REG 5 /* Line Status Register */
33  #define LSR_THRE 0x20 /* Tx holding reg. empty */
34 
35 static DWORD trace2com_speed = 115200UL;
36 static int trace2com_base = 0;
37 static int trace2com_fifoSize_1 = 0;
38 static int trace2com_stdPorts [4] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
39 
40 /*
41  * ___trace2com() - Strings passed here are dumped to the set-up serial
42  * "com" port. If the string is < 16 chars long, it will fit into the
43  * 16550 UARTs FIFO and will not cause any significant delay.
44  * No interrupts are used, so this will not interfere with anything
45  * else that might be happening.
46  */
47 int MS_CDECL __trace2com (const char *fmt, ...)
48 {
49  int fifoLeft = 0; /* Assume TX FIFO is full on first round -> force check */
50  char buf [256];
51  int len, i;
52  va_list args;
53 
54  if (trace2com_base <= 0) /* Not yet initialized */
55  return (0);
56 
57  va_start (args, fmt);
58 
59 #if defined(VSNPRINTF)
60  len = VSNPRINTF (buf, sizeof(buf)-1, fmt, args);
61  if (len < 0 || len >= SIZEOF(buf)-1)
62  {
63  outsnl (_LANG("ERROR: __trace2com() overrun"));
64  len = sizeof(buf)-1;
65  buf [len] = '\0';
66  }
67 #else
68  len = vsprintf (buf, fmt, args);
69  if (len > SIZEOF(buf)) /* harm already done, but better than no test */
70  {
71  outsnl (_LANG("ERROR: __trace2com() overrun"));
72  return (0);
73  }
74 #endif
75 
76  for (i = 0; i < len; i++)
77  {
78  DWORD to = set_timeout (400000/trace2com_speed); /* 10ms at 38kB/s */
79 
80  if (--fifoLeft < 0) /* Is the TX FIFO full? */
81  {
82  /* Wait until THRE or TX FIFO empty
83  */
84  while (!(_inportb (trace2com_base+LSR_REG) & LSR_THRE))
85  {
86  if (chk_timeout(to))
87  return (i);
88  }
89  fifoLeft = trace2com_fifoSize_1; /* Now we can fill it up again */
90  }
91  _outportb (trace2com_base+TXRX_REG, buf[i]);
92  }
93 
94  if (--fifoLeft < 0)
95  {
96  DWORD to = set_timeout (400000/trace2com_speed);
97 
98  /* Wait until THRE or TX FIFO empty
99  */
100  while (!(_inportb (trace2com_base+LSR_REG) & LSR_THRE))
101  {
102  if (chk_timeout(to))
103  return (len);
104  }
105  }
106  _outportb (trace2com_base+TXRX_REG, '\r');
107  _outportb (trace2com_base+TXRX_REG, '\n');
108  return (len+2);
109 }
110 
111 /*
112  * trace2com_init() - Public initialisation
113  */
114 int trace2com_init (WORD portAddress, DWORD baudRate)
115 {
116  BYTE Lsb, Msb;
117  WORD base;
118  DWORD div;
119 
120  /* Check/get UART address
121  */
122  if (portAddress < 1 || portAddress > 4)
123  return (0);
124 
125  base = trace2com_stdPorts [portAddress-1];
126 
127  /* See if the chip is actually there and ready
128  */
129  if (_inportb (base+IER_REG) == 0xFF) /* Nothing here */
130  return (0);
131 
132  if ((_inportb (base+IER_REG) & 0x0F) != 0x00)
133  return (0); /* UART is already in use by another program */
134 
135  _outportb (base+IER_REG, 0); /* disable all interrupts */
136  if (_inportb (base+IER_REG) != 0)
137  return (0); /* Whatever is here is not an UART */
138 
139  /* Set up UARTs registers
140  */
141  div = 115200UL / baudRate;
142  Msb = div >> 8;
143  Lsb = (div << 8) >> 8;
144 
145  _outportb (base+LCR_REG, 0x80); /* Turn address latch on */
146  _outportb (base+BAUD_LSB_REG, Lsb);
147  _outportb (base+BAUD_MSB_REG, Msb);
148  _outportb (base+LCR_REG, 0x00); /* Turn address latch off (again) */
149 
150  _outportb (base+IER_REG, 0x00); /* No interrupts, we use polling */
151  _outportb (base+FIFO_REG, 0x01|0x08); /* Activate FIFO @ MODE 2 */
152  _outportb (base+LCR_REG , 0x03); /* 8, N, 1 */
153  _outportb (base+MCR_REG, 0x03); /* DTR + DTS on */
154 
155  /* Check chip type, gives us the FIFO size
156  */
157  _outportb (base + FIFO_REG, 0x11);
158  Lsb = _inportb (base + FIFO_REG);
159 
160  /* If we have a 16750 or 16550 the FIFO size is 16, otherwise we assume 1
161  */
162  trace2com_fifoSize_1 = ((Lsb & 0x20) != 0x20 ||
163  (Lsb & 0xC0) == 0xC0) ? 15 : 0;
164 
165  /* We are now officially open for business
166  */
167  trace2com_speed = baudRate;
168  trace2com_base = base;
169 
170  SIO_TRACE ((_LANG("Watt-32 COM%d trace started"), portAddress));
171  return (1);
172 }
173 #endif /* USE_RS232_DBG */
174 
Core definitions.
DWORD W32_CALL set_timeout(DWORD msec)
Return time for when given timeout (msec) expires.
Definition: timer.c:503
BOOL W32_CALL chk_timeout(DWORD value)
Check if milli-sec value has expired:
Definition: timer.c:547