Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / char / viocons.c
blob44f5fb4a46efaec16a59ae47b673e0362bb18d2e
1 /* -*- linux-c -*-
3 * drivers/char/viocons.c
5 * iSeries Virtual Terminal
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>
12 * (C) Copyright 2000, 2001, 2002, 2003, 2004 IBM Corporation
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.
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.
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
28 #include <linux/config.h>
29 #include <linux/version.h>
30 #include <linux/kernel.h>
31 #include <linux/proc_fs.h>
32 #include <linux/errno.h>
33 #include <linux/vmalloc.h>
34 #include <linux/mm.h>
35 #include <linux/console.h>
36 #include <linux/module.h>
37 #include <asm/uaccess.h>
38 #include <linux/init.h>
39 #include <linux/wait.h>
40 #include <linux/spinlock.h>
41 #include <asm/ioctls.h>
42 #include <linux/kd.h>
43 #include <linux/tty.h>
44 #include <linux/tty_flip.h>
45 #include <linux/sysrq.h>
47 #include <asm/iSeries/vio.h>
49 #include <asm/iSeries/HvLpEvent.h>
50 #include <asm/iSeries/HvCallEvent.h>
51 #include <asm/iSeries/HvLpConfig.h>
52 #include <asm/iSeries/HvCall.h>
54 #ifdef CONFIG_VT
55 #error You must turn off CONFIG_VT to use CONFIG_VIOCONS
56 #endif
58 #define VIOTTY_MAGIC (0x0DCB)
59 #define VTTY_PORTS 10
61 #define VIOCONS_KERN_WARN KERN_WARNING "viocons: "
62 #define VIOCONS_KERN_INFO KERN_INFO "viocons: "
64 static DEFINE_SPINLOCK(consolelock);
65 static DEFINE_SPINLOCK(consoleloglock);
67 #ifdef CONFIG_MAGIC_SYSRQ
68 static int vio_sysrq_pressed;
69 extern int sysrq_enabled;
70 #endif
73 * The structure of the events that flow between us and OS/400. You can't
74 * mess with this unless the OS/400 side changes too
76 struct viocharlpevent {
77 struct HvLpEvent event;
78 u32 reserved;
79 u16 version;
80 u16 subtype_result_code;
81 u8 virtual_device;
82 u8 len;
83 u8 data[VIOCHAR_MAX_DATA];
86 #define VIOCHAR_WINDOW 10
87 #define VIOCHAR_HIGHWATERMARK 3
89 enum viocharsubtype {
90 viocharopen = 0x0001,
91 viocharclose = 0x0002,
92 viochardata = 0x0003,
93 viocharack = 0x0004,
94 viocharconfig = 0x0005
97 enum viochar_rc {
98 viochar_rc_ebusy = 1
101 #define VIOCHAR_NUM_BUF 16
104 * Our port information. We store a pointer to one entry in the
105 * tty_driver_data
107 static struct port_info {
108 int magic;
109 struct tty_struct *tty;
110 HvLpIndex lp;
111 u8 vcons;
112 u64 seq; /* sequence number of last HV send */
113 u64 ack; /* last ack from HV */
115 * When we get writes faster than we can send it to the partition,
116 * buffer the data here. Note that used is a bit map of used buffers.
117 * It had better have enough bits to hold VIOCHAR_NUM_BUF the bitops assume
118 * it is a multiple of unsigned long
120 unsigned long used;
121 u8 *buffer[VIOCHAR_NUM_BUF];
122 int bufferBytes[VIOCHAR_NUM_BUF];
123 int curbuf;
124 int bufferOverflow;
125 int overflowMessage;
126 } port_info[VTTY_PORTS];
128 #define viochar_is_console(pi) ((pi) == &port_info[0])
129 #define viochar_port(pi) ((pi) - &port_info[0])
131 static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp);
133 static struct tty_driver *viotty_driver;
135 void hvlog(char *fmt, ...)
137 int i;
138 unsigned long flags;
139 va_list args;
140 static char buf[256];
142 spin_lock_irqsave(&consoleloglock, flags);
143 va_start(args, fmt);
144 i = vscnprintf(buf, sizeof(buf) - 1, fmt, args);
145 va_end(args);
146 buf[i++] = '\r';
147 HvCall_writeLogBuffer(buf, i);
148 spin_unlock_irqrestore(&consoleloglock, flags);
151 void hvlogOutput(const char *buf, int count)
153 unsigned long flags;
154 int begin;
155 int index;
156 static const char cr = '\r';
158 begin = 0;
159 spin_lock_irqsave(&consoleloglock, flags);
160 for (index = 0; index < count; index++) {
161 if (buf[index] == '\n') {
163 * Start right after the last '\n' or at the zeroth
164 * array position and output the number of characters
165 * including the newline.
167 HvCall_writeLogBuffer(&buf[begin], index - begin + 1);
168 begin = index + 1;
169 HvCall_writeLogBuffer(&cr, 1);
172 if ((index - begin) > 0)
173 HvCall_writeLogBuffer(&buf[begin], index - begin);
174 spin_unlock_irqrestore(&consoleloglock, flags);
178 * Make sure we're pointing to a valid port_info structure. Shamelessly
179 * plagerized from serial.c
181 static inline int viotty_paranoia_check(struct port_info *pi,
182 char *name, const char *routine)
184 static const char *bad_pi_addr = VIOCONS_KERN_WARN
185 "warning: bad address for port_info struct (%s) in %s\n";
186 static const char *badmagic = VIOCONS_KERN_WARN
187 "warning: bad magic number for port_info struct (%s) in %s\n";
189 if ((pi < &port_info[0]) || (viochar_port(pi) > VTTY_PORTS)) {
190 printk(bad_pi_addr, name, routine);
191 return 1;
193 if (pi->magic != VIOTTY_MAGIC) {
194 printk(badmagic, name, routine);
195 return 1;
197 return 0;
201 * Add data to our pending-send buffers.
203 * NOTE: Don't use printk in here because it gets nastily recursive.
204 * hvlog can be used to log to the hypervisor buffer
206 static int buffer_add(struct port_info *pi, const char *buf, size_t len)
208 size_t bleft;
209 size_t curlen;
210 const char *curbuf;
211 int nextbuf;
213 curbuf = buf;
214 bleft = len;
215 while (bleft > 0) {
217 * If there is no space left in the current buffer, we have
218 * filled everything up, so return. If we filled the previous
219 * buffer we would already have moved to the next one.
221 if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) {
222 hvlog ("\n\rviocons: No overflow buffer available for memcpy().\n");
223 pi->bufferOverflow++;
224 pi->overflowMessage = 1;
225 break;
229 * Turn on the "used" bit for this buffer. If it's already on,
230 * that's fine.
232 set_bit(pi->curbuf, &pi->used);
235 * See if this buffer has been allocated. If not, allocate it.
237 if (pi->buffer[pi->curbuf] == NULL) {
238 pi->buffer[pi->curbuf] =
239 kmalloc(VIOCHAR_MAX_DATA, GFP_ATOMIC);
240 if (pi->buffer[pi->curbuf] == NULL) {
241 hvlog("\n\rviocons: kmalloc failed allocating spaces for buffer %d.",
242 pi->curbuf);
243 break;
247 /* Figure out how much we can copy into this buffer. */
248 if (bleft < (VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf]))
249 curlen = bleft;
250 else
251 curlen = VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf];
253 /* Copy the data into the buffer. */
254 memcpy(pi->buffer[pi->curbuf] + pi->bufferBytes[pi->curbuf],
255 curbuf, curlen);
257 pi->bufferBytes[pi->curbuf] += curlen;
258 curbuf += curlen;
259 bleft -= curlen;
262 * Now see if we've filled this buffer. If not then
263 * we'll try to use it again later. If we've filled it
264 * up then we'll advance the curbuf to the next in the
265 * circular queue.
267 if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) {
268 nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF;
270 * Move to the next buffer if it hasn't been used yet
272 if (test_bit(nextbuf, &pi->used) == 0)
273 pi->curbuf = nextbuf;
276 return len - bleft;
280 * Send pending data
282 * NOTE: Don't use printk in here because it gets nastily recursive.
283 * hvlog can be used to log to the hypervisor buffer
285 static void send_buffers(struct port_info *pi)
287 HvLpEvent_Rc hvrc;
288 int nextbuf;
289 struct viocharlpevent *viochar;
290 unsigned long flags;
292 spin_lock_irqsave(&consolelock, flags);
294 viochar = (struct viocharlpevent *)
295 vio_get_event_buffer(viomajorsubtype_chario);
297 /* Make sure we got a buffer */
298 if (viochar == NULL) {
299 hvlog("\n\rviocons: Can't get viochar buffer in sendBuffers().");
300 spin_unlock_irqrestore(&consolelock, flags);
301 return;
304 if (pi->used == 0) {
305 hvlog("\n\rviocons: in sendbuffers(), but no buffers used.\n");
306 vio_free_event_buffer(viomajorsubtype_chario, viochar);
307 spin_unlock_irqrestore(&consolelock, flags);
308 return;
312 * curbuf points to the buffer we're filling. We want to
313 * start sending AFTER this one.
315 nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF;
318 * Loop until we find a buffer with the used bit on
320 while (test_bit(nextbuf, &pi->used) == 0)
321 nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF;
323 initDataEvent(viochar, pi->lp);
326 * While we have buffers with data, and our send window
327 * is open, send them
329 while ((test_bit(nextbuf, &pi->used)) &&
330 ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) {
331 viochar->len = pi->bufferBytes[nextbuf];
332 viochar->event.xCorrelationToken = pi->seq++;
333 viochar->event.xSizeMinus1 =
334 offsetof(struct viocharlpevent, data) + viochar->len;
336 memcpy(viochar->data, pi->buffer[nextbuf], viochar->len);
338 hvrc = HvCallEvent_signalLpEvent(&viochar->event);
339 if (hvrc) {
341 * MUST unlock the spinlock before doing a printk
343 vio_free_event_buffer(viomajorsubtype_chario, viochar);
344 spin_unlock_irqrestore(&consolelock, flags);
346 printk(VIOCONS_KERN_WARN
347 "error sending event! return code %d\n",
348 (int)hvrc);
349 return;
353 * clear the used bit, zero the number of bytes in
354 * this buffer, and move to the next buffer
356 clear_bit(nextbuf, &pi->used);
357 pi->bufferBytes[nextbuf] = 0;
358 nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF;
362 * If we have emptied all the buffers, start at 0 again.
363 * this will re-use any allocated buffers
365 if (pi->used == 0) {
366 pi->curbuf = 0;
368 if (pi->overflowMessage)
369 pi->overflowMessage = 0;
371 if (pi->tty) {
372 tty_wakeup(pi->tty);
376 vio_free_event_buffer(viomajorsubtype_chario, viochar);
377 spin_unlock_irqrestore(&consolelock, flags);
381 * Our internal writer. Gets called both from the console device and
382 * the tty device. the tty pointer will be NULL if called from the console.
383 * Return total number of bytes "written".
385 * NOTE: Don't use printk in here because it gets nastily recursive. hvlog
386 * can be used to log to the hypervisor buffer
388 static int internal_write(struct port_info *pi, const char *buf, size_t len)
390 HvLpEvent_Rc hvrc;
391 size_t bleft;
392 size_t curlen;
393 const char *curbuf;
394 unsigned long flags;
395 struct viocharlpevent *viochar;
398 * Write to the hvlog of inbound data are now done prior to
399 * calling internal_write() since internal_write() is only called in
400 * the event that an lp event path is active, which isn't the case for
401 * logging attempts prior to console initialization.
403 * If there is already data queued for this port, send it prior to
404 * attempting to send any new data.
406 if (pi->used)
407 send_buffers(pi);
409 spin_lock_irqsave(&consolelock, flags);
411 viochar = vio_get_event_buffer(viomajorsubtype_chario);
412 if (viochar == NULL) {
413 spin_unlock_irqrestore(&consolelock, flags);
414 hvlog("\n\rviocons: Can't get vio buffer in internal_write().");
415 return -EAGAIN;
417 initDataEvent(viochar, pi->lp);
419 curbuf = buf;
420 bleft = len;
422 while ((bleft > 0) && (pi->used == 0) &&
423 ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) {
424 if (bleft > VIOCHAR_MAX_DATA)
425 curlen = VIOCHAR_MAX_DATA;
426 else
427 curlen = bleft;
429 viochar->event.xCorrelationToken = pi->seq++;
430 memcpy(viochar->data, curbuf, curlen);
431 viochar->len = curlen;
432 viochar->event.xSizeMinus1 =
433 offsetof(struct viocharlpevent, data) + curlen;
435 hvrc = HvCallEvent_signalLpEvent(&viochar->event);
436 if (hvrc) {
437 hvlog("viocons: error sending event! %d\n", (int)hvrc);
438 goto out;
440 curbuf += curlen;
441 bleft -= curlen;
444 /* If we didn't send it all, buffer as much of it as we can. */
445 if (bleft > 0)
446 bleft -= buffer_add(pi, curbuf, bleft);
447 out:
448 vio_free_event_buffer(viomajorsubtype_chario, viochar);
449 spin_unlock_irqrestore(&consolelock, flags);
450 return len - bleft;
453 static struct port_info *get_port_data(struct tty_struct *tty)
455 unsigned long flags;
456 struct port_info *pi;
458 spin_lock_irqsave(&consolelock, flags);
459 if (tty) {
460 pi = (struct port_info *)tty->driver_data;
461 if (!pi || viotty_paranoia_check(pi, tty->name,
462 "get_port_data")) {
463 pi = NULL;
465 } else
467 * If this is the console device, use the lp from
468 * the first port entry
470 pi = &port_info[0];
471 spin_unlock_irqrestore(&consolelock, flags);
472 return pi;
476 * Initialize the common fields in a charLpEvent
478 static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp)
480 memset(viochar, 0, sizeof(struct viocharlpevent));
482 viochar->event.xFlags.xValid = 1;
483 viochar->event.xFlags.xFunction = HvLpEvent_Function_Int;
484 viochar->event.xFlags.xAckInd = HvLpEvent_AckInd_NoAck;
485 viochar->event.xFlags.xAckType = HvLpEvent_AckType_DeferredAck;
486 viochar->event.xType = HvLpEvent_Type_VirtualIo;
487 viochar->event.xSubtype = viomajorsubtype_chario | viochardata;
488 viochar->event.xSourceLp = HvLpConfig_getLpIndex();
489 viochar->event.xTargetLp = lp;
490 viochar->event.xSizeMinus1 = sizeof(struct viocharlpevent);
491 viochar->event.xSourceInstanceId = viopath_sourceinst(lp);
492 viochar->event.xTargetInstanceId = viopath_targetinst(lp);
496 * early console device write
498 static void viocons_write_early(struct console *co, const char *s, unsigned count)
500 hvlogOutput(s, count);
504 * console device write
506 static void viocons_write(struct console *co, const char *s, unsigned count)
508 int index;
509 int begin;
510 struct port_info *pi;
512 static const char cr = '\r';
515 * Check port data first because the target LP might be valid but
516 * simply not active, in which case we want to hvlog the output.
518 pi = get_port_data(NULL);
519 if (pi == NULL) {
520 hvlog("\n\rviocons_write: unable to get port data.");
521 return;
524 hvlogOutput(s, count);
526 if (!viopath_isactive(pi->lp))
527 return;
530 * Any newline character found will cause a
531 * carriage return character to be emitted as well.
533 begin = 0;
534 for (index = 0; index < count; index++) {
535 if (s[index] == '\n') {
537 * Newline found. Print everything up to and
538 * including the newline
540 internal_write(pi, &s[begin], index - begin + 1);
541 begin = index + 1;
542 /* Emit a carriage return as well */
543 internal_write(pi, &cr, 1);
547 /* If any characters left to write, write them now */
548 if ((index - begin) > 0)
549 internal_write(pi, &s[begin], index - begin);
553 * Work out the device associate with this console
555 static struct tty_driver *viocons_device(struct console *c, int *index)
557 *index = c->index;
558 return viotty_driver;
562 * console device I/O methods
564 static struct console viocons_early = {
565 .name = "viocons",
566 .write = viocons_write_early,
567 .flags = CON_PRINTBUFFER,
568 .index = -1,
571 static struct console viocons = {
572 .name = "viocons",
573 .write = viocons_write,
574 .device = viocons_device,
575 .flags = CON_PRINTBUFFER,
576 .index = -1,
580 * TTY Open method
582 static int viotty_open(struct tty_struct *tty, struct file *filp)
584 int port;
585 unsigned long flags;
586 struct port_info *pi;
588 port = tty->index;
590 if ((port < 0) || (port >= VTTY_PORTS))
591 return -ENODEV;
593 spin_lock_irqsave(&consolelock, flags);
595 pi = &port_info[port];
596 /* If some other TTY is already connected here, reject the open */
597 if ((pi->tty) && (pi->tty != tty)) {
598 spin_unlock_irqrestore(&consolelock, flags);
599 printk(VIOCONS_KERN_WARN
600 "attempt to open device twice from different ttys\n");
601 return -EBUSY;
603 tty->driver_data = pi;
604 pi->tty = tty;
605 spin_unlock_irqrestore(&consolelock, flags);
607 return 0;
611 * TTY Close method
613 static void viotty_close(struct tty_struct *tty, struct file *filp)
615 unsigned long flags;
616 struct port_info *pi;
618 spin_lock_irqsave(&consolelock, flags);
619 pi = (struct port_info *)tty->driver_data;
621 if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_close")) {
622 spin_unlock_irqrestore(&consolelock, flags);
623 return;
625 if (tty->count == 1)
626 pi->tty = NULL;
627 spin_unlock_irqrestore(&consolelock, flags);
631 * TTY Write method
633 static int viotty_write(struct tty_struct *tty, const unsigned char *buf,
634 int count)
636 struct port_info *pi;
638 pi = get_port_data(tty);
639 if (pi == NULL) {
640 hvlog("\n\rviotty_write: no port data.");
641 return -ENODEV;
644 if (viochar_is_console(pi))
645 hvlogOutput(buf, count);
648 * If the path to this LP is closed, don't bother doing anything more.
649 * just dump the data on the floor and return count. For some reason
650 * some user level programs will attempt to probe available tty's and
651 * they'll attempt a viotty_write on an invalid port which maps to an
652 * invalid target lp. If this is the case then ignore the
653 * viotty_write call and, since the viopath isn't active to this
654 * partition, return count.
656 if (!viopath_isactive(pi->lp))
657 return count;
659 return internal_write(pi, buf, count);
663 * TTY put_char method
665 static void viotty_put_char(struct tty_struct *tty, unsigned char ch)
667 struct port_info *pi;
669 pi = get_port_data(tty);
670 if (pi == NULL)
671 return;
673 /* This will append '\r' as well if the char is '\n' */
674 if (viochar_is_console(pi))
675 hvlogOutput(&ch, 1);
677 if (viopath_isactive(pi->lp))
678 internal_write(pi, &ch, 1);
682 * TTY write_room method
684 static int viotty_write_room(struct tty_struct *tty)
686 int i;
687 int room = 0;
688 struct port_info *pi;
689 unsigned long flags;
691 spin_lock_irqsave(&consolelock, flags);
692 pi = (struct port_info *)tty->driver_data;
693 if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_write_room")) {
694 spin_unlock_irqrestore(&consolelock, flags);
695 return 0;
698 /* If no buffers are used, return the max size. */
699 if (pi->used == 0) {
700 spin_unlock_irqrestore(&consolelock, flags);
701 return VIOCHAR_MAX_DATA * VIOCHAR_NUM_BUF;
705 * We retain the spinlock because we want to get an accurate
706 * count and it can change on us between each operation if we
707 * don't hold the spinlock.
709 for (i = 0; ((i < VIOCHAR_NUM_BUF) && (room < VIOCHAR_MAX_DATA)); i++)
710 room += (VIOCHAR_MAX_DATA - pi->bufferBytes[i]);
711 spin_unlock_irqrestore(&consolelock, flags);
713 if (room > VIOCHAR_MAX_DATA)
714 room = VIOCHAR_MAX_DATA;
715 return room;
719 * TTY chars_in_buffer method
721 static int viotty_chars_in_buffer(struct tty_struct *tty)
723 return 0;
726 static int viotty_ioctl(struct tty_struct *tty, struct file *file,
727 unsigned int cmd, unsigned long arg)
729 switch (cmd) {
731 * the ioctls below read/set the flags usually shown in the leds
732 * don't use them - they will go away without warning
734 case KDGETLED:
735 case KDGKBLED:
736 return put_user(0, (char *)arg);
738 case KDSKBLED:
739 return 0;
742 return n_tty_ioctl(tty, file, cmd, arg);
746 * Handle an open charLpEvent. Could be either interrupt or ack
748 static void vioHandleOpenEvent(struct HvLpEvent *event)
750 unsigned long flags;
751 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
752 u8 port = cevent->virtual_device;
753 struct port_info *pi;
754 int reject = 0;
756 if (event->xFlags.xFunction == HvLpEvent_Function_Ack) {
757 if (port >= VTTY_PORTS)
758 return;
760 spin_lock_irqsave(&consolelock, flags);
761 /* Got the lock, don't cause console output */
763 pi = &port_info[port];
764 if (event->xRc == HvLpEvent_Rc_Good) {
765 pi->seq = pi->ack = 0;
767 * This line allows connections from the primary
768 * partition but once one is connected from the
769 * primary partition nothing short of a reboot
770 * of linux will allow access from the hosting
771 * partition again without a required iSeries fix.
773 pi->lp = event->xTargetLp;
776 spin_unlock_irqrestore(&consolelock, flags);
777 if (event->xRc != HvLpEvent_Rc_Good)
778 printk(VIOCONS_KERN_WARN
779 "handle_open_event: event->xRc == (%d).\n",
780 event->xRc);
782 if (event->xCorrelationToken != 0) {
783 atomic_t *aptr= (atomic_t *)event->xCorrelationToken;
784 atomic_set(aptr, 1);
785 } else
786 printk(VIOCONS_KERN_WARN
787 "weird...got open ack without atomic\n");
788 return;
791 /* This had better require an ack, otherwise complain */
792 if (event->xFlags.xAckInd != HvLpEvent_AckInd_DoAck) {
793 printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n");
794 return;
797 spin_lock_irqsave(&consolelock, flags);
798 /* Got the lock, don't cause console output */
800 /* Make sure this is a good virtual tty */
801 if (port >= VTTY_PORTS) {
802 event->xRc = HvLpEvent_Rc_SubtypeError;
803 cevent->subtype_result_code = viorc_openRejected;
805 * Flag state here since we can't printk while holding
806 * a spinlock.
808 reject = 1;
809 } else {
810 pi = &port_info[port];
811 if ((pi->lp != HvLpIndexInvalid) &&
812 (pi->lp != event->xSourceLp)) {
814 * If this is tty is already connected to a different
815 * partition, fail.
817 event->xRc = HvLpEvent_Rc_SubtypeError;
818 cevent->subtype_result_code = viorc_openRejected;
819 reject = 2;
820 } else {
821 pi->lp = event->xSourceLp;
822 event->xRc = HvLpEvent_Rc_Good;
823 cevent->subtype_result_code = viorc_good;
824 pi->seq = pi->ack = 0;
825 reject = 0;
829 spin_unlock_irqrestore(&consolelock, flags);
831 if (reject == 1)
832 printk(VIOCONS_KERN_WARN "open rejected: bad virtual tty.\n");
833 else if (reject == 2)
834 printk(VIOCONS_KERN_WARN
835 "open rejected: console in exclusive use by another partition.\n");
837 /* Return the acknowledgement */
838 HvCallEvent_ackLpEvent(event);
842 * Handle a close charLpEvent. This should ONLY be an Interrupt because the
843 * virtual console should never actually issue a close event to the hypervisor
844 * because the virtual console never goes away. A close event coming from the
845 * hypervisor simply means that there are no client consoles connected to the
846 * virtual console.
848 * Regardless of the number of connections masqueraded on the other side of
849 * the hypervisor ONLY ONE close event should be called to accompany the ONE
850 * open event that is called. The close event should ONLY be called when NO
851 * MORE connections (masqueraded or not) exist on the other side of the
852 * hypervisor.
854 static void vioHandleCloseEvent(struct HvLpEvent *event)
856 unsigned long flags;
857 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
858 u8 port = cevent->virtual_device;
860 if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
861 if (port >= VTTY_PORTS) {
862 printk(VIOCONS_KERN_WARN
863 "close message from invalid virtual device.\n");
864 return;
867 /* For closes, just mark the console partition invalid */
868 spin_lock_irqsave(&consolelock, flags);
869 /* Got the lock, don't cause console output */
871 if (port_info[port].lp == event->xSourceLp)
872 port_info[port].lp = HvLpIndexInvalid;
874 spin_unlock_irqrestore(&consolelock, flags);
875 printk(VIOCONS_KERN_INFO "close from %d\n", event->xSourceLp);
876 } else
877 printk(VIOCONS_KERN_WARN
878 "got unexpected close acknowlegement\n");
882 * Handle a config charLpEvent. Could be either interrupt or ack
884 static void vioHandleConfig(struct HvLpEvent *event)
886 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
888 HvCall_writeLogBuffer(cevent->data, cevent->len);
890 if (cevent->data[0] == 0x01)
891 printk(VIOCONS_KERN_INFO "window resized to %d: %d: %d: %d\n",
892 cevent->data[1], cevent->data[2],
893 cevent->data[3], cevent->data[4]);
894 else
895 printk(VIOCONS_KERN_WARN "unknown config event\n");
899 * Handle a data charLpEvent.
901 static void vioHandleData(struct HvLpEvent *event)
903 struct tty_struct *tty;
904 unsigned long flags;
905 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
906 struct port_info *pi;
907 int index;
908 u8 port = cevent->virtual_device;
910 if (port >= VTTY_PORTS) {
911 printk(VIOCONS_KERN_WARN "data on invalid virtual device %d\n",
912 port);
913 return;
917 * Hold the spinlock so that we don't take an interrupt that
918 * changes tty between the time we fetch the port_info
919 * pointer and the time we paranoia check.
921 spin_lock_irqsave(&consolelock, flags);
922 pi = &port_info[port];
925 * Change 05/01/2003 - Ryan Arnold: If a partition other than
926 * the current exclusive partition tries to send us data
927 * events then just drop them on the floor because we don't
928 * want his stinking data. He isn't authorized to receive
929 * data because he wasn't the first one to get the console,
930 * therefore he shouldn't be allowed to send data either.
931 * This will work without an iSeries fix.
933 if (pi->lp != event->xSourceLp) {
934 spin_unlock_irqrestore(&consolelock, flags);
935 return;
938 tty = pi->tty;
939 if (tty == NULL) {
940 spin_unlock_irqrestore(&consolelock, flags);
941 printk(VIOCONS_KERN_WARN "no tty for virtual device %d\n",
942 port);
943 return;
946 if (tty->magic != TTY_MAGIC) {
947 spin_unlock_irqrestore(&consolelock, flags);
948 printk(VIOCONS_KERN_WARN "tty bad magic\n");
949 return;
953 * Just to be paranoid, make sure the tty points back to this port
955 pi = (struct port_info *)tty->driver_data;
956 if (!pi || viotty_paranoia_check(pi, tty->name, "vioHandleData")) {
957 spin_unlock_irqrestore(&consolelock, flags);
958 return;
960 spin_unlock_irqrestore(&consolelock, flags);
963 * Change 07/21/2003 - Ryan Arnold: functionality added to
964 * support sysrq utilizing ^O as the sysrq key. The sysrq
965 * functionality will only work if built into the kernel and
966 * then only if sysrq is enabled through the proc filesystem.
968 for (index = 0; index < cevent->len; index++) {
969 #ifdef CONFIG_MAGIC_SYSRQ
970 if (sysrq_enabled) {
971 /* 0x0f is the ascii character for ^O */
972 if (cevent->data[index] == '\x0f') {
973 vio_sysrq_pressed = 1;
975 * continue because we don't want to add
976 * the sysrq key into the data string.
978 continue;
979 } else if (vio_sysrq_pressed) {
980 handle_sysrq(cevent->data[index], NULL, tty);
981 vio_sysrq_pressed = 0;
983 * continue because we don't want to add
984 * the sysrq sequence into the data string.
986 continue;
989 #endif
991 * The sysrq sequence isn't included in this check if
992 * sysrq is enabled and compiled into the kernel because
993 * the sequence will never get inserted into the buffer.
994 * Don't attempt to copy more data into the buffer than we
995 * have room for because it would fail without indication.
997 if ((tty->flip.count + 1) > TTY_FLIPBUF_SIZE) {
998 printk(VIOCONS_KERN_WARN "input buffer overflow!\n");
999 break;
1001 tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL);
1004 /* if cevent->len == 0 then no data was added to the buffer and flip.count == 0 */
1005 if (tty->flip.count)
1006 /* The next call resets flip.count when the data is flushed. */
1007 tty_flip_buffer_push(tty);
1011 * Handle an ack charLpEvent.
1013 static void vioHandleAck(struct HvLpEvent *event)
1015 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
1016 unsigned long flags;
1017 u8 port = cevent->virtual_device;
1019 if (port >= VTTY_PORTS) {
1020 printk(VIOCONS_KERN_WARN "data on invalid virtual device\n");
1021 return;
1024 spin_lock_irqsave(&consolelock, flags);
1025 port_info[port].ack = event->xCorrelationToken;
1026 spin_unlock_irqrestore(&consolelock, flags);
1028 if (port_info[port].used)
1029 send_buffers(&port_info[port]);
1033 * Handle charLpEvents and route to the appropriate routine
1035 static void vioHandleCharEvent(struct HvLpEvent *event)
1037 int charminor;
1039 if (event == NULL)
1040 return;
1042 charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
1043 switch (charminor) {
1044 case viocharopen:
1045 vioHandleOpenEvent(event);
1046 break;
1047 case viocharclose:
1048 vioHandleCloseEvent(event);
1049 break;
1050 case viochardata:
1051 vioHandleData(event);
1052 break;
1053 case viocharack:
1054 vioHandleAck(event);
1055 break;
1056 case viocharconfig:
1057 vioHandleConfig(event);
1058 break;
1059 default:
1060 if ((event->xFlags.xFunction == HvLpEvent_Function_Int) &&
1061 (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
1062 event->xRc = HvLpEvent_Rc_InvalidSubtype;
1063 HvCallEvent_ackLpEvent(event);
1069 * Send an open event
1071 static int send_open(HvLpIndex remoteLp, void *sem)
1073 return HvCallEvent_signalLpEventFast(remoteLp,
1074 HvLpEvent_Type_VirtualIo,
1075 viomajorsubtype_chario | viocharopen,
1076 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
1077 viopath_sourceinst(remoteLp),
1078 viopath_targetinst(remoteLp),
1079 (u64)(unsigned long)sem, VIOVERSION << 16,
1080 0, 0, 0, 0);
1083 static struct tty_operations serial_ops = {
1084 .open = viotty_open,
1085 .close = viotty_close,
1086 .write = viotty_write,
1087 .put_char = viotty_put_char,
1088 .write_room = viotty_write_room,
1089 .chars_in_buffer = viotty_chars_in_buffer,
1090 .ioctl = viotty_ioctl,
1093 static int __init viocons_init2(void)
1095 atomic_t wait_flag;
1096 int rc;
1098 /* +2 for fudge */
1099 rc = viopath_open(HvLpConfig_getPrimaryLpIndex(),
1100 viomajorsubtype_chario, VIOCHAR_WINDOW + 2);
1101 if (rc)
1102 printk(VIOCONS_KERN_WARN "error opening to primary %d\n", rc);
1104 if (viopath_hostLp == HvLpIndexInvalid)
1105 vio_set_hostlp();
1108 * And if the primary is not the same as the hosting LP, open to the
1109 * hosting lp
1111 if ((viopath_hostLp != HvLpIndexInvalid) &&
1112 (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) {
1113 printk(VIOCONS_KERN_INFO "open path to hosting (%d)\n",
1114 viopath_hostLp);
1115 rc = viopath_open(viopath_hostLp, viomajorsubtype_chario,
1116 VIOCHAR_WINDOW + 2); /* +2 for fudge */
1117 if (rc)
1118 printk(VIOCONS_KERN_WARN
1119 "error opening to partition %d: %d\n",
1120 viopath_hostLp, rc);
1123 if (vio_setHandler(viomajorsubtype_chario, vioHandleCharEvent) < 0)
1124 printk(VIOCONS_KERN_WARN
1125 "error seting handler for console events!\n");
1128 * First, try to open the console to the hosting lp.
1129 * Wait on a semaphore for the response.
1131 atomic_set(&wait_flag, 0);
1132 if ((viopath_isactive(viopath_hostLp)) &&
1133 (send_open(viopath_hostLp, (void *)&wait_flag) == 0)) {
1134 printk(VIOCONS_KERN_INFO "hosting partition %d\n",
1135 viopath_hostLp);
1136 while (atomic_read(&wait_flag) == 0)
1137 mb();
1138 atomic_set(&wait_flag, 0);
1142 * If we don't have an active console, try the primary
1144 if ((!viopath_isactive(port_info[0].lp)) &&
1145 (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) &&
1146 (send_open(HvLpConfig_getPrimaryLpIndex(), (void *)&wait_flag)
1147 == 0)) {
1148 printk(VIOCONS_KERN_INFO "opening console to primary partition\n");
1149 while (atomic_read(&wait_flag) == 0)
1150 mb();
1153 /* Initialize the tty_driver structure */
1154 viotty_driver = alloc_tty_driver(VTTY_PORTS);
1155 viotty_driver->owner = THIS_MODULE;
1156 viotty_driver->driver_name = "vioconsole";
1157 viotty_driver->devfs_name = "vcs/";
1158 viotty_driver->name = "tty";
1159 viotty_driver->name_base = 1;
1160 viotty_driver->major = TTY_MAJOR;
1161 viotty_driver->minor_start = 1;
1162 viotty_driver->type = TTY_DRIVER_TYPE_CONSOLE;
1163 viotty_driver->subtype = 1;
1164 viotty_driver->init_termios = tty_std_termios;
1165 viotty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
1166 tty_set_operations(viotty_driver, &serial_ops);
1168 if (tty_register_driver(viotty_driver)) {
1169 printk(VIOCONS_KERN_WARN "couldn't register console driver\n");
1170 put_tty_driver(viotty_driver);
1171 viotty_driver = NULL;
1174 unregister_console(&viocons_early);
1175 register_console(&viocons);
1177 return 0;
1180 static int __init viocons_init(void)
1182 int i;
1184 printk(VIOCONS_KERN_INFO "registering console\n");
1185 for (i = 0; i < VTTY_PORTS; i++) {
1186 port_info[i].lp = HvLpIndexInvalid;
1187 port_info[i].magic = VIOTTY_MAGIC;
1189 HvCall_setLogBufferFormatAndCodepage(HvCall_LogBuffer_ASCII, 437);
1190 register_console(&viocons_early);
1191 return 0;
1194 console_initcall(viocons_init);
1195 module_init(viocons_init2);