at v2.6.21 247 lines 5.2 kB view raw
1/* suncore.c 2 * 3 * Common SUN serial routines. Based entirely 4 * upon drivers/sbus/char/sunserial.c which is: 5 * 6 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) 7 * 8 * Adaptation to new UART layer is: 9 * 10 * Copyright (C) 2002 David S. Miller (davem@redhat.com) 11 */ 12 13#include <linux/module.h> 14#include <linux/kernel.h> 15#include <linux/console.h> 16#include <linux/tty.h> 17#include <linux/errno.h> 18#include <linux/string.h> 19#include <linux/init.h> 20 21#include <asm/oplib.h> 22 23#include "suncore.h" 24 25int sunserial_current_minor = 64; 26 27EXPORT_SYMBOL(sunserial_current_minor); 28 29void 30sunserial_console_termios(struct console *con) 31{ 32 char mode[16], buf[16], *s; 33 char *mode_prop = "ttyX-mode"; 34 char *cd_prop = "ttyX-ignore-cd"; 35 char *dtr_prop = "ttyX-rts-dtr-off"; 36 char *ssp_console_modes_prop = "ssp-console-modes"; 37 int baud, bits, stop, cflag; 38 char parity; 39 int carrier = 0; 40 int rtsdtr = 1; 41 int topnd, nd; 42 43 if (!serial_console) 44 return; 45 46 switch (serial_console) { 47 case PROMDEV_OTTYA: 48 mode_prop[3] = 'a'; 49 cd_prop[3] = 'a'; 50 dtr_prop[3] = 'a'; 51 break; 52 53 case PROMDEV_OTTYB: 54 mode_prop[3] = 'b'; 55 cd_prop[3] = 'b'; 56 dtr_prop[3] = 'b'; 57 break; 58 59 case PROMDEV_ORSC: 60 61 nd = prom_pathtoinode("rsc"); 62 if (!nd) { 63 strcpy(mode, "115200,8,n,1,-"); 64 goto no_options; 65 } 66 67 if (!prom_node_has_property(nd, ssp_console_modes_prop)) { 68 strcpy(mode, "115200,8,n,1,-"); 69 goto no_options; 70 } 71 72 memset(mode, 0, sizeof(mode)); 73 prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode)); 74 goto no_options; 75 76 default: 77 strcpy(mode, "9600,8,n,1,-"); 78 goto no_options; 79 } 80 81 topnd = prom_getchild(prom_root_node); 82 nd = prom_searchsiblings(topnd, "options"); 83 if (!nd) { 84 strcpy(mode, "9600,8,n,1,-"); 85 goto no_options; 86 } 87 88 if (!prom_node_has_property(nd, mode_prop)) { 89 strcpy(mode, "9600,8,n,1,-"); 90 goto no_options; 91 } 92 93 memset(mode, 0, sizeof(mode)); 94 prom_getstring(nd, mode_prop, mode, sizeof(mode)); 95 96 if (prom_node_has_property(nd, cd_prop)) { 97 memset(buf, 0, sizeof(buf)); 98 prom_getstring(nd, cd_prop, buf, sizeof(buf)); 99 if (!strcmp(buf, "false")) 100 carrier = 1; 101 102 /* XXX: this is unused below. */ 103 } 104 105 if (prom_node_has_property(nd, dtr_prop)) { 106 memset(buf, 0, sizeof(buf)); 107 prom_getstring(nd, dtr_prop, buf, sizeof(buf)); 108 if (!strcmp(buf, "false")) 109 rtsdtr = 0; 110 111 /* XXX: this is unused below. */ 112 } 113 114no_options: 115 cflag = CREAD | HUPCL | CLOCAL; 116 117 s = mode; 118 baud = simple_strtoul(s, NULL, 0); 119 s = strchr(s, ','); 120 bits = simple_strtoul(++s, NULL, 0); 121 s = strchr(s, ','); 122 parity = *(++s); 123 s = strchr(s, ','); 124 stop = simple_strtoul(++s, NULL, 0); 125 s = strchr(s, ','); 126 /* XXX handshake is not handled here. */ 127 128 switch (baud) { 129 case 150: cflag |= B150; break; 130 case 300: cflag |= B300; break; 131 case 600: cflag |= B600; break; 132 case 1200: cflag |= B1200; break; 133 case 2400: cflag |= B2400; break; 134 case 4800: cflag |= B4800; break; 135 case 9600: cflag |= B9600; break; 136 case 19200: cflag |= B19200; break; 137 case 38400: cflag |= B38400; break; 138 case 57600: cflag |= B57600; break; 139 case 115200: cflag |= B115200; break; 140 case 230400: cflag |= B230400; break; 141 case 460800: cflag |= B460800; break; 142 default: baud = 9600; cflag |= B9600; break; 143 } 144 145 switch (bits) { 146 case 5: cflag |= CS5; break; 147 case 6: cflag |= CS6; break; 148 case 7: cflag |= CS7; break; 149 case 8: cflag |= CS8; break; 150 default: cflag |= CS8; break; 151 } 152 153 switch (parity) { 154 case 'o': cflag |= (PARENB | PARODD); break; 155 case 'e': cflag |= PARENB; break; 156 case 'n': default: break; 157 } 158 159 switch (stop) { 160 case 2: cflag |= CSTOPB; break; 161 case 1: default: break; 162 } 163 164 con->cflag = cflag; 165} 166 167EXPORT_SYMBOL(sunserial_console_termios); 168 169/* Sun serial MOUSE auto baud rate detection. */ 170static struct mouse_baud_cflag { 171 int baud; 172 unsigned int cflag; 173} mouse_baud_table[] = { 174 { 1200, B1200 }, 175 { 2400, B2400 }, 176 { 4800, B4800 }, 177 { 9600, B9600 }, 178 { -1, ~0 }, 179 { -1, ~0 }, 180}; 181 182unsigned int suncore_mouse_baud_cflag_next(unsigned int cflag, int *new_baud) 183{ 184 int i; 185 186 for (i = 0; mouse_baud_table[i].baud != -1; i++) 187 if (mouse_baud_table[i].cflag == (cflag & CBAUD)) 188 break; 189 190 i += 1; 191 if (mouse_baud_table[i].baud == -1) 192 i = 0; 193 194 *new_baud = mouse_baud_table[i].baud; 195 return mouse_baud_table[i].cflag; 196} 197 198EXPORT_SYMBOL(suncore_mouse_baud_cflag_next); 199 200/* Basically, when the baud rate is wrong the mouse spits out 201 * breaks to us. 202 */ 203int suncore_mouse_baud_detection(unsigned char ch, int is_break) 204{ 205 static int mouse_got_break = 0; 206 static int ctr = 0; 207 208 if (is_break) { 209 /* Let a few normal bytes go by before we jump the gun 210 * and say we need to try another baud rate. 211 */ 212 if (mouse_got_break && ctr < 8) 213 return 1; 214 215 /* Ok, we need to try another baud. */ 216 ctr = 0; 217 mouse_got_break = 1; 218 return 2; 219 } 220 if (mouse_got_break) { 221 ctr++; 222 if (ch == 0x87) { 223 /* Correct baud rate determined. */ 224 mouse_got_break = 0; 225 } 226 return 1; 227 } 228 return 0; 229} 230 231EXPORT_SYMBOL(suncore_mouse_baud_detection); 232 233static int __init suncore_init(void) 234{ 235 return 0; 236} 237 238static void __exit suncore_exit(void) 239{ 240} 241 242module_init(suncore_init); 243module_exit(suncore_exit); 244 245MODULE_AUTHOR("Eddie C. Dost, David S. Miller"); 246MODULE_DESCRIPTION("Sun serial common layer"); 247MODULE_LICENSE("GPL");