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