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