comio_direct.c revision 1.2 1 /*-
2 * Copyright (c) 1993, 1994, 1995, 1996, 1997
3 * Charles M. Hannum. All rights reserved.
4 *
5 * Taken from sys/dev/isa/com.c and integrated into standalone boot
6 * programs by Martin Husemann.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles M. Hannum.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Copyright (c) 1991 The Regents of the University of California.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * @(#)com.c 7.5 (Berkeley) 5/16/91
67 */
68
69 #include <sys/types.h>
70 #include <lib/libsa/stand.h>
71 #include <machine/pio.h>
72 #include <dev/ic/comreg.h>
73 #include "comio_direct.h"
74
75 static int comspeed __P((long speed));
76
77 /* preread buffer for xon/xoff handling */
78 #define XON 0x11
79 #define XOFF 0x13
80 #define SERBUFSIZE 16
81 static u_char serbuf[SERBUFSIZE];
82 static int serbuf_read = 0;
83 static int serbuf_write = 0;
84 static int stopped = 0;
85
86 #define ISSET(t,f) ((t) & (f))
87
88 /*
89 * calculate divisor for a given speed
90 */
91 static int
92 comspeed(speed)
93 long speed;
94 {
95 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
96
97 int x, err;
98
99 #if 0
100 if (speed == 0)
101 return (0);
102 #endif
103 if (speed <= 0)
104 return (-1);
105 x = divrnd((COM_FREQ / 16), speed);
106 if (x <= 0)
107 return (-1);
108 err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
109 if (err < 0)
110 err = -err;
111 if (err > COM_TOLERANCE)
112 return (-1);
113 return (x);
114
115 #undef divrnd(n, q)
116 }
117
118 /*
119 * get a character
120 */
121 int
122 comgetc_d(combase)
123 int combase;
124 {
125 u_char stat, c;
126
127 if (serbuf_read != serbuf_write) {
128 c = serbuf[serbuf_read++];
129 if (serbuf_read >= SERBUFSIZE)
130 serbuf_read = 0;
131 return c;
132 }
133
134 for (;;) {
135 while (!ISSET(stat = inb(combase + com_lsr), LSR_RXRDY))
136 ;
137 c = inb(combase + com_data);
138 inb(combase + com_iir);
139 if (c != XOFF) {
140 stopped = 0;
141 break; /* got a real char, deliver it... */
142 }
143 stopped = 1;
144 }
145 return (c);
146 }
147
148 /*
149 * output a character, return nonzero on success
150 */
151 int
152 computc_d(c, combase)
153 int c;
154 int combase;
155 {
156 u_char stat;
157 register int timo;
158
159 /* check for old XOFF */
160 while (stopped)
161 comgetc_d(combase); /* wait for XON */
162
163 /* check for new XOFF */
164 if (comstatus_d(combase)) {
165 int c = comgetc_d(combase); /* XOFF handled in comgetc_d */
166 /* stuff char into preread buffer */
167 serbuf[serbuf_write++] = c;
168 if (serbuf_write >= SERBUFSIZE)
169 serbuf_write = 0;
170 }
171
172 /* wait for any pending transmission to finish */
173 timo = 50000;
174 while (!ISSET(stat = inb(combase + com_lsr), LSR_TXRDY)
175 && --timo)
176 ;
177 if (timo == 0) return 0;
178 outb(combase + com_data, c);
179 /* wait for this transmission to complete */
180 timo = 1500000;
181 while (!ISSET(stat = inb(combase + com_lsr), LSR_TXRDY)
182 && --timo)
183 ;
184 if (timo == 0) return 0;
185 /* clear any interrupts generated by this transmission */
186 inb(combase + com_iir);
187
188 return 1;
189 }
190
191 /*
192 * Initialize UART to known state.
193 */
194 void
195 cominit_d(combase)
196 int combase;
197 {
198 int rate;
199
200 serbuf_read = 0;
201 serbuf_write = 0;
202
203 outb(combase + com_cfcr, LCR_DLAB);
204 #ifdef CONSPEED
205 rate = comspeed(CONSPEED);
206 #else
207 rate = comspeed(9600);
208 #endif
209 outb(combase + com_dlbl, rate);
210 outb(combase + com_dlbh, rate >> 8);
211 outb(combase + com_cfcr, LCR_8BITS);
212 outb(combase + com_mcr, 0);
213 outb(combase + com_fifo,
214 FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
215 outb(combase + com_ier, 0);
216 }
217
218 /*
219 * return nonzero if input char available, do XON/XOFF handling
220 */
221 int
222 comstatus_d(combase)
223 int combase;
224 {
225 /* check if any preread input is already there */
226 if (serbuf_read != serbuf_write) return 1;
227
228 /* check for new stuff on the port */
229 if (ISSET(inb(combase + com_lsr), LSR_RXRDY)) {
230 /* this could be XOFF, which we would swallow, so we can't
231 claim there is input available... */
232 int c = inb(combase + com_data);
233 inb(combase + com_iir);
234 if (c == XOFF) {
235 stopped = 1;
236 } else {
237 /* stuff char into preread buffer */
238 serbuf[serbuf_write++] = c;
239 if (serbuf_write >= SERBUFSIZE)
240 serbuf_write = 0;
241 return 1;
242 }
243 }
244
245 return 0; /* nothing out there... */
246 }
247