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