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