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 void tty_receive_char(struct tty_struct *tty, char ch) 85 { 86 if (tty == NULL) 87 return; 88 89 if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { 90 if (ch == STOP_CHAR(tty)) { 91 stop_tty(tty); 92 return; 93 } 94 else if (ch == START_CHAR(tty)) { 95 start_tty(tty); 96 return; 97 } 98 } 99 100 tty_insert_flip_char(tty, ch, TTY_NORMAL); 101 } 102 103 static int open_one_chan(struct chan *chan) 104 { 105 int fd, err; 106 107 if (chan->opened) 108 return 0; 109 110 if (chan->ops->open == NULL) 111 fd = 0; 112 else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary, 113 chan->data, &chan->dev); 114 if (fd < 0) 115 return fd; 116 117 err = os_set_fd_block(fd, 0); 118 if (err) { 119 (*chan->ops->close)(fd, chan->data); 120 return err; 121 } 122 123 chan->fd = fd; 124 125 chan->opened = 1; 126 return 0; 127 } 128 129 static int open_chan(struct list_head *chans) 130 { 131 struct list_head *ele; 132 struct chan *chan; 133 int ret, err = 0; 134 135 list_for_each(ele, chans) { 136 chan = list_entry(ele, struct chan, list); 137 ret = open_one_chan(chan); 138 if (chan->primary) 139 err = ret; 140 } 141 return err; 142 } 143 144 void chan_enable_winch(struct chan *chan, struct tty_struct *tty) 145 { 146 if (chan && chan->primary && chan->ops->winch) 147 register_winch(chan->fd, tty); 148 } 149 150 static void line_timer_cb(struct work_struct *work) 151 { 152 struct line *line = container_of(work, struct line, task.work); 153 154 if (!line->throttled) 155 chan_interrupt(line, line->tty, line->driver->read_irq); 156 } 157 158 int enable_chan(struct line *line) 159 { 160 struct list_head *ele; 161 struct chan *chan; 162 int err; 163 164 INIT_DELAYED_WORK(&line->task, line_timer_cb); 165 166 list_for_each(ele, &line->chan_list) { 167 chan = list_entry(ele, struct chan, list); 168 err = open_one_chan(chan); 169 if (err) { 170 if (chan->primary) 171 goto out_close; 172 173 continue; 174 } 175 176 if (chan->enabled) 177 continue; 178 err = line_setup_irq(chan->fd, chan->input, chan->output, line, 179 chan); 180 if (err) 181 goto out_close; 182 183 chan->enabled = 1; 184 } 185 186 return 0; 187 188 out_close: 189 close_chan(line); 190 return err; 191 } 192 193 /* Items are added in IRQ context, when free_irq can't be called, and 194 * removed in process context, when it can. 195 * This handles interrupt sources which disappear, and which need to 196 * be permanently disabled. This is discovered in IRQ context, but 197 * the freeing of the IRQ must be done later. 198 */ 199 static DEFINE_SPINLOCK(irqs_to_free_lock); 200 static LIST_HEAD(irqs_to_free); 201 202 void free_irqs(void) 203 { 204 struct chan *chan; 205 LIST_HEAD(list); 206 struct list_head *ele; 207 unsigned long flags; 208 209 spin_lock_irqsave(&irqs_to_free_lock, flags); 210 list_splice_init(&irqs_to_free, &list); 211 spin_unlock_irqrestore(&irqs_to_free_lock, flags); 212 213 list_for_each(ele, &list) { 214 chan = list_entry(ele, struct chan, free_list); 215 216 if (chan->input && chan->enabled) 217 um_free_irq(chan->line->driver->read_irq, chan); 218 if (chan->output && chan->enabled) 219 um_free_irq(chan->line->driver->write_irq, chan); 220 chan->enabled = 0; 221 } 222 } 223 224 static void close_one_chan(struct chan *chan, int delay_free_irq) 225 { 226 unsigned long flags; 227 228 if (!chan->opened) 229 return; 230 231 if (delay_free_irq) { 232 spin_lock_irqsave(&irqs_to_free_lock, flags); 233 list_add(&chan->free_list, &irqs_to_free); 234 spin_unlock_irqrestore(&irqs_to_free_lock, flags); 235 } 236 else { 237 if (chan->input && chan->enabled) 238 um_free_irq(chan->line->driver->read_irq, chan); 239 if (chan->output && chan->enabled) 240 um_free_irq(chan->line->driver->write_irq, chan); 241 chan->enabled = 0; 242 } 243 if (chan->ops->close != NULL) 244 (*chan->ops->close)(chan->fd, chan->data); 245 246 chan->opened = 0; 247 chan->fd = -1; 248 } 249 250 void close_chan(struct line *line) 251 { 252 struct chan *chan; 253 254 /* Close in reverse order as open in case more than one of them 255 * refers to the same device and they save and restore that device's 256 * state. Then, the first one opened will have the original state, 257 * so it must be the last closed. 258 */ 259 list_for_each_entry_reverse(chan, &line->chan_list, list) { 260 close_one_chan(chan, 0); 261 } 262 } 263 264 void deactivate_chan(struct chan *chan, int irq) 265 { 266 if (chan && chan->enabled) 267 deactivate_fd(chan->fd, irq); 268 } 269 270 void reactivate_chan(struct chan *chan, int irq) 271 { 272 if (chan && chan->enabled) 273 reactivate_fd(chan->fd, irq); 274 } 275 276 int write_chan(struct chan *chan, const char *buf, int len, 277 int write_irq) 278 { 279 int n, ret = 0; 280 281 if (len == 0 || !chan || !chan->ops->write) 282 return 0; 283 284 n = chan->ops->write(chan->fd, buf, len, chan->data); 285 if (chan->primary) { 286 ret = n; 287 if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))) 288 reactivate_fd(chan->fd, write_irq); 289 } 290 return ret; 291 } 292 293 int console_write_chan(struct chan *chan, const char *buf, int len) 294 { 295 int n, ret = 0; 296 297 if (!chan || !chan->ops->console_write) 298 return 0; 299 300 n = chan->ops->console_write(chan->fd, buf, len); 301 if (chan->primary) 302 ret = n; 303 return ret; 304 } 305 306 int console_open_chan(struct line *line, struct console *co) 307 { 308 int err; 309 310 err = open_chan(&line->chan_list); 311 if (err) 312 return err; 313 314 printk(KERN_INFO "Console initialized on /dev/%s%d\n", co->name, 315 co->index); 316 return 0; 317 } 318 319 int chan_window_size(struct line *line, unsigned short *rows_out, 320 unsigned short *cols_out) 321 { 322 struct chan *chan; 323 324 chan = line->chan_in; 325 if (chan && chan->primary) { 326 if (chan->ops->window_size == NULL) 327 return 0; 328 return chan->ops->window_size(chan->fd, chan->data, 329 rows_out, cols_out); 330 } 331 chan = line->chan_out; 332 if (chan && chan->primary) { 333 if (chan->ops->window_size == NULL) 334 return 0; 335 return chan->ops->window_size(chan->fd, chan->data, 336 rows_out, cols_out); 337 } 338 return 0; 339 } 340 341 static void free_one_chan(struct chan *chan) 342 { 343 list_del(&chan->list); 344 345 close_one_chan(chan, 0); 346 347 if (chan->ops->free != NULL) 348 (*chan->ops->free)(chan->data); 349 350 if (chan->primary && chan->output) 351 ignore_sigio_fd(chan->fd); 352 kfree(chan); 353 } 354 355 static void free_chan(struct list_head *chans) 356 { 357 struct list_head *ele, *next; 358 struct chan *chan; 359 360 list_for_each_safe(ele, next, chans) { 361 chan = list_entry(ele, struct chan, list); 362 free_one_chan(chan); 363 } 364 } 365 366 static int one_chan_config_string(struct chan *chan, char *str, int size, 367 char **error_out) 368 { 369 int n = 0; 370 371 if (chan == NULL) { 372 CONFIG_CHUNK(str, size, n, "none", 1); 373 return n; 374 } 375 376 CONFIG_CHUNK(str, size, n, chan->ops->type, 0); 377 378 if (chan->dev == NULL) { 379 CONFIG_CHUNK(str, size, n, "", 1); 380 return n; 381 } 382 383 CONFIG_CHUNK(str, size, n, ":", 0); 384 CONFIG_CHUNK(str, size, n, chan->dev, 0); 385 386 return n; 387 } 388 389 static int chan_pair_config_string(struct chan *in, struct chan *out, 390 char *str, int size, char **error_out) 391 { 392 int n; 393 394 n = one_chan_config_string(in, str, size, error_out); 395 str += n; 396 size -= n; 397 398 if (in == out) { 399 CONFIG_CHUNK(str, size, n, "", 1); 400 return n; 401 } 402 403 CONFIG_CHUNK(str, size, n, ",", 1); 404 n = one_chan_config_string(out, str, size, error_out); 405 str += n; 406 size -= n; 407 CONFIG_CHUNK(str, size, n, "", 1); 408 409 return n; 410 } 411 412 int chan_config_string(struct line *line, char *str, int size, 413 char **error_out) 414 { 415 struct chan *in = line->chan_in, *out = line->chan_out; 416 417 if (in && !in->primary) 418 in = NULL; 419 if (out && !out->primary) 420 out = NULL; 421 422 return chan_pair_config_string(in, out, str, size, error_out); 423 } 424 425 struct chan_type { 426 char *key; 427 const struct chan_ops *ops; 428 }; 429 430 static const struct chan_type chan_table[] = { 431 { "fd", &fd_ops }, 432 433 #ifdef CONFIG_NULL_CHAN 434 { "null", &null_ops }, 435 #else 436 { "null", ¬_configged_ops }, 437 #endif 438 439 #ifdef CONFIG_PORT_CHAN 440 { "port", &port_ops }, 441 #else 442 { "port", ¬_configged_ops }, 443 #endif 444 445 #ifdef CONFIG_PTY_CHAN 446 { "pty", &pty_ops }, 447 { "pts", &pts_ops }, 448 #else 449 { "pty", ¬_configged_ops }, 450 { "pts", ¬_configged_ops }, 451 #endif 452 453 #ifdef CONFIG_TTY_CHAN 454 { "tty", &tty_ops }, 455 #else 456 { "tty", ¬_configged_ops }, 457 #endif 458 459 #ifdef CONFIG_XTERM_CHAN 460 { "xterm", &xterm_ops }, 461 #else 462 { "xterm", ¬_configged_ops }, 463 #endif 464 }; 465 466 static struct chan *parse_chan(struct line *line, char *str, int device, 467 const struct chan_opts *opts, char **error_out) 468 { 469 const struct chan_type *entry; 470 const struct chan_ops *ops; 471 struct chan *chan; 472 void *data; 473 int i; 474 475 ops = NULL; 476 data = NULL; 477 for(i = 0; i < ARRAY_SIZE(chan_table); i++) { 478 entry = &chan_table[i]; 479 if (!strncmp(str, entry->key, strlen(entry->key))) { 480 ops = entry->ops; 481 str += strlen(entry->key); 482 break; 483 } 484 } 485 if (ops == NULL) { 486 *error_out = "No match for configured backends"; 487 return NULL; 488 } 489 490 data = (*ops->init)(str, device, opts); 491 if (data == NULL) { 492 *error_out = "Configuration failed"; 493 return NULL; 494 } 495 496 chan = kmalloc(sizeof(*chan), GFP_ATOMIC); 497 if (chan == NULL) { 498 *error_out = "Memory allocation failed"; 499 return NULL; 500 } 501 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 502 .free_list = 503 LIST_HEAD_INIT(chan->free_list), 504 .line = line, 505 .primary = 1, 506 .input = 0, 507 .output = 0, 508 .opened = 0, 509 .enabled = 0, 510 .fd = -1, 511 .ops = ops, 512 .data = data }); 513 return chan; 514 } 515 516 int parse_chan_pair(char *str, struct line *line, int device, 517 const struct chan_opts *opts, char **error_out) 518 { 519 struct list_head *chans = &line->chan_list; 520 struct chan *new; 521 char *in, *out; 522 523 if (!list_empty(chans)) { 524 line->chan_in = line->chan_out = NULL; 525 free_chan(chans); 526 INIT_LIST_HEAD(chans); 527 } 528 529 if (!str) 530 return 0; 531 532 out = strchr(str, ','); 533 if (out != NULL) { 534 in = str; 535 *out = '\0'; 536 out++; 537 new = parse_chan(line, in, device, opts, error_out); 538 if (new == NULL) 539 return -1; 540 541 new->input = 1; 542 list_add(&new->list, chans); 543 line->chan_in = new; 544 545 new = parse_chan(line, out, device, opts, error_out); 546 if (new == NULL) 547 return -1; 548 549 list_add(&new->list, chans); 550 new->output = 1; 551 line->chan_out = new; 552 } 553 else { 554 new = parse_chan(line, str, device, opts, error_out); 555 if (new == NULL) 556 return -1; 557 558 list_add(&new->list, chans); 559 new->input = 1; 560 new->output = 1; 561 line->chan_in = line->chan_out = new; 562 } 563 return 0; 564 } 565 566 void chan_interrupt(struct line *line, struct tty_struct *tty, int irq) 567 { 568 struct chan *chan = line->chan_in; 569 int err; 570 char c; 571 572 if (!chan || !chan->ops->read) 573 goto out; 574 575 do { 576 if (tty && !tty_buffer_request_room(tty, 1)) { 577 schedule_delayed_work(&line->task, 1); 578 goto out; 579 } 580 err = chan->ops->read(chan->fd, &c, chan->data); 581 if (err > 0) 582 tty_receive_char(tty, c); 583 } while (err > 0); 584 585 if (err == 0) 586 reactivate_fd(chan->fd, irq); 587 if (err == -EIO) { 588 if (chan->primary) { 589 if (tty != NULL) 590 tty_hangup(tty); 591 if (line->chan_out != chan) 592 close_one_chan(line->chan_out, 1); 593 } 594 close_one_chan(chan, 1); 595 if (chan->primary) 596 return; 597 } 598 out: 599 if (tty) 600 tty_flip_buffer_push(tty); 601 } 602