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