1/* -*- linux-c -*- 2 * 3 * drivers/char/viocons.c 4 * 5 * iSeries Virtual Terminal 6 * 7 * Authors: Dave Boutcher <boutcher@us.ibm.com> 8 * Ryan Arnold <ryanarn@us.ibm.com> 9 * Colin Devilbiss <devilbis@us.ibm.com> 10 * Stephen Rothwell <sfr@au1.ibm.com> 11 * 12 * (C) Copyright 2000, 2001, 2002, 2003, 2004 IBM Corporation 13 * 14 * This program is free software; you can redistribute it and/or 15 * modify it under the terms of the GNU General Public License as 16 * published by the Free Software Foundation; either version 2 of the 17 * License, or (at your option) anyu later version. 18 * 19 * This program is distributed in the hope that it will be useful, but 20 * WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 * General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, write to the Free Software Foundation, 26 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 */ 28#include <linux/kernel.h> 29#include <linux/proc_fs.h> 30#include <linux/errno.h> 31#include <linux/vmalloc.h> 32#include <linux/mm.h> 33#include <linux/console.h> 34#include <linux/module.h> 35#include <asm/uaccess.h> 36#include <linux/init.h> 37#include <linux/wait.h> 38#include <linux/spinlock.h> 39#include <asm/ioctls.h> 40#include <linux/kd.h> 41#include <linux/tty.h> 42#include <linux/tty_flip.h> 43#include <linux/sysrq.h> 44 45#include <asm/firmware.h> 46#include <asm/iseries/vio.h> 47#include <asm/iseries/hv_lp_event.h> 48#include <asm/iseries/hv_call_event.h> 49#include <asm/iseries/hv_lp_config.h> 50#include <asm/iseries/hv_call.h> 51 52#ifdef CONFIG_VT 53#error You must turn off CONFIG_VT to use CONFIG_VIOCONS 54#endif 55 56#define VIOTTY_MAGIC (0x0DCB) 57#define VTTY_PORTS 10 58 59#define VIOCONS_KERN_WARN KERN_WARNING "viocons: " 60#define VIOCONS_KERN_INFO KERN_INFO "viocons: " 61 62static DEFINE_SPINLOCK(consolelock); 63static DEFINE_SPINLOCK(consoleloglock); 64 65static int vio_sysrq_pressed; 66 67#define VIOCHAR_NUM_BUF 16 68 69/* 70 * Our port information. We store a pointer to one entry in the 71 * tty_driver_data 72 */ 73static struct port_info { 74 int magic; 75 struct tty_struct *tty; 76 HvLpIndex lp; 77 u8 vcons; 78 u64 seq; /* sequence number of last HV send */ 79 u64 ack; /* last ack from HV */ 80/* 81 * When we get writes faster than we can send it to the partition, 82 * buffer the data here. Note that used is a bit map of used buffers. 83 * It had better have enough bits to hold VIOCHAR_NUM_BUF the bitops assume 84 * it is a multiple of unsigned long 85 */ 86 unsigned long used; 87 u8 *buffer[VIOCHAR_NUM_BUF]; 88 int bufferBytes[VIOCHAR_NUM_BUF]; 89 int curbuf; 90 int bufferOverflow; 91 int overflowMessage; 92} port_info[VTTY_PORTS]; 93 94#define viochar_is_console(pi) ((pi) == &port_info[0]) 95#define viochar_port(pi) ((pi) - &port_info[0]) 96 97static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp); 98 99static struct tty_driver *viotty_driver; 100 101static void hvlog(char *fmt, ...) 102{ 103 int i; 104 unsigned long flags; 105 va_list args; 106 static char buf[256]; 107 108 spin_lock_irqsave(&consoleloglock, flags); 109 va_start(args, fmt); 110 i = vscnprintf(buf, sizeof(buf) - 1, fmt, args); 111 va_end(args); 112 buf[i++] = '\r'; 113 HvCall_writeLogBuffer(buf, i); 114 spin_unlock_irqrestore(&consoleloglock, flags); 115} 116 117static void hvlogOutput(const char *buf, int count) 118{ 119 unsigned long flags; 120 int begin; 121 int index; 122 static const char cr = '\r'; 123 124 begin = 0; 125 spin_lock_irqsave(&consoleloglock, flags); 126 for (index = 0; index < count; index++) { 127 if (buf[index] == '\n') { 128 /* 129 * Start right after the last '\n' or at the zeroth 130 * array position and output the number of characters 131 * including the newline. 132 */ 133 HvCall_writeLogBuffer(&buf[begin], index - begin + 1); 134 begin = index + 1; 135 HvCall_writeLogBuffer(&cr, 1); 136 } 137 } 138 if ((index - begin) > 0) 139 HvCall_writeLogBuffer(&buf[begin], index - begin); 140 spin_unlock_irqrestore(&consoleloglock, flags); 141} 142 143/* 144 * Make sure we're pointing to a valid port_info structure. Shamelessly 145 * plagerized from serial.c 146 */ 147static inline int viotty_paranoia_check(struct port_info *pi, 148 char *name, const char *routine) 149{ 150 static const char *bad_pi_addr = VIOCONS_KERN_WARN 151 "warning: bad address for port_info struct (%s) in %s\n"; 152 static const char *badmagic = VIOCONS_KERN_WARN 153 "warning: bad magic number for port_info struct (%s) in %s\n"; 154 155 if ((pi < &port_info[0]) || (viochar_port(pi) > VTTY_PORTS)) { 156 printk(bad_pi_addr, name, routine); 157 return 1; 158 } 159 if (pi->magic != VIOTTY_MAGIC) { 160 printk(badmagic, name, routine); 161 return 1; 162 } 163 return 0; 164} 165 166/* 167 * Add data to our pending-send buffers. 168 * 169 * NOTE: Don't use printk in here because it gets nastily recursive. 170 * hvlog can be used to log to the hypervisor buffer 171 */ 172static int buffer_add(struct port_info *pi, const char *buf, size_t len) 173{ 174 size_t bleft; 175 size_t curlen; 176 const char *curbuf; 177 int nextbuf; 178 179 curbuf = buf; 180 bleft = len; 181 while (bleft > 0) { 182 /* 183 * If there is no space left in the current buffer, we have 184 * filled everything up, so return. If we filled the previous 185 * buffer we would already have moved to the next one. 186 */ 187 if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) { 188 hvlog ("\n\rviocons: No overflow buffer available for memcpy().\n"); 189 pi->bufferOverflow++; 190 pi->overflowMessage = 1; 191 break; 192 } 193 194 /* 195 * Turn on the "used" bit for this buffer. If it's already on, 196 * that's fine. 197 */ 198 set_bit(pi->curbuf, &pi->used); 199 200 /* 201 * See if this buffer has been allocated. If not, allocate it. 202 */ 203 if (pi->buffer[pi->curbuf] == NULL) { 204 pi->buffer[pi->curbuf] = 205 kmalloc(VIOCHAR_MAX_DATA, GFP_ATOMIC); 206 if (pi->buffer[pi->curbuf] == NULL) { 207 hvlog("\n\rviocons: kmalloc failed allocating spaces for buffer %d.", 208 pi->curbuf); 209 break; 210 } 211 } 212 213 /* Figure out how much we can copy into this buffer. */ 214 if (bleft < (VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf])) 215 curlen = bleft; 216 else 217 curlen = VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf]; 218 219 /* Copy the data into the buffer. */ 220 memcpy(pi->buffer[pi->curbuf] + pi->bufferBytes[pi->curbuf], 221 curbuf, curlen); 222 223 pi->bufferBytes[pi->curbuf] += curlen; 224 curbuf += curlen; 225 bleft -= curlen; 226 227 /* 228 * Now see if we've filled this buffer. If not then 229 * we'll try to use it again later. If we've filled it 230 * up then we'll advance the curbuf to the next in the 231 * circular queue. 232 */ 233 if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) { 234 nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF; 235 /* 236 * Move to the next buffer if it hasn't been used yet 237 */ 238 if (test_bit(nextbuf, &pi->used) == 0) 239 pi->curbuf = nextbuf; 240 } 241 } 242 return len - bleft; 243} 244 245/* 246 * Send pending data 247 * 248 * NOTE: Don't use printk in here because it gets nastily recursive. 249 * hvlog can be used to log to the hypervisor buffer 250 */ 251static void send_buffers(struct port_info *pi) 252{ 253 HvLpEvent_Rc hvrc; 254 int nextbuf; 255 struct viocharlpevent *viochar; 256 unsigned long flags; 257 258 spin_lock_irqsave(&consolelock, flags); 259 260 viochar = (struct viocharlpevent *) 261 vio_get_event_buffer(viomajorsubtype_chario); 262 263 /* Make sure we got a buffer */ 264 if (viochar == NULL) { 265 hvlog("\n\rviocons: Can't get viochar buffer in sendBuffers()."); 266 spin_unlock_irqrestore(&consolelock, flags); 267 return; 268 } 269 270 if (pi->used == 0) { 271 hvlog("\n\rviocons: in sendbuffers(), but no buffers used.\n"); 272 vio_free_event_buffer(viomajorsubtype_chario, viochar); 273 spin_unlock_irqrestore(&consolelock, flags); 274 return; 275 } 276 277 /* 278 * curbuf points to the buffer we're filling. We want to 279 * start sending AFTER this one. 280 */ 281 nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF; 282 283 /* 284 * Loop until we find a buffer with the used bit on 285 */ 286 while (test_bit(nextbuf, &pi->used) == 0) 287 nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF; 288 289 initDataEvent(viochar, pi->lp); 290 291 /* 292 * While we have buffers with data, and our send window 293 * is open, send them 294 */ 295 while ((test_bit(nextbuf, &pi->used)) && 296 ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) { 297 viochar->len = pi->bufferBytes[nextbuf]; 298 viochar->event.xCorrelationToken = pi->seq++; 299 viochar->event.xSizeMinus1 = 300 offsetof(struct viocharlpevent, data) + viochar->len; 301 302 memcpy(viochar->data, pi->buffer[nextbuf], viochar->len); 303 304 hvrc = HvCallEvent_signalLpEvent(&viochar->event); 305 if (hvrc) { 306 /* 307 * MUST unlock the spinlock before doing a printk 308 */ 309 vio_free_event_buffer(viomajorsubtype_chario, viochar); 310 spin_unlock_irqrestore(&consolelock, flags); 311 312 printk(VIOCONS_KERN_WARN 313 "error sending event! return code %d\n", 314 (int)hvrc); 315 return; 316 } 317 318 /* 319 * clear the used bit, zero the number of bytes in 320 * this buffer, and move to the next buffer 321 */ 322 clear_bit(nextbuf, &pi->used); 323 pi->bufferBytes[nextbuf] = 0; 324 nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF; 325 } 326 327 /* 328 * If we have emptied all the buffers, start at 0 again. 329 * this will re-use any allocated buffers 330 */ 331 if (pi->used == 0) { 332 pi->curbuf = 0; 333 334 if (pi->overflowMessage) 335 pi->overflowMessage = 0; 336 337 if (pi->tty) { 338 tty_wakeup(pi->tty); 339 } 340 } 341 342 vio_free_event_buffer(viomajorsubtype_chario, viochar); 343 spin_unlock_irqrestore(&consolelock, flags); 344} 345 346/* 347 * Our internal writer. Gets called both from the console device and 348 * the tty device. the tty pointer will be NULL if called from the console. 349 * Return total number of bytes "written". 350 * 351 * NOTE: Don't use printk in here because it gets nastily recursive. hvlog 352 * can be used to log to the hypervisor buffer 353 */ 354static int internal_write(struct port_info *pi, const char *buf, size_t len) 355{ 356 HvLpEvent_Rc hvrc; 357 size_t bleft; 358 size_t curlen; 359 const char *curbuf; 360 unsigned long flags; 361 struct viocharlpevent *viochar; 362 363 /* 364 * Write to the hvlog of inbound data are now done prior to 365 * calling internal_write() since internal_write() is only called in 366 * the event that an lp event path is active, which isn't the case for 367 * logging attempts prior to console initialization. 368 * 369 * If there is already data queued for this port, send it prior to 370 * attempting to send any new data. 371 */ 372 if (pi->used) 373 send_buffers(pi); 374 375 spin_lock_irqsave(&consolelock, flags); 376 377 viochar = vio_get_event_buffer(viomajorsubtype_chario); 378 if (viochar == NULL) { 379 spin_unlock_irqrestore(&consolelock, flags); 380 hvlog("\n\rviocons: Can't get vio buffer in internal_write()."); 381 return -EAGAIN; 382 } 383 initDataEvent(viochar, pi->lp); 384 385 curbuf = buf; 386 bleft = len; 387 388 while ((bleft > 0) && (pi->used == 0) && 389 ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) { 390 if (bleft > VIOCHAR_MAX_DATA) 391 curlen = VIOCHAR_MAX_DATA; 392 else 393 curlen = bleft; 394 395 viochar->event.xCorrelationToken = pi->seq++; 396 memcpy(viochar->data, curbuf, curlen); 397 viochar->len = curlen; 398 viochar->event.xSizeMinus1 = 399 offsetof(struct viocharlpevent, data) + curlen; 400 401 hvrc = HvCallEvent_signalLpEvent(&viochar->event); 402 if (hvrc) { 403 hvlog("viocons: error sending event! %d\n", (int)hvrc); 404 goto out; 405 } 406 curbuf += curlen; 407 bleft -= curlen; 408 } 409 410 /* If we didn't send it all, buffer as much of it as we can. */ 411 if (bleft > 0) 412 bleft -= buffer_add(pi, curbuf, bleft); 413out: 414 vio_free_event_buffer(viomajorsubtype_chario, viochar); 415 spin_unlock_irqrestore(&consolelock, flags); 416 return len - bleft; 417} 418 419static struct port_info *get_port_data(struct tty_struct *tty) 420{ 421 unsigned long flags; 422 struct port_info *pi; 423 424 spin_lock_irqsave(&consolelock, flags); 425 if (tty) { 426 pi = (struct port_info *)tty->driver_data; 427 if (!pi || viotty_paranoia_check(pi, tty->name, 428 "get_port_data")) { 429 pi = NULL; 430 } 431 } else 432 /* 433 * If this is the console device, use the lp from 434 * the first port entry 435 */ 436 pi = &port_info[0]; 437 spin_unlock_irqrestore(&consolelock, flags); 438 return pi; 439} 440 441/* 442 * Initialize the common fields in a charLpEvent 443 */ 444static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp) 445{ 446 struct HvLpEvent *hev = &viochar->event; 447 448 memset(viochar, 0, sizeof(struct viocharlpevent)); 449 450 hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK | 451 HV_LP_EVENT_INT; 452 hev->xType = HvLpEvent_Type_VirtualIo; 453 hev->xSubtype = viomajorsubtype_chario | viochardata; 454 hev->xSourceLp = HvLpConfig_getLpIndex(); 455 hev->xTargetLp = lp; 456 hev->xSizeMinus1 = sizeof(struct viocharlpevent); 457 hev->xSourceInstanceId = viopath_sourceinst(lp); 458 hev->xTargetInstanceId = viopath_targetinst(lp); 459} 460 461/* 462 * early console device write 463 */ 464static void viocons_write_early(struct console *co, const char *s, unsigned count) 465{ 466 hvlogOutput(s, count); 467} 468 469/* 470 * console device write 471 */ 472static void viocons_write(struct console *co, const char *s, unsigned count) 473{ 474 int index; 475 int begin; 476 struct port_info *pi; 477 478 static const char cr = '\r'; 479 480 /* 481 * Check port data first because the target LP might be valid but 482 * simply not active, in which case we want to hvlog the output. 483 */ 484 pi = get_port_data(NULL); 485 if (pi == NULL) { 486 hvlog("\n\rviocons_write: unable to get port data."); 487 return; 488 } 489 490 hvlogOutput(s, count); 491 492 if (!viopath_isactive(pi->lp)) 493 return; 494 495 /* 496 * Any newline character found will cause a 497 * carriage return character to be emitted as well. 498 */ 499 begin = 0; 500 for (index = 0; index < count; index++) { 501 if (s[index] == '\n') { 502 /* 503 * Newline found. Print everything up to and 504 * including the newline 505 */ 506 internal_write(pi, &s[begin], index - begin + 1); 507 begin = index + 1; 508 /* Emit a carriage return as well */ 509 internal_write(pi, &cr, 1); 510 } 511 } 512 513 /* If any characters left to write, write them now */ 514 if ((index - begin) > 0) 515 internal_write(pi, &s[begin], index - begin); 516} 517 518/* 519 * Work out the device associate with this console 520 */ 521static struct tty_driver *viocons_device(struct console *c, int *index) 522{ 523 *index = c->index; 524 return viotty_driver; 525} 526 527/* 528 * console device I/O methods 529 */ 530static struct console viocons_early = { 531 .name = "viocons", 532 .write = viocons_write_early, 533 .flags = CON_PRINTBUFFER, 534 .index = -1, 535}; 536 537static struct console viocons = { 538 .name = "viocons", 539 .write = viocons_write, 540 .device = viocons_device, 541 .flags = CON_PRINTBUFFER, 542 .index = -1, 543}; 544 545/* 546 * TTY Open method 547 */ 548static int viotty_open(struct tty_struct *tty, struct file *filp) 549{ 550 int port; 551 unsigned long flags; 552 struct port_info *pi; 553 554 port = tty->index; 555 556 if ((port < 0) || (port >= VTTY_PORTS)) 557 return -ENODEV; 558 559 spin_lock_irqsave(&consolelock, flags); 560 561 pi = &port_info[port]; 562 /* If some other TTY is already connected here, reject the open */ 563 if ((pi->tty) && (pi->tty != tty)) { 564 spin_unlock_irqrestore(&consolelock, flags); 565 printk(VIOCONS_KERN_WARN 566 "attempt to open device twice from different ttys\n"); 567 return -EBUSY; 568 } 569 tty->driver_data = pi; 570 pi->tty = tty; 571 spin_unlock_irqrestore(&consolelock, flags); 572 573 return 0; 574} 575 576/* 577 * TTY Close method 578 */ 579static void viotty_close(struct tty_struct *tty, struct file *filp) 580{ 581 unsigned long flags; 582 struct port_info *pi; 583 584 spin_lock_irqsave(&consolelock, flags); 585 pi = (struct port_info *)tty->driver_data; 586 587 if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_close")) { 588 spin_unlock_irqrestore(&consolelock, flags); 589 return; 590 } 591 if (tty->count == 1) 592 pi->tty = NULL; 593 spin_unlock_irqrestore(&consolelock, flags); 594} 595 596/* 597 * TTY Write method 598 */ 599static int viotty_write(struct tty_struct *tty, const unsigned char *buf, 600 int count) 601{ 602 struct port_info *pi; 603 604 pi = get_port_data(tty); 605 if (pi == NULL) { 606 hvlog("\n\rviotty_write: no port data."); 607 return -ENODEV; 608 } 609 610 if (viochar_is_console(pi)) 611 hvlogOutput(buf, count); 612 613 /* 614 * If the path to this LP is closed, don't bother doing anything more. 615 * just dump the data on the floor and return count. For some reason 616 * some user level programs will attempt to probe available tty's and 617 * they'll attempt a viotty_write on an invalid port which maps to an 618 * invalid target lp. If this is the case then ignore the 619 * viotty_write call and, since the viopath isn't active to this 620 * partition, return count. 621 */ 622 if (!viopath_isactive(pi->lp)) 623 return count; 624 625 return internal_write(pi, buf, count); 626} 627 628/* 629 * TTY put_char method 630 */ 631static void viotty_put_char(struct tty_struct *tty, unsigned char ch) 632{ 633 struct port_info *pi; 634 635 pi = get_port_data(tty); 636 if (pi == NULL) 637 return; 638 639 /* This will append '\r' as well if the char is '\n' */ 640 if (viochar_is_console(pi)) 641 hvlogOutput(&ch, 1); 642 643 if (viopath_isactive(pi->lp)) 644 internal_write(pi, &ch, 1); 645} 646 647/* 648 * TTY write_room method 649 */ 650static int viotty_write_room(struct tty_struct *tty) 651{ 652 int i; 653 int room = 0; 654 struct port_info *pi; 655 unsigned long flags; 656 657 spin_lock_irqsave(&consolelock, flags); 658 pi = (struct port_info *)tty->driver_data; 659 if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_write_room")) { 660 spin_unlock_irqrestore(&consolelock, flags); 661 return 0; 662 } 663 664 /* If no buffers are used, return the max size. */ 665 if (pi->used == 0) { 666 spin_unlock_irqrestore(&consolelock, flags); 667 return VIOCHAR_MAX_DATA * VIOCHAR_NUM_BUF; 668 } 669 670 /* 671 * We retain the spinlock because we want to get an accurate 672 * count and it can change on us between each operation if we 673 * don't hold the spinlock. 674 */ 675 for (i = 0; ((i < VIOCHAR_NUM_BUF) && (room < VIOCHAR_MAX_DATA)); i++) 676 room += (VIOCHAR_MAX_DATA - pi->bufferBytes[i]); 677 spin_unlock_irqrestore(&consolelock, flags); 678 679 if (room > VIOCHAR_MAX_DATA) 680 room = VIOCHAR_MAX_DATA; 681 return room; 682} 683 684/* 685 * TTY chars_in_buffer method 686 */ 687static int viotty_chars_in_buffer(struct tty_struct *tty) 688{ 689 return 0; 690} 691 692static int viotty_ioctl(struct tty_struct *tty, struct file *file, 693 unsigned int cmd, unsigned long arg) 694{ 695 switch (cmd) { 696 /* 697 * the ioctls below read/set the flags usually shown in the leds 698 * don't use them - they will go away without warning 699 */ 700 case KDGETLED: 701 case KDGKBLED: 702 return put_user(0, (char *)arg); 703 704 case KDSKBLED: 705 return 0; 706 } 707 708 return n_tty_ioctl(tty, file, cmd, arg); 709} 710 711/* 712 * Handle an open charLpEvent. Could be either interrupt or ack 713 */ 714static void vioHandleOpenEvent(struct HvLpEvent *event) 715{ 716 unsigned long flags; 717 struct viocharlpevent *cevent = (struct viocharlpevent *)event; 718 u8 port = cevent->virtual_device; 719 struct port_info *pi; 720 int reject = 0; 721 722 if (hvlpevent_is_ack(event)) { 723 if (port >= VTTY_PORTS) 724 return; 725 726 spin_lock_irqsave(&consolelock, flags); 727 /* Got the lock, don't cause console output */ 728 729 pi = &port_info[port]; 730 if (event->xRc == HvLpEvent_Rc_Good) { 731 pi->seq = pi->ack = 0; 732 /* 733 * This line allows connections from the primary 734 * partition but once one is connected from the 735 * primary partition nothing short of a reboot 736 * of linux will allow access from the hosting 737 * partition again without a required iSeries fix. 738 */ 739 pi->lp = event->xTargetLp; 740 } 741 742 spin_unlock_irqrestore(&consolelock, flags); 743 if (event->xRc != HvLpEvent_Rc_Good) 744 printk(VIOCONS_KERN_WARN 745 "handle_open_event: event->xRc == (%d).\n", 746 event->xRc); 747 748 if (event->xCorrelationToken != 0) { 749 atomic_t *aptr= (atomic_t *)event->xCorrelationToken; 750 atomic_set(aptr, 1); 751 } else 752 printk(VIOCONS_KERN_WARN 753 "weird...got open ack without atomic\n"); 754 return; 755 } 756 757 /* This had better require an ack, otherwise complain */ 758 if (!hvlpevent_need_ack(event)) { 759 printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n"); 760 return; 761 } 762 763 spin_lock_irqsave(&consolelock, flags); 764 /* Got the lock, don't cause console output */ 765 766 /* Make sure this is a good virtual tty */ 767 if (port >= VTTY_PORTS) { 768 event->xRc = HvLpEvent_Rc_SubtypeError; 769 cevent->subtype_result_code = viorc_openRejected; 770 /* 771 * Flag state here since we can't printk while holding 772 * a spinlock. 773 */ 774 reject = 1; 775 } else { 776 pi = &port_info[port]; 777 if ((pi->lp != HvLpIndexInvalid) && 778 (pi->lp != event->xSourceLp)) { 779 /* 780 * If this is tty is already connected to a different 781 * partition, fail. 782 */ 783 event->xRc = HvLpEvent_Rc_SubtypeError; 784 cevent->subtype_result_code = viorc_openRejected; 785 reject = 2; 786 } else { 787 pi->lp = event->xSourceLp; 788 event->xRc = HvLpEvent_Rc_Good; 789 cevent->subtype_result_code = viorc_good; 790 pi->seq = pi->ack = 0; 791 reject = 0; 792 } 793 } 794 795 spin_unlock_irqrestore(&consolelock, flags); 796 797 if (reject == 1) 798 printk(VIOCONS_KERN_WARN "open rejected: bad virtual tty.\n"); 799 else if (reject == 2) 800 printk(VIOCONS_KERN_WARN 801 "open rejected: console in exclusive use by another partition.\n"); 802 803 /* Return the acknowledgement */ 804 HvCallEvent_ackLpEvent(event); 805} 806 807/* 808 * Handle a close charLpEvent. This should ONLY be an Interrupt because the 809 * virtual console should never actually issue a close event to the hypervisor 810 * because the virtual console never goes away. A close event coming from the 811 * hypervisor simply means that there are no client consoles connected to the 812 * virtual console. 813 * 814 * Regardless of the number of connections masqueraded on the other side of 815 * the hypervisor ONLY ONE close event should be called to accompany the ONE 816 * open event that is called. The close event should ONLY be called when NO 817 * MORE connections (masqueraded or not) exist on the other side of the 818 * hypervisor. 819 */ 820static void vioHandleCloseEvent(struct HvLpEvent *event) 821{ 822 unsigned long flags; 823 struct viocharlpevent *cevent = (struct viocharlpevent *)event; 824 u8 port = cevent->virtual_device; 825 826 if (hvlpevent_is_int(event)) { 827 if (port >= VTTY_PORTS) { 828 printk(VIOCONS_KERN_WARN 829 "close message from invalid virtual device.\n"); 830 return; 831 } 832 833 /* For closes, just mark the console partition invalid */ 834 spin_lock_irqsave(&consolelock, flags); 835 /* Got the lock, don't cause console output */ 836 837 if (port_info[port].lp == event->xSourceLp) 838 port_info[port].lp = HvLpIndexInvalid; 839 840 spin_unlock_irqrestore(&consolelock, flags); 841 printk(VIOCONS_KERN_INFO "close from %d\n", event->xSourceLp); 842 } else 843 printk(VIOCONS_KERN_WARN 844 "got unexpected close acknowlegement\n"); 845} 846 847/* 848 * Handle a config charLpEvent. Could be either interrupt or ack 849 */ 850static void vioHandleConfig(struct HvLpEvent *event) 851{ 852 struct viocharlpevent *cevent = (struct viocharlpevent *)event; 853 854 HvCall_writeLogBuffer(cevent->data, cevent->len); 855 856 if (cevent->data[0] == 0x01) 857 printk(VIOCONS_KERN_INFO "window resized to %d: %d: %d: %d\n", 858 cevent->data[1], cevent->data[2], 859 cevent->data[3], cevent->data[4]); 860 else 861 printk(VIOCONS_KERN_WARN "unknown config event\n"); 862} 863 864/* 865 * Handle a data charLpEvent. 866 */ 867static void vioHandleData(struct HvLpEvent *event) 868{ 869 struct tty_struct *tty; 870 unsigned long flags; 871 struct viocharlpevent *cevent = (struct viocharlpevent *)event; 872 struct port_info *pi; 873 int index; 874 int num_pushed; 875 u8 port = cevent->virtual_device; 876 877 if (port >= VTTY_PORTS) { 878 printk(VIOCONS_KERN_WARN "data on invalid virtual device %d\n", 879 port); 880 return; 881 } 882 883 /* 884 * Hold the spinlock so that we don't take an interrupt that 885 * changes tty between the time we fetch the port_info 886 * pointer and the time we paranoia check. 887 */ 888 spin_lock_irqsave(&consolelock, flags); 889 pi = &port_info[port]; 890 891 /* 892 * Change 05/01/2003 - Ryan Arnold: If a partition other than 893 * the current exclusive partition tries to send us data 894 * events then just drop them on the floor because we don't 895 * want his stinking data. He isn't authorized to receive 896 * data because he wasn't the first one to get the console, 897 * therefore he shouldn't be allowed to send data either. 898 * This will work without an iSeries fix. 899 */ 900 if (pi->lp != event->xSourceLp) { 901 spin_unlock_irqrestore(&consolelock, flags); 902 return; 903 } 904 905 tty = pi->tty; 906 if (tty == NULL) { 907 spin_unlock_irqrestore(&consolelock, flags); 908 printk(VIOCONS_KERN_WARN "no tty for virtual device %d\n", 909 port); 910 return; 911 } 912 913 if (tty->magic != TTY_MAGIC) { 914 spin_unlock_irqrestore(&consolelock, flags); 915 printk(VIOCONS_KERN_WARN "tty bad magic\n"); 916 return; 917 } 918 919 /* 920 * Just to be paranoid, make sure the tty points back to this port 921 */ 922 pi = (struct port_info *)tty->driver_data; 923 if (!pi || viotty_paranoia_check(pi, tty->name, "vioHandleData")) { 924 spin_unlock_irqrestore(&consolelock, flags); 925 return; 926 } 927 spin_unlock_irqrestore(&consolelock, flags); 928 929 /* 930 * Change 07/21/2003 - Ryan Arnold: functionality added to 931 * support sysrq utilizing ^O as the sysrq key. The sysrq 932 * functionality will only work if built into the kernel and 933 * then only if sysrq is enabled through the proc filesystem. 934 */ 935 num_pushed = 0; 936 for (index = 0; index < cevent->len; index++) { 937 /* 938 * Will be optimized away if !CONFIG_MAGIC_SYSRQ: 939 */ 940 if (sysrq_on()) { 941 /* 0x0f is the ascii character for ^O */ 942 if (cevent->data[index] == '\x0f') { 943 vio_sysrq_pressed = 1; 944 /* 945 * continue because we don't want to add 946 * the sysrq key into the data string. 947 */ 948 continue; 949 } else if (vio_sysrq_pressed) { 950 handle_sysrq(cevent->data[index], tty); 951 vio_sysrq_pressed = 0; 952 /* 953 * continue because we don't want to add 954 * the sysrq sequence into the data string. 955 */ 956 continue; 957 } 958 } 959 /* 960 * The sysrq sequence isn't included in this check if 961 * sysrq is enabled and compiled into the kernel because 962 * the sequence will never get inserted into the buffer. 963 * Don't attempt to copy more data into the buffer than we 964 * have room for because it would fail without indication. 965 */ 966 if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) { 967 printk(VIOCONS_KERN_WARN "input buffer overflow!\n"); 968 break; 969 } 970 num_pushed++; 971 } 972 973 if (num_pushed) 974 tty_flip_buffer_push(tty); 975} 976 977/* 978 * Handle an ack charLpEvent. 979 */ 980static void vioHandleAck(struct HvLpEvent *event) 981{ 982 struct viocharlpevent *cevent = (struct viocharlpevent *)event; 983 unsigned long flags; 984 u8 port = cevent->virtual_device; 985 986 if (port >= VTTY_PORTS) { 987 printk(VIOCONS_KERN_WARN "data on invalid virtual device\n"); 988 return; 989 } 990 991 spin_lock_irqsave(&consolelock, flags); 992 port_info[port].ack = event->xCorrelationToken; 993 spin_unlock_irqrestore(&consolelock, flags); 994 995 if (port_info[port].used) 996 send_buffers(&port_info[port]); 997} 998 999/* 1000 * Handle charLpEvents and route to the appropriate routine 1001 */ 1002static void vioHandleCharEvent(struct HvLpEvent *event) 1003{ 1004 int charminor; 1005 1006 if (event == NULL) 1007 return; 1008 1009 charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; 1010 switch (charminor) { 1011 case viocharopen: 1012 vioHandleOpenEvent(event); 1013 break; 1014 case viocharclose: 1015 vioHandleCloseEvent(event); 1016 break; 1017 case viochardata: 1018 vioHandleData(event); 1019 break; 1020 case viocharack: 1021 vioHandleAck(event); 1022 break; 1023 case viocharconfig: 1024 vioHandleConfig(event); 1025 break; 1026 default: 1027 if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) { 1028 event->xRc = HvLpEvent_Rc_InvalidSubtype; 1029 HvCallEvent_ackLpEvent(event); 1030 } 1031 } 1032} 1033 1034/* 1035 * Send an open event 1036 */ 1037static int send_open(HvLpIndex remoteLp, void *sem) 1038{ 1039 return HvCallEvent_signalLpEventFast(remoteLp, 1040 HvLpEvent_Type_VirtualIo, 1041 viomajorsubtype_chario | viocharopen, 1042 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, 1043 viopath_sourceinst(remoteLp), 1044 viopath_targetinst(remoteLp), 1045 (u64)(unsigned long)sem, VIOVERSION << 16, 1046 0, 0, 0, 0); 1047} 1048 1049static const struct tty_operations serial_ops = { 1050 .open = viotty_open, 1051 .close = viotty_close, 1052 .write = viotty_write, 1053 .put_char = viotty_put_char, 1054 .write_room = viotty_write_room, 1055 .chars_in_buffer = viotty_chars_in_buffer, 1056 .ioctl = viotty_ioctl, 1057}; 1058 1059static int __init viocons_init2(void) 1060{ 1061 atomic_t wait_flag; 1062 int rc; 1063 1064 if (!firmware_has_feature(FW_FEATURE_ISERIES)) 1065 return -ENODEV; 1066 1067 /* +2 for fudge */ 1068 rc = viopath_open(HvLpConfig_getPrimaryLpIndex(), 1069 viomajorsubtype_chario, VIOCHAR_WINDOW + 2); 1070 if (rc) 1071 printk(VIOCONS_KERN_WARN "error opening to primary %d\n", rc); 1072 1073 if (viopath_hostLp == HvLpIndexInvalid) 1074 vio_set_hostlp(); 1075 1076 /* 1077 * And if the primary is not the same as the hosting LP, open to the 1078 * hosting lp 1079 */ 1080 if ((viopath_hostLp != HvLpIndexInvalid) && 1081 (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) { 1082 printk(VIOCONS_KERN_INFO "open path to hosting (%d)\n", 1083 viopath_hostLp); 1084 rc = viopath_open(viopath_hostLp, viomajorsubtype_chario, 1085 VIOCHAR_WINDOW + 2); /* +2 for fudge */ 1086 if (rc) 1087 printk(VIOCONS_KERN_WARN 1088 "error opening to partition %d: %d\n", 1089 viopath_hostLp, rc); 1090 } 1091 1092 if (vio_setHandler(viomajorsubtype_chario, vioHandleCharEvent) < 0) 1093 printk(VIOCONS_KERN_WARN 1094 "error seting handler for console events!\n"); 1095 1096 /* 1097 * First, try to open the console to the hosting lp. 1098 * Wait on a semaphore for the response. 1099 */ 1100 atomic_set(&wait_flag, 0); 1101 if ((viopath_isactive(viopath_hostLp)) && 1102 (send_open(viopath_hostLp, (void *)&wait_flag) == 0)) { 1103 printk(VIOCONS_KERN_INFO "hosting partition %d\n", 1104 viopath_hostLp); 1105 while (atomic_read(&wait_flag) == 0) 1106 mb(); 1107 atomic_set(&wait_flag, 0); 1108 } 1109 1110 /* 1111 * If we don't have an active console, try the primary 1112 */ 1113 if ((!viopath_isactive(port_info[0].lp)) && 1114 (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) && 1115 (send_open(HvLpConfig_getPrimaryLpIndex(), (void *)&wait_flag) 1116 == 0)) { 1117 printk(VIOCONS_KERN_INFO "opening console to primary partition\n"); 1118 while (atomic_read(&wait_flag) == 0) 1119 mb(); 1120 } 1121 1122 /* Initialize the tty_driver structure */ 1123 viotty_driver = alloc_tty_driver(VTTY_PORTS); 1124 viotty_driver->owner = THIS_MODULE; 1125 viotty_driver->driver_name = "vioconsole"; 1126 viotty_driver->name = "tty"; 1127 viotty_driver->name_base = 1; 1128 viotty_driver->major = TTY_MAJOR; 1129 viotty_driver->minor_start = 1; 1130 viotty_driver->type = TTY_DRIVER_TYPE_CONSOLE; 1131 viotty_driver->subtype = 1; 1132 viotty_driver->init_termios = tty_std_termios; 1133 viotty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; 1134 tty_set_operations(viotty_driver, &serial_ops); 1135 1136 if (tty_register_driver(viotty_driver)) { 1137 printk(VIOCONS_KERN_WARN "couldn't register console driver\n"); 1138 put_tty_driver(viotty_driver); 1139 viotty_driver = NULL; 1140 } 1141 1142 unregister_console(&viocons_early); 1143 register_console(&viocons); 1144 1145 return 0; 1146} 1147 1148static int __init viocons_init(void) 1149{ 1150 int i; 1151 1152 if (!firmware_has_feature(FW_FEATURE_ISERIES)) 1153 return -ENODEV; 1154 1155 printk(VIOCONS_KERN_INFO "registering console\n"); 1156 for (i = 0; i < VTTY_PORTS; i++) { 1157 port_info[i].lp = HvLpIndexInvalid; 1158 port_info[i].magic = VIOTTY_MAGIC; 1159 } 1160 HvCall_setLogBufferFormatAndCodepage(HvCall_LogBuffer_ASCII, 437); 1161 add_preferred_console("viocons", 0, NULL); 1162 register_console(&viocons_early); 1163 return 0; 1164} 1165 1166console_initcall(viocons_init); 1167module_init(viocons_init2); 1168