]>
Commit | Line | Data |
---|---|---|
55e303ae A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
e5568f75 A |
6 | * The contents of this file constitute Original Code as defined in and |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
55e303ae | 11 | * |
e5568f75 A |
12 | * This Original Code and all software distributed under the License are |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
55e303ae A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
e5568f75 A |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
55e303ae A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | ||
23 | /* | |
24 | * file: pe_serial.c | |
25 | * Polled-mode 16x50 UART driver. | |
26 | */ | |
27 | ||
28 | #include <pexpert/protos.h> | |
29 | #include <pexpert/pexpert.h> | |
30 | ||
91447636 A |
31 | void serial_putc(char); |
32 | int serial_getc(void); | |
33 | int serial_init(void); | |
34 | ||
55e303ae A |
35 | /* standard port addresses */ |
36 | enum { | |
37 | COM1_PORT_ADDR = 0x3f8, | |
38 | COM2_PORT_ADDR = 0x2f8 | |
39 | }; | |
40 | ||
41 | /* UART register offsets */ | |
42 | enum { | |
43 | UART_RBR = 0, /* receive buffer Register (R) */ | |
44 | UART_THR = 0, /* transmit holding register (W) */ | |
45 | UART_DLL = 0, /* DLAB = 1, divisor latch (LSB) */ | |
46 | UART_IER = 1, /* interrupt enable register */ | |
47 | UART_DLM = 1, /* DLAB = 1, divisor latch (MSB) */ | |
48 | UART_IIR = 2, /* interrupt ident register (R) */ | |
49 | UART_FCR = 2, /* fifo control register (W) */ | |
50 | UART_LCR = 3, /* line control register */ | |
51 | UART_MCR = 4, /* modem control register */ | |
52 | UART_LSR = 5, /* line status register */ | |
53 | UART_MSR = 6 /* modem status register */ | |
54 | }; | |
55 | ||
56 | enum { | |
57 | UART_LCR_8BITS = 0x03, | |
58 | UART_LCR_DLAB = 0x80 | |
59 | }; | |
60 | ||
61 | enum { | |
62 | UART_MCR_DTR = 0x01, | |
63 | UART_MCR_RTS = 0x02, | |
64 | UART_MCR_OUT1 = 0x04, | |
65 | UART_MCR_OUT2 = 0x08, | |
66 | UART_MCR_LOOP = 0x10 | |
67 | }; | |
68 | ||
69 | enum { | |
70 | UART_LSR_THRE = 0x20 | |
71 | }; | |
72 | ||
73 | #define UART_BAUD_RATE 115200 | |
74 | #define UART_PORT_ADDR COM1_PORT_ADDR | |
75 | ||
76 | #define WRITE(r, v) outb(UART_PORT_ADDR + UART_##r, v) | |
77 | #define READ(r) inb(UART_PORT_ADDR + UART_##r) | |
78 | #define DELAY(x) { volatile int _d_; for (_d_ = 0; _d_ < (10000*x); _d_++) ; } | |
79 | ||
80 | static int uart_initted = 0; /* 1 if init'ed */ | |
81 | ||
82 | static int | |
83 | uart_probe( void ) | |
84 | { | |
85 | /* Verify that the Divisor Register is accessible */ | |
86 | ||
87 | WRITE( LCR, UART_LCR_DLAB ); | |
88 | WRITE( DLL, 0x5a ); | |
89 | if (READ(DLL) != 0x5a) return 0; | |
90 | WRITE( DLL, 0xa5 ); | |
91 | if (READ(DLL) != 0xa5) return 0; | |
92 | WRITE( LCR, 0x00 ); | |
93 | return 1; | |
94 | } | |
95 | ||
96 | static void | |
97 | uart_set_baud_rate( unsigned long baud_rate ) | |
98 | { | |
99 | #define UART_CLOCK 1843200 /* 1.8432 MHz clock */ | |
100 | ||
101 | const unsigned char lcr = READ( LCR ); | |
102 | unsigned long div; | |
103 | ||
104 | if (baud_rate == 0) baud_rate = 9600; | |
105 | div = UART_CLOCK / 16 / baud_rate; | |
106 | WRITE( LCR, lcr | UART_LCR_DLAB ); | |
107 | WRITE( DLM, (unsigned char)(div >> 8) ); | |
108 | WRITE( DLL, (unsigned char) div ); | |
109 | WRITE( LCR, lcr & ~UART_LCR_DLAB); | |
110 | } | |
111 | ||
112 | static void | |
113 | uart_putc( char c ) | |
114 | { | |
115 | if (!uart_initted) return; | |
116 | ||
117 | /* Wait for THR empty */ | |
118 | while ( !(READ(LSR) & UART_LSR_THRE) ) DELAY(1); | |
119 | ||
120 | WRITE( THR, c ); | |
121 | } | |
122 | ||
123 | int serial_init( void ) | |
124 | { | |
91447636 | 125 | if ( /*uart_initted ||*/ uart_probe() == 0 ) return 0; |
55e303ae A |
126 | |
127 | /* Disable hardware interrupts */ | |
128 | ||
129 | WRITE( MCR, 0 ); | |
130 | WRITE( IER, 0 ); | |
131 | ||
132 | /* Disable FIFO's for 16550 devices */ | |
133 | ||
134 | WRITE( FCR, 0 ); | |
135 | ||
136 | /* Set for 8-bit, no parity, DLAB bit cleared */ | |
137 | ||
138 | WRITE( LCR, UART_LCR_8BITS ); | |
139 | ||
140 | /* Set baud rate */ | |
141 | ||
142 | uart_set_baud_rate( UART_BAUD_RATE ); | |
143 | ||
144 | /* Assert DTR# and RTS# lines (OUT2?) */ | |
145 | ||
146 | WRITE( MCR, UART_MCR_DTR | UART_MCR_RTS ); | |
147 | ||
148 | /* Clear any garbage in the input buffer */ | |
149 | ||
150 | READ( RBR ); | |
151 | ||
152 | uart_initted = 1; | |
153 | ||
154 | return 1; | |
155 | } | |
156 | ||
157 | void serial_putc( char c ) | |
158 | { | |
159 | uart_putc(c); | |
160 | if (c == '\n') uart_putc('\r'); | |
161 | } | |
162 | ||
163 | int serial_getc( void ) | |
164 | { | |
165 | return 0; /* not supported */ | |
166 | } |