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