1 /*- 2 * Copyright (c) 2004 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 34 #include <machine/bus.h> 35 #include <machine/vmparam.h> 36 37 #include <dev/uart/uart.h> 38 #include <dev/uart/uart_cpu.h> 39 40 #define UART_TAG_BR 0 41 #define UART_TAG_CH 1 42 #define UART_TAG_DB 2 43 #define UART_TAG_DT 3 44 #define UART_TAG_IO 4 45 #define UART_TAG_MM 5 46 #define UART_TAG_PA 6 47 #define UART_TAG_RS 7 48 #define UART_TAG_SB 8 49 #define UART_TAG_XO 9 50 51 static struct uart_class *uart_classes[] = { 52 &uart_ns8250_class, 53 &uart_sab82532_class, 54 &uart_z8530_class, 55 &uart_lpc_class, 56 }; 57 static size_t uart_nclasses = sizeof(uart_classes) / sizeof(uart_classes[0]); 58 59 static bus_addr_t 60 uart_parse_addr(const char **p) 61 { 62 return (strtoul(*p, (char**)(uintptr_t)p, 0)); 63 } 64 65 static struct uart_class * 66 uart_parse_class(struct uart_class *class, const char **p) 67 { 68 struct uart_class *uc; 69 const char *nm; 70 size_t len; 71 u_int i; 72 73 for (i = 0; i < uart_nclasses; i++) { 74 uc = uart_classes[i]; 75 nm = uart_getname(uc); 76 if (nm == NULL || *nm == '\0') 77 continue; 78 len = strlen(nm); 79 if (strncmp(nm, *p, len) == 0) { 80 *p += len; 81 return (uc); 82 } 83 } 84 return (class); 85 } 86 87 static long 88 uart_parse_long(const char **p) 89 { 90 return (strtol(*p, (char**)(uintptr_t)p, 0)); 91 } 92 93 static int 94 uart_parse_parity(const char **p) 95 { 96 if (!strncmp(*p, "even", 4)) { 97 *p += 4; 98 return UART_PARITY_EVEN; 99 } 100 if (!strncmp(*p, "mark", 4)) { 101 *p += 4; 102 return UART_PARITY_MARK; 103 } 104 if (!strncmp(*p, "none", 4)) { 105 *p += 4; 106 return UART_PARITY_NONE; 107 } 108 if (!strncmp(*p, "odd", 3)) { 109 *p += 3; 110 return UART_PARITY_ODD; 111 } 112 if (!strncmp(*p, "space", 5)) { 113 *p += 5; 114 return UART_PARITY_SPACE; 115 } 116 return (-1); 117 } 118 119 static int 120 uart_parse_tag(const char **p) 121 { 122 int tag; 123 124 if ((*p)[0] == 'b' && (*p)[1] == 'r') { 125 tag = UART_TAG_BR; 126 goto out; 127 } 128 if ((*p)[0] == 'c' && (*p)[1] == 'h') { 129 tag = UART_TAG_CH; 130 goto out; 131 } 132 if ((*p)[0] == 'd' && (*p)[1] == 'b') { 133 tag = UART_TAG_DB; 134 goto out; 135 } 136 if ((*p)[0] == 'd' && (*p)[1] == 't') { 137 tag = UART_TAG_DT; 138 goto out; 139 } 140 if ((*p)[0] == 'i' && (*p)[1] == 'o') { 141 tag = UART_TAG_IO; 142 goto out; 143 } 144 if ((*p)[0] == 'm' && (*p)[1] == 'm') { 145 tag = UART_TAG_MM; 146 goto out; 147 } 148 if ((*p)[0] == 'p' && (*p)[1] == 'a') { 149 tag = UART_TAG_PA; 150 goto out; 151 } 152 if ((*p)[0] == 'r' && (*p)[1] == 's') { 153 tag = UART_TAG_RS; 154 goto out; 155 } 156 if ((*p)[0] == 's' && (*p)[1] == 'b') { 157 tag = UART_TAG_SB; 158 goto out; 159 } 160 if ((*p)[0] == 'x' && (*p)[1] == 'o') { 161 tag = UART_TAG_XO; 162 goto out; 163 } 164 return (-1); 165 166 out: 167 *p += 2; 168 if ((*p)[0] != ':') 169 return (-1); 170 (*p)++; 171 return (tag); 172 } 173 174 /* 175 * Parse a device specification. The specification is a list of attributes 176 * separated by commas. Each attribute is a tag-value pair with the tag and 177 * value separated by a colon. Supported tags are: 178 * 179 * br = Baudrate 180 * ch = Channel 181 * db = Data bits 182 * dt = Device type 183 * io = I/O port address 184 * mm = Memory mapped I/O address 185 * pa = Parity 186 * rs = Register shift 187 * sb = Stopbits 188 * xo = Device clock (xtal oscillator) 189 * 190 * The io and mm tags are mutually exclusive. 191 */ 192 193 int 194 uart_getenv(int devtype, struct uart_devinfo *di, struct uart_class *class) 195 { 196 const char *spec; 197 bus_addr_t addr = ~0U; 198 int error; 199 200 /* 201 * All uart_class references are weak. Make sure the default 202 * device class has been compiled-in. 203 */ 204 if (class == NULL) 205 return (ENXIO); 206 207 /* 208 * Check the environment variables "hw.uart.console" and 209 * "hw.uart.dbgport". These variables, when present, specify 210 * which UART port is to be used as serial console or debug 211 * port (resp). 212 */ 213 if (devtype == UART_DEV_CONSOLE) 214 spec = getenv("hw.uart.console"); 215 else if (devtype == UART_DEV_DBGPORT) 216 spec = getenv("hw.uart.dbgport"); 217 else 218 spec = NULL; 219 if (spec == NULL) 220 return (ENXIO); 221 222 /* Set defaults. */ 223 di->bas.chan = 0; 224 di->bas.regshft = 0; 225 di->bas.rclk = 0; 226 di->baudrate = 0; 227 di->databits = 8; 228 di->stopbits = 1; 229 di->parity = UART_PARITY_NONE; 230 231 /* Parse the attributes. */ 232 while (1) { 233 switch (uart_parse_tag(&spec)) { 234 case UART_TAG_BR: 235 di->baudrate = uart_parse_long(&spec); 236 break; 237 case UART_TAG_CH: 238 di->bas.chan = uart_parse_long(&spec); 239 break; 240 case UART_TAG_DB: 241 di->databits = uart_parse_long(&spec); 242 break; 243 case UART_TAG_DT: 244 class = uart_parse_class(class, &spec); 245 break; 246 case UART_TAG_IO: 247 di->bas.bst = uart_bus_space_io; 248 addr = uart_parse_addr(&spec); 249 break; 250 case UART_TAG_MM: 251 di->bas.bst = uart_bus_space_mem; 252 addr = uart_parse_addr(&spec); 253 break; 254 case UART_TAG_PA: 255 di->parity = uart_parse_parity(&spec); 256 break; 257 case UART_TAG_RS: 258 di->bas.regshft = uart_parse_long(&spec); 259 break; 260 case UART_TAG_SB: 261 di->stopbits = uart_parse_long(&spec); 262 break; 263 case UART_TAG_XO: 264 di->bas.rclk = uart_parse_long(&spec); 265 break; 266 default: 267 return (EINVAL); 268 } 269 if (*spec == '\0') 270 break; 271 if (*spec != ',') 272 return (EINVAL); 273 spec++; 274 } 275 276 /* 277 * If we still have an invalid address, the specification must be 278 * missing an I/O port or memory address. We don't like that. 279 */ 280 if (addr == ~0U) 281 return (EINVAL); 282 283 /* 284 * Accept only the well-known baudrates. Any invalid baudrate 285 * is silently replaced with a 0-valued baudrate. The 0 baudrate 286 * has special meaning. It means that we're not supposed to 287 * program the baudrate and simply communicate with whatever 288 * speed the hardware is currently programmed for. 289 */ 290 if (di->baudrate >= 19200) { 291 if (di->baudrate % 19200) 292 di->baudrate = 0; 293 } else if (di->baudrate >= 1200) { 294 if (di->baudrate % 1200) 295 di->baudrate = 0; 296 } else if (di->baudrate > 0) { 297 if (di->baudrate % 75) 298 di->baudrate = 0; 299 } else 300 di->baudrate = 0; 301 302 /* Set the ops and create a bus space handle. */ 303 di->ops = uart_getops(class); 304 error = bus_space_map(di->bas.bst, addr, uart_getrange(class), 0, 305 &di->bas.bsh); 306 return (error); 307 } 308