1 /* 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) 3 * Licensed under the GPL 4 */ 5 6 #include <linux/slab.h> 7 #include <linux/tty.h> 8 #include <linux/tty_flip.h> 9 #include "chan.h" 10 #include <os.h> 11 #include <irq_kern.h> 12 13 #ifdef CONFIG_NOCONFIG_CHAN 14 static void *not_configged_init(char *str, int device, 15 const struct chan_opts *opts) 16 { 17 printk(KERN_ERR "Using a channel type which is configured out of " 18 "UML\n"); 19 return NULL; 20 } 21 22 static int not_configged_open(int input, int output, int primary, void *data, 23 char **dev_out) 24 { 25 printk(KERN_ERR "Using a channel type which is configured out of " 26 "UML\n"); 27 return -ENODEV; 28 } 29 30 static void not_configged_close(int fd, void *data) 31 { 32 printk(KERN_ERR "Using a channel type which is configured out of " 33 "UML\n"); 34 } 35 36 static int not_configged_read(int fd, char *c_out, void *data) 37 { 38 printk(KERN_ERR "Using a channel type which is configured out of " 39 "UML\n"); 40 return -EIO; 41 } 42 43 static int not_configged_write(int fd, const char *buf, int len, void *data) 44 { 45 printk(KERN_ERR "Using a channel type which is configured out of " 46 "UML\n"); 47 return -EIO; 48 } 49 50 static int not_configged_console_write(int fd, const char *buf, int len) 51 { 52 printk(KERN_ERR "Using a channel type which is configured out of " 53 "UML\n"); 54 return -EIO; 55 } 56 57 static int not_configged_window_size(int fd, void *data, unsigned short *rows, 58 unsigned short *cols) 59 { 60 printk(KERN_ERR "Using a channel type which is configured out of " 61 "UML\n"); 62 return -ENODEV; 63 } 64 65 static void not_configged_free(void *data) 66 { 67 printk(KERN_ERR "Using a channel type which is configured out of " 68 "UML\n"); 69 } 70 71 static const struct chan_ops not_configged_ops = { 72 .init = not_configged_init, 73 .open = not_configged_open, 74 .close = not_configged_close, 75 .read = not_configged_read, 76 .write = not_configged_write, 77 .console_write = not_configged_console_write, 78 .window_size = not_configged_window_size, 79 .free = not_configged_free, 80 .winch = 0, 81 }; 82 #endif /* CONFIG_NOCONFIG_CHAN */ 83 84 static int open_one_chan(struct chan *chan) 85 { 86 int fd, err; 87 88 if (chan->opened) 89 return 0; 90 91 if (chan->ops->open == NULL) 92 fd = 0; 93 else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary, 94 chan->data, &chan->dev); 95 if (fd < 0) 96 return fd; 97 98 err = os_set_fd_block(fd, 0); 99 if (err) { 100 (*chan->ops->close)(fd, chan->data); 101 return err; 102 } 103 104 chan->fd = fd; 105 106 chan->opened = 1; 107 return 0; 108 } 109 110 static int open_chan(struct list_head *chans) 111 { 112 struct list_head *ele; 113 struct chan *chan; 114 int ret, err = 0; 115 116 list_for_each(ele, chans) { 117 chan = list_entry(ele, struct chan, list); 118 ret = open_one_chan(chan); 119 if (chan->primary) 120 err = ret; 121 } 122 return err; 123 } 124 125 void chan_enable_winch(struct chan *chan, struct tty_port *port) 126 { 127 if (chan && chan->primary && chan->ops->winch) 128 register_winch(chan->fd, port); 129 } 130 131 static void line_timer_cb(struct work_struct *work) 132 { 133 struct line *line = container_of(work, struct line, task.work); 134 135 if (!line->throttled) 136 chan_interrupt(line, line->driver->read_irq); 137 } 138 139 int enable_chan(struct line *line) 140 { 141 struct list_head *ele; 142 struct chan *chan; 143 int err; 144 145 INIT_DELAYED_WORK(&line->task, line_timer_cb); 146 147 list_for_each(ele, &line->chan_list) { 148 chan = list_entry(ele, struct chan, list); 149 err = open_one_chan(chan); 150 if (err) { 151 if (chan->primary) 152 goto out_close; 153 154 continue; 155 } 156 157 if (chan->enabled) 158 continue; 159 err = line_setup_irq(chan->fd, chan->input, chan->output, line, 160 chan); 161 if (err) 162 goto out_close; 163 164 chan->enabled = 1; 165 } 166 167 return 0; 168 169 out_close: 170 close_chan(line); 171 return err; 172 } 173 174 static void close_one_chan(struct chan *chan, int delay_free_irq) 175 { 176 if (!chan->opened) 177 return; 178 179 /* we can safely call free now - it will be marked 180 * as free and freed once the IRQ stopped processing 181 */ 182 if (chan->input && chan->enabled) 183 um_free_irq(chan->line->driver->read_irq, chan); 184 if (chan->output && chan->enabled) 185 um_free_irq(chan->line->driver->write_irq, chan); 186 chan->enabled = 0; 187 if (chan->ops->close != NULL) 188 (*chan->ops->close)(chan->fd, chan->data); 189 190 chan->opened = 0; 191 chan->fd = -1; 192 } 193 194 void close_chan(struct line *line) 195 { 196 struct chan *chan; 197 198 /* Close in reverse order as open in case more than one of them 199 * refers to the same device and they save and restore that device's 200 * state. Then, the first one opened will have the original state, 201 * so it must be the last closed. 202 */ 203 list_for_each_entry_reverse(chan, &line->chan_list, list) { 204 close_one_chan(chan, 0); 205 } 206 } 207 208 void deactivate_chan(struct chan *chan, int irq) 209 { 210 if (chan && chan->enabled) 211 deactivate_fd(chan->fd, irq); 212 } 213 214 int write_chan(struct chan *chan, const char *buf, int len, 215 int write_irq) 216 { 217 int n, ret = 0; 218 219 if (len == 0 || !chan || !chan->ops->write) 220 return 0; 221 222 n = chan->ops->write(chan->fd, buf, len, chan->data); 223 if (chan->primary) { 224 ret = n; 225 } 226 return ret; 227 } 228 229 int console_write_chan(struct chan *chan, const char *buf, int len) 230 { 231 int n, ret = 0; 232 233 if (!chan || !chan->ops->console_write) 234 return 0; 235 236 n = chan->ops->console_write(chan->fd, buf, len); 237 if (chan->primary) 238 ret = n; 239 return ret; 240 } 241 242 int console_open_chan(struct line *line, struct console *co) 243 { 244 int err; 245 246 err = open_chan(&line->chan_list); 247 if (err) 248 return err; 249 250 printk(KERN_INFO "Console initialized on /dev/%s%d\n", co->name, 251 co->index); 252 return 0; 253 } 254 255 int chan_window_size(struct line *line, unsigned short *rows_out, 256 unsigned short *cols_out) 257 { 258 struct chan *chan; 259 260 chan = line->chan_in; 261 if (chan && chan->primary) { 262 if (chan->ops->window_size == NULL) 263 return 0; 264 return chan->ops->window_size(chan->fd, chan->data, 265 rows_out, cols_out); 266 } 267 chan = line->chan_out; 268 if (chan && chan->primary) { 269 if (chan->ops->window_size == NULL) 270 return 0; 271 return chan->ops->window_size(chan->fd, chan->data, 272 rows_out, cols_out); 273 } 274 return 0; 275 } 276 277 static void free_one_chan(struct chan *chan) 278 { 279 list_del(&chan->list); 280 281 close_one_chan(chan, 0); 282 283 if (chan->ops->free != NULL) 284 (*chan->ops->free)(chan->data); 285 286 if (chan->primary && chan->output) 287 ignore_sigio_fd(chan->fd); 288 kfree(chan); 289 } 290 291 static void free_chan(struct list_head *chans) 292 { 293 struct list_head *ele, *next; 294 struct chan *chan; 295 296 list_for_each_safe(ele, next, chans) { 297 chan = list_entry(ele, struct chan, list); 298 free_one_chan(chan); 299 } 300 } 301 302 static int one_chan_config_string(struct chan *chan, char *str, int size, 303 char **error_out) 304 { 305 int n = 0; 306 307 if (chan == NULL) { 308 CONFIG_CHUNK(str, size, n, "none", 1); 309 return n; 310 } 311 312 CONFIG_CHUNK(str, size, n, chan->ops->type, 0); 313 314 if (chan->dev == NULL) { 315 CONFIG_CHUNK(str, size, n, "", 1); 316 return n; 317 } 318 319 CONFIG_CHUNK(str, size, n, ":", 0); 320 CONFIG_CHUNK(str, size, n, chan->dev, 0); 321 322 return n; 323 } 324 325 static int chan_pair_config_string(struct chan *in, struct chan *out, 326 char *str, int size, char **error_out) 327 { 328 int n; 329 330 n = one_chan_config_string(in, str, size, error_out); 331 str += n; 332 size -= n; 333 334 if (in == out) { 335 CONFIG_CHUNK(str, size, n, "", 1); 336 return n; 337 } 338 339 CONFIG_CHUNK(str, size, n, ",", 1); 340 n = one_chan_config_string(out, str, size, error_out); 341 str += n; 342 size -= n; 343 CONFIG_CHUNK(str, size, n, "", 1); 344 345 return n; 346 } 347 348 int chan_config_string(struct line *line, char *str, int size, 349 char **error_out) 350 { 351 struct chan *in = line->chan_in, *out = line->chan_out; 352 353 if (in && !in->primary) 354 in = NULL; 355 if (out && !out->primary) 356 out = NULL; 357 358 return chan_pair_config_string(in, out, str, size, error_out); 359 } 360 361 struct chan_type { 362 char *key; 363 const struct chan_ops *ops; 364 }; 365 366 static const struct chan_type chan_table[] = { 367 { "fd", &fd_ops }, 368 369 #ifdef CONFIG_NULL_CHAN 370 { "null", &null_ops }, 371 #else 372 { "null", ¬_configged_ops }, 373 #endif 374 375 #ifdef CONFIG_PORT_CHAN 376 { "port", &port_ops }, 377 #else 378 { "port", ¬_configged_ops }, 379 #endif 380 381 #ifdef CONFIG_PTY_CHAN 382 { "pty", &pty_ops }, 383 { "pts", &pts_ops }, 384 #else 385 { "pty", ¬_configged_ops }, 386 { "pts", ¬_configged_ops }, 387 #endif 388 389 #ifdef CONFIG_TTY_CHAN 390 { "tty", &tty_ops }, 391 #else 392 { "tty", ¬_configged_ops }, 393 #endif 394 395 #ifdef CONFIG_XTERM_CHAN 396 { "xterm", &xterm_ops }, 397 #else 398 { "xterm", ¬_configged_ops }, 399 #endif 400 }; 401 402 static struct chan *parse_chan(struct line *line, char *str, int device, 403 const struct chan_opts *opts, char **error_out) 404 { 405 const struct chan_type *entry; 406 const struct chan_ops *ops; 407 struct chan *chan; 408 void *data; 409 int i; 410 411 ops = NULL; 412 data = NULL; 413 for(i = 0; i < ARRAY_SIZE(chan_table); i++) { 414 entry = &chan_table[i]; 415 if (!strncmp(str, entry->key, strlen(entry->key))) { 416 ops = entry->ops; 417 str += strlen(entry->key); 418 break; 419 } 420 } 421 if (ops == NULL) { 422 *error_out = "No match for configured backends"; 423 return NULL; 424 } 425 426 data = (*ops->init)(str, device, opts); 427 if (data == NULL) { 428 *error_out = "Configuration failed"; 429 return NULL; 430 } 431 432 chan = kmalloc(sizeof(*chan), GFP_ATOMIC); 433 if (chan == NULL) { 434 *error_out = "Memory allocation failed"; 435 return NULL; 436 } 437 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 438 .free_list = 439 LIST_HEAD_INIT(chan->free_list), 440 .line = line, 441 .primary = 1, 442 .input = 0, 443 .output = 0, 444 .opened = 0, 445 .enabled = 0, 446 .fd = -1, 447 .ops = ops, 448 .data = data }); 449 return chan; 450 } 451 452 int parse_chan_pair(char *str, struct line *line, int device, 453 const struct chan_opts *opts, char **error_out) 454 { 455 struct list_head *chans = &line->chan_list; 456 struct chan *new; 457 char *in, *out; 458 459 if (!list_empty(chans)) { 460 line->chan_in = line->chan_out = NULL; 461 free_chan(chans); 462 INIT_LIST_HEAD(chans); 463 } 464 465 if (!str) 466 return 0; 467 468 out = strchr(str, ','); 469 if (out != NULL) { 470 in = str; 471 *out = '\0'; 472 out++; 473 new = parse_chan(line, in, device, opts, error_out); 474 if (new == NULL) 475 return -1; 476 477 new->input = 1; 478 list_add(&new->list, chans); 479 line->chan_in = new; 480 481 new = parse_chan(line, out, device, opts, error_out); 482 if (new == NULL) 483 return -1; 484 485 list_add(&new->list, chans); 486 new->output = 1; 487 line->chan_out = new; 488 } 489 else { 490 new = parse_chan(line, str, device, opts, error_out); 491 if (new == NULL) 492 return -1; 493 494 list_add(&new->list, chans); 495 new->input = 1; 496 new->output = 1; 497 line->chan_in = line->chan_out = new; 498 } 499 return 0; 500 } 501 502 void chan_interrupt(struct line *line, int irq) 503 { 504 struct tty_port *port = &line->port; 505 struct chan *chan = line->chan_in; 506 int err; 507 char c; 508 509 if (!chan || !chan->ops->read) 510 goto out; 511 512 do { 513 if (!tty_buffer_request_room(port, 1)) { 514 schedule_delayed_work(&line->task, 1); 515 goto out; 516 } 517 err = chan->ops->read(chan->fd, &c, chan->data); 518 if (err > 0) 519 tty_insert_flip_char(port, c, TTY_NORMAL); 520 } while (err > 0); 521 522 if (err == -EIO) { 523 if (chan->primary) { 524 tty_port_tty_hangup(&line->port, false); 525 if (line->chan_out != chan) 526 close_one_chan(line->chan_out, 1); 527 } 528 close_one_chan(chan, 1); 529 if (chan->primary) 530 return; 531 } 532 out: 533 tty_flip_buffer_push(port); 534 } 535