|
|
1.1 root 1: /*
2: * File: albaud.c
3: *
4: * Purpose: common code for various async drivers
5: *
6: * $Log: albaud.c,v $
7: * Revision 2.2 93/07/26 15:27:51 nigel
8: * Nigel's R80
9: *
10: * Revision 1.2 93/04/14 10:24:08 root
11: * r75
12: *
13: * Revision 1.1 92/04/30 08:58:54 hal
14: * Add asy. Remove silos from tty struct.
15: *
16: */
17:
18: /*
19: * ----------------------------------------------------------------------
20: * Includes.
21: */
22: #include <sys/coherent.h>
23: #include <sys/ins8250.h>
24:
25: /*
26: * ----------------------------------------------------------------------
27: * Definitions.
28: * Constants.
29: * Macros with argument lists.
30: * Typedefs.
31: * Enums.
32: */
33: #define TESTBAUD 0x03A5
34:
35: /*
36: * ----------------------------------------------------------------------
37: * Functions.
38: * Import Functions.
39: * Export Functions.
40: * Local Functions.
41: */
42: int uart_sense();
43:
44: /*
45: * ----------------------------------------------------------------------
46: * Global Data.
47: * Import Variables.
48: * Export Variables.
49: * Local Variables.
50: */
51:
52: int albaud[] ={
53: 0, /* 0 */
54: 2304, /* 50 */
55: 1536, /* 75 */
56: 1047, /* 110 */
57: 857, /* 134.5 */
58: 768, /* 150 */
59: 576, /* 200 */
60: 384, /* 300 */
61: 192, /* 600 */
62: 96, /* 1200 */
63: 64, /* 1800 */
64: #ifdef _I386
65: 48, /* 2400 */
66: 24, /* 4800 */
67: 12, /* 9600 */
68: 6, /* 19200 */
69: 3 /* 38400 */
70: #else
71: 58, /* 2000 */
72: 48, /* 2400 */
73: 32, /* 3600 */
74: 24, /* 4800 */
75: 16, /* 7200 */
76: 12, /* 9600 */
77: 6, /* 19200 */
78: 0, /* EXTA */
79: 0 /* EXTB */
80: #endif
81: };
82:
83: /*
84: * alp_rate[] is tied to albaud[] - it gives the minimum polling
85: * rate for the corresponding port speed; it must be a multiple
86: * of 100 (system clock Hz) and >= baud/6
87: */
88: int alp_rate[] ={ /* baud/6 or zero */
89: 0, /* 0 */
90: 1*HZ, /* 50 */
91: 1*HZ, /* 75 */
92: 1*HZ, /* 110 */
93: 1*HZ, /* 134.5 */
94: 1*HZ, /* 150 */
95: 1*HZ, /* 200 */
96: 1*HZ, /* 300 */
97: 1*HZ, /* 600 */
98: 2*HZ, /* 1200 */
99: 3*HZ, /* 1800 */
100: #ifdef _I386
101: 4*HZ, /* 2400 */
102: 8*HZ, /* 4800 */
103: 16*HZ, /* 9600 */
104: 32*HZ, /* 19200 */
105: 64*HZ /* 38400 */
106: #else
107: 4*HZ, /* 2000 */
108: 4*HZ, /* 2400 */
109: 6*HZ, /* 3600 */
110: 8*HZ, /* 4800 */
111: 12*HZ, /* 7200 */
112: 16*HZ, /* 9600 */
113: 32*HZ, /* 19200 */
114: 0, /* EXTA */
115: 0 /* EXTB */
116: #endif
117: };
118:
119: /*
120: * ----------------------------------------------------------------------
121: * Code.
122: */
123:
124: /*
125: * uart_sense()
126: *
127: * Given port address, return what type of 8250-family chip is found there.
128: *
129: * 0 - no chip
130: * 1 - 8250 or 8250B
131: * 2 - 8250A or 16450
132: * 3 - 16550
133: * 4 - 16550A
134: *
135: * Only the last of these has usable on-chip FIFO.
136: */
137: int uart_sense(port)
138: int port;
139: {
140: int ret = US_NONE;
141: unsigned ch;
142: short testbaud;
143: char lcr, dll, dlh;
144:
145: /*
146: * See if UART is detected at port address.
147: * UART should have IER = 0000 xxxx
148: * MCR = 000x xxxx
149: * IIR = xx00 xxxx
150: * and should be write and read back the baud rate regs.
151: */
152: if (inb(port+IER) & 0xF0
153: || inb(port+MCR) & 0xE0
154: || inb(port+IIR) & 0x30) {
155: goto done;
156: }
157: lcr = inb(port + LCR);
158: outb(port+LCR, LC_DLAB);
159: dll = inb(port + DLL);
160: dlh = inb(port + DLH);
161: outb(port+DLL, TESTBAUD & 0xFF);
162: outb(port+DLH, TESTBAUD >> 8);
163: testbaud = inb(port+DLL) | inb(port+DLH) << 8;
164: outb(port+LCR, LC_CS8);
165: if (testbaud != TESTBAUD){
166: goto done;
167: } else {
168: outb(port+LCR, LC_DLAB);
169: outb(port+DLL, dll);
170: outb(port+DLH, dlh);
171: outb(port+LCR, lcr);
172: }
173:
174: /*
175: * Scratch register NOT found on 8250/8250B.
176: */
177: outb(port+SCR, 0x55);
178: ch = inb(port+SCR);
179: if (ch != 0x55) {
180: ret = US_8250;
181: }
182:
183: /*
184: * After trying to turn on FIFO mode,
185: * If IIR is 00xx xxxx, it's 8250A/16450 (no FIFO).
186: * If IIR is 10xx xxxx, it's 16550 (broken FIFO).
187: * If IIR is 11xx xxxx, it's 16550A (usable FIFO).
188: */
189: outb(port+FCR, 0x01);
190: ch = inb(port+FCR);
191: switch (ch & 0xC0) {
192: case 0x00:
193: if (ret == US_NONE)
194: ret = US_16450;
195: break;
196: case 0x80:
197: if (ret == US_NONE)
198: ret = US_16550;
199: break;
200: case 0xC0:
201: ret = US_16550A;
202: break;
203: }
204: outb(port+FCR, 0x00);
205: done:
206:
207: switch(port){
208: case 0x3F8:
209: printf("com1 ");
210: break;
211: case 0x2F8:
212: printf("com2 ");
213: break;
214: case 0x3E8:
215: printf("com3 ");
216: break;
217: case 0x2E8:
218: printf("com4 ");
219: break;
220: }
221: printf("port %x: ", port);
222: switch (ret) {
223: case US_NONE:
224: printf("no UART ");
225: break;
226: case US_8250:
227: printf("8250/8250B ");
228: break;
229: case US_16450:
230: printf("8250A/16450 ");
231: break;
232: case US_16550:
233: printf("16550 - no FIFO ");
234: break;
235: case US_16550A:
236: printf("16550A - FIFO ");
237: break;
238: }
239: return ret;
240: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.