]> err.no Git - linux-2.6/blob - drivers/char/viocons.c
Merge git://git.infradead.org/battery-2.6
[linux-2.6] / drivers / char / viocons.c
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
62 static DEFINE_SPINLOCK(consolelock);
63 static DEFINE_SPINLOCK(consoleloglock);
64
65 static 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  */
73 static 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
97 static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp);
98
99 static struct tty_driver *viotty_driver;
100
101 static 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
117 static 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  */
147 static 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  */
172 static 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  */
251 static 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  */
354 static 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);
413 out:
414         vio_free_event_buffer(viomajorsubtype_chario, viochar);
415         spin_unlock_irqrestore(&consolelock, flags);
416         return len - bleft;
417 }
418
419 static 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  */
444 static 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  */
464 static 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  */
472 static 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  */
521 static 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  */
530 static struct console viocons_early = {
531         .name = "viocons",
532         .write = viocons_write_early,
533         .flags = CON_PRINTBUFFER,
534         .index = -1,
535 };
536
537 static 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  */
548 static 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  */
579 static 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  */
599 static 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  */
631 static int 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 0;
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         return 1;
646 }
647
648 /*
649  * TTY write_room method
650  */
651 static int viotty_write_room(struct tty_struct *tty)
652 {
653         int i;
654         int room = 0;
655         struct port_info *pi;
656         unsigned long flags;
657
658         spin_lock_irqsave(&consolelock, flags);
659         pi = (struct port_info *)tty->driver_data;
660         if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_write_room")) {
661                 spin_unlock_irqrestore(&consolelock, flags);
662                 return 0;
663         }
664
665         /* If no buffers are used, return the max size. */
666         if (pi->used == 0) {
667                 spin_unlock_irqrestore(&consolelock, flags);
668                 return VIOCHAR_MAX_DATA * VIOCHAR_NUM_BUF;
669         }
670
671         /*
672          * We retain the spinlock because we want to get an accurate
673          * count and it can change on us between each operation if we
674          * don't hold the spinlock.
675          */
676         for (i = 0; ((i < VIOCHAR_NUM_BUF) && (room < VIOCHAR_MAX_DATA)); i++)
677                 room += (VIOCHAR_MAX_DATA - pi->bufferBytes[i]);
678         spin_unlock_irqrestore(&consolelock, flags);
679
680         if (room > VIOCHAR_MAX_DATA)
681                 room = VIOCHAR_MAX_DATA;
682         return room;
683 }
684
685 /*
686  * TTY chars_in_buffer method
687  */
688 static int viotty_chars_in_buffer(struct tty_struct *tty)
689 {
690         return 0;
691 }
692
693 static int viotty_ioctl(struct tty_struct *tty, struct file *file,
694                         unsigned int cmd, unsigned long arg)
695 {
696         switch (cmd) {
697         /*
698          * the ioctls below read/set the flags usually shown in the leds
699          * don't use them - they will go away without warning
700          */
701         case KDGETLED:
702         case KDGKBLED:
703                 return put_user(0, (char *)arg);
704
705         case KDSKBLED:
706                 return 0;
707         }
708         /* FIXME: WTF is this being called for ??? */
709         lock_kernel();
710         ret =  n_tty_ioctl(tty, file, cmd, arg);
711         unlock_kernel();
712         return ret;
713 }
714
715 /*
716  * Handle an open charLpEvent.  Could be either interrupt or ack
717  */
718 static void vioHandleOpenEvent(struct HvLpEvent *event)
719 {
720         unsigned long flags;
721         struct viocharlpevent *cevent = (struct viocharlpevent *)event;
722         u8 port = cevent->virtual_device;
723         struct port_info *pi;
724         int reject = 0;
725
726         if (hvlpevent_is_ack(event)) {
727                 if (port >= VTTY_PORTS)
728                         return;
729
730                 spin_lock_irqsave(&consolelock, flags);
731                 /* Got the lock, don't cause console output */
732
733                 pi = &port_info[port];
734                 if (event->xRc == HvLpEvent_Rc_Good) {
735                         pi->seq = pi->ack = 0;
736                         /*
737                          * This line allows connections from the primary
738                          * partition but once one is connected from the
739                          * primary partition nothing short of a reboot
740                          * of linux will allow access from the hosting
741                          * partition again without a required iSeries fix.
742                          */
743                         pi->lp = event->xTargetLp;
744                 }
745
746                 spin_unlock_irqrestore(&consolelock, flags);
747                 if (event->xRc != HvLpEvent_Rc_Good)
748                         printk(VIOCONS_KERN_WARN
749                                "handle_open_event: event->xRc == (%d).\n",
750                                event->xRc);
751
752                 if (event->xCorrelationToken != 0) {
753                         atomic_t *aptr= (atomic_t *)event->xCorrelationToken;
754                         atomic_set(aptr, 1);
755                 } else
756                         printk(VIOCONS_KERN_WARN
757                                "weird...got open ack without atomic\n");
758                 return;
759         }
760
761         /* This had better require an ack, otherwise complain */
762         if (!hvlpevent_need_ack(event)) {
763                 printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n");
764                 return;
765         }
766
767         spin_lock_irqsave(&consolelock, flags);
768         /* Got the lock, don't cause console output */
769
770         /* Make sure this is a good virtual tty */
771         if (port >= VTTY_PORTS) {
772                 event->xRc = HvLpEvent_Rc_SubtypeError;
773                 cevent->subtype_result_code = viorc_openRejected;
774                 /*
775                  * Flag state here since we can't printk while holding
776                  * a spinlock.
777                  */
778                 reject = 1;
779         } else {
780                 pi = &port_info[port];
781                 if ((pi->lp != HvLpIndexInvalid) &&
782                                 (pi->lp != event->xSourceLp)) {
783                         /*
784                          * If this is tty is already connected to a different
785                          * partition, fail.
786                          */
787                         event->xRc = HvLpEvent_Rc_SubtypeError;
788                         cevent->subtype_result_code = viorc_openRejected;
789                         reject = 2;
790                 } else {
791                         pi->lp = event->xSourceLp;
792                         event->xRc = HvLpEvent_Rc_Good;
793                         cevent->subtype_result_code = viorc_good;
794                         pi->seq = pi->ack = 0;
795                         reject = 0;
796                 }
797         }
798
799         spin_unlock_irqrestore(&consolelock, flags);
800
801         if (reject == 1)
802                 printk(VIOCONS_KERN_WARN "open rejected: bad virtual tty.\n");
803         else if (reject == 2)
804                 printk(VIOCONS_KERN_WARN
805                         "open rejected: console in exclusive use by another partition.\n");
806
807         /* Return the acknowledgement */
808         HvCallEvent_ackLpEvent(event);
809 }
810
811 /*
812  * Handle a close charLpEvent.  This should ONLY be an Interrupt because the
813  * virtual console should never actually issue a close event to the hypervisor
814  * because the virtual console never goes away.  A close event coming from the
815  * hypervisor simply means that there are no client consoles connected to the
816  * virtual console.
817  *
818  * Regardless of the number of connections masqueraded on the other side of
819  * the hypervisor ONLY ONE close event should be called to accompany the ONE
820  * open event that is called.  The close event should ONLY be called when NO
821  * MORE connections (masqueraded or not) exist on the other side of the
822  * hypervisor.
823  */
824 static void vioHandleCloseEvent(struct HvLpEvent *event)
825 {
826         unsigned long flags;
827         struct viocharlpevent *cevent = (struct viocharlpevent *)event;
828         u8 port = cevent->virtual_device;
829
830         if (hvlpevent_is_int(event)) {
831                 if (port >= VTTY_PORTS) {
832                         printk(VIOCONS_KERN_WARN
833                                         "close message from invalid virtual device.\n");
834                         return;
835                 }
836
837                 /* For closes, just mark the console partition invalid */
838                 spin_lock_irqsave(&consolelock, flags);
839                 /* Got the lock, don't cause console output */
840
841                 if (port_info[port].lp == event->xSourceLp)
842                         port_info[port].lp = HvLpIndexInvalid;
843
844                 spin_unlock_irqrestore(&consolelock, flags);
845                 printk(VIOCONS_KERN_INFO "close from %d\n", event->xSourceLp);
846         } else
847                 printk(VIOCONS_KERN_WARN
848                                 "got unexpected close acknowlegement\n");
849 }
850
851 /*
852  * Handle a config charLpEvent.  Could be either interrupt or ack
853  */
854 static void vioHandleConfig(struct HvLpEvent *event)
855 {
856         struct viocharlpevent *cevent = (struct viocharlpevent *)event;
857
858         HvCall_writeLogBuffer(cevent->data, cevent->len);
859
860         if (cevent->data[0] == 0x01)
861                 printk(VIOCONS_KERN_INFO "window resized to %d: %d: %d: %d\n",
862                        cevent->data[1], cevent->data[2],
863                        cevent->data[3], cevent->data[4]);
864         else
865                 printk(VIOCONS_KERN_WARN "unknown config event\n");
866 }
867
868 /*
869  * Handle a data charLpEvent. 
870  */
871 static void vioHandleData(struct HvLpEvent *event)
872 {
873         struct tty_struct *tty;
874         unsigned long flags;
875         struct viocharlpevent *cevent = (struct viocharlpevent *)event;
876         struct port_info *pi;
877         int index;
878         int num_pushed;
879         u8 port = cevent->virtual_device;
880
881         if (port >= VTTY_PORTS) {
882                 printk(VIOCONS_KERN_WARN "data on invalid virtual device %d\n",
883                                 port);
884                 return;
885         }
886
887         /*
888          * Hold the spinlock so that we don't take an interrupt that
889          * changes tty between the time we fetch the port_info
890          * pointer and the time we paranoia check.
891          */
892         spin_lock_irqsave(&consolelock, flags);
893         pi = &port_info[port];
894
895         /*
896          * Change 05/01/2003 - Ryan Arnold: If a partition other than
897          * the current exclusive partition tries to send us data
898          * events then just drop them on the floor because we don't
899          * want his stinking data.  He isn't authorized to receive
900          * data because he wasn't the first one to get the console,
901          * therefore he shouldn't be allowed to send data either.
902          * This will work without an iSeries fix.
903          */
904         if (pi->lp != event->xSourceLp) {
905                 spin_unlock_irqrestore(&consolelock, flags);
906                 return;
907         }
908
909         tty = pi->tty;
910         if (tty == NULL) {
911                 spin_unlock_irqrestore(&consolelock, flags);
912                 printk(VIOCONS_KERN_WARN "no tty for virtual device %d\n",
913                                 port);
914                 return;
915         }
916
917         if (tty->magic != TTY_MAGIC) {
918                 spin_unlock_irqrestore(&consolelock, flags);
919                 printk(VIOCONS_KERN_WARN "tty bad magic\n");
920                 return;
921         }
922
923         /*
924          * Just to be paranoid, make sure the tty points back to this port
925          */
926         pi = (struct port_info *)tty->driver_data;
927         if (!pi || viotty_paranoia_check(pi, tty->name, "vioHandleData")) {
928                 spin_unlock_irqrestore(&consolelock, flags);
929                 return;
930         }
931         spin_unlock_irqrestore(&consolelock, flags);
932
933         /*
934          * Change 07/21/2003 - Ryan Arnold: functionality added to
935          * support sysrq utilizing ^O as the sysrq key.  The sysrq
936          * functionality will only work if built into the kernel and
937          * then only if sysrq is enabled through the proc filesystem.
938          */
939         num_pushed = 0;
940         for (index = 0; index < cevent->len; index++) {
941                 /*
942                  * Will be optimized away if !CONFIG_MAGIC_SYSRQ:
943                  */
944                 if (sysrq_on()) {
945                         /* 0x0f is the ascii character for ^O */
946                         if (cevent->data[index] == '\x0f') {
947                                 vio_sysrq_pressed = 1;
948                                 /*
949                                  * continue because we don't want to add
950                                  * the sysrq key into the data string.
951                                  */
952                                 continue;
953                         } else if (vio_sysrq_pressed) {
954                                 handle_sysrq(cevent->data[index], tty);
955                                 vio_sysrq_pressed = 0;
956                                 /*
957                                  * continue because we don't want to add
958                                  * the sysrq sequence into the data string.
959                                  */
960                                 continue;
961                         }
962                 }
963                 /*
964                  * The sysrq sequence isn't included in this check if
965                  * sysrq is enabled and compiled into the kernel because
966                  * the sequence will never get inserted into the buffer.
967                  * Don't attempt to copy more data into the buffer than we
968                  * have room for because it would fail without indication.
969                  */
970                 if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) {
971                         printk(VIOCONS_KERN_WARN "input buffer overflow!\n");
972                         break;
973                 }
974                 num_pushed++;
975         }
976
977         if (num_pushed)
978                 tty_flip_buffer_push(tty);
979 }
980
981 /*
982  * Handle an ack charLpEvent. 
983  */
984 static void vioHandleAck(struct HvLpEvent *event)
985 {
986         struct viocharlpevent *cevent = (struct viocharlpevent *)event;
987         unsigned long flags;
988         u8 port = cevent->virtual_device;
989
990         if (port >= VTTY_PORTS) {
991                 printk(VIOCONS_KERN_WARN "data on invalid virtual device\n");
992                 return;
993         }
994
995         spin_lock_irqsave(&consolelock, flags);
996         port_info[port].ack = event->xCorrelationToken;
997         spin_unlock_irqrestore(&consolelock, flags);
998
999         if (port_info[port].used)
1000                 send_buffers(&port_info[port]);
1001 }
1002
1003 /*
1004  * Handle charLpEvents and route to the appropriate routine
1005  */
1006 static void vioHandleCharEvent(struct HvLpEvent *event)
1007 {
1008         int charminor;
1009
1010         if (event == NULL)
1011                 return;
1012
1013         charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
1014         switch (charminor) {
1015         case viocharopen:
1016                 vioHandleOpenEvent(event);
1017                 break;
1018         case viocharclose:
1019                 vioHandleCloseEvent(event);
1020                 break;
1021         case viochardata:
1022                 vioHandleData(event);
1023                 break;
1024         case viocharack:
1025                 vioHandleAck(event);
1026                 break;
1027         case viocharconfig:
1028                 vioHandleConfig(event);
1029                 break;
1030         default:
1031                 if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
1032                         event->xRc = HvLpEvent_Rc_InvalidSubtype;
1033                         HvCallEvent_ackLpEvent(event);
1034                 }
1035         }
1036 }
1037
1038 /*
1039  * Send an open event
1040  */
1041 static int send_open(HvLpIndex remoteLp, void *sem)
1042 {
1043         return HvCallEvent_signalLpEventFast(remoteLp,
1044                         HvLpEvent_Type_VirtualIo,
1045                         viomajorsubtype_chario | viocharopen,
1046                         HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
1047                         viopath_sourceinst(remoteLp),
1048                         viopath_targetinst(remoteLp),
1049                         (u64)(unsigned long)sem, VIOVERSION << 16,
1050                         0, 0, 0, 0);
1051 }
1052
1053 static const struct tty_operations serial_ops = {
1054         .open = viotty_open,
1055         .close = viotty_close,
1056         .write = viotty_write,
1057         .put_char = viotty_put_char,
1058         .write_room = viotty_write_room,
1059         .chars_in_buffer = viotty_chars_in_buffer,
1060         .ioctl = viotty_ioctl,
1061 };
1062
1063 static int __init viocons_init2(void)
1064 {
1065         atomic_t wait_flag;
1066         int rc;
1067
1068         if (!firmware_has_feature(FW_FEATURE_ISERIES))
1069                 return -ENODEV;
1070
1071         /* +2 for fudge */
1072         rc = viopath_open(HvLpConfig_getPrimaryLpIndex(),
1073                         viomajorsubtype_chario, VIOCHAR_WINDOW + 2);
1074         if (rc)
1075                 printk(VIOCONS_KERN_WARN "error opening to primary %d\n", rc);
1076
1077         if (viopath_hostLp == HvLpIndexInvalid)
1078                 vio_set_hostlp();
1079
1080         /*
1081          * And if the primary is not the same as the hosting LP, open to the 
1082          * hosting lp
1083          */
1084         if ((viopath_hostLp != HvLpIndexInvalid) &&
1085             (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) {
1086                 printk(VIOCONS_KERN_INFO "open path to hosting (%d)\n",
1087                                 viopath_hostLp);
1088                 rc = viopath_open(viopath_hostLp, viomajorsubtype_chario,
1089                                 VIOCHAR_WINDOW + 2);    /* +2 for fudge */
1090                 if (rc)
1091                         printk(VIOCONS_KERN_WARN
1092                                 "error opening to partition %d: %d\n",
1093                                 viopath_hostLp, rc);
1094         }
1095
1096         if (vio_setHandler(viomajorsubtype_chario, vioHandleCharEvent) < 0)
1097                 printk(VIOCONS_KERN_WARN
1098                                 "error seting handler for console events!\n");
1099
1100         /*
1101          * First, try to open the console to the hosting lp.
1102          * Wait on a semaphore for the response.
1103          */
1104         atomic_set(&wait_flag, 0);
1105         if ((viopath_isactive(viopath_hostLp)) &&
1106             (send_open(viopath_hostLp, (void *)&wait_flag) == 0)) {
1107                 printk(VIOCONS_KERN_INFO "hosting partition %d\n",
1108                         viopath_hostLp);
1109                 while (atomic_read(&wait_flag) == 0)
1110                         mb();
1111                 atomic_set(&wait_flag, 0);
1112         }
1113
1114         /*
1115          * If we don't have an active console, try the primary
1116          */
1117         if ((!viopath_isactive(port_info[0].lp)) &&
1118             (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) &&
1119             (send_open(HvLpConfig_getPrimaryLpIndex(), (void *)&wait_flag)
1120              == 0)) {
1121                 printk(VIOCONS_KERN_INFO "opening console to primary partition\n");
1122                 while (atomic_read(&wait_flag) == 0)
1123                         mb();
1124         }
1125
1126         /* Initialize the tty_driver structure */
1127         viotty_driver = alloc_tty_driver(VTTY_PORTS);
1128         viotty_driver->owner = THIS_MODULE;
1129         viotty_driver->driver_name = "vioconsole";
1130         viotty_driver->name = "tty";
1131         viotty_driver->name_base = 1;
1132         viotty_driver->major = TTY_MAJOR;
1133         viotty_driver->minor_start = 1;
1134         viotty_driver->type = TTY_DRIVER_TYPE_CONSOLE;
1135         viotty_driver->subtype = 1;
1136         viotty_driver->init_termios = tty_std_termios;
1137         viotty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
1138         tty_set_operations(viotty_driver, &serial_ops);
1139
1140         if (tty_register_driver(viotty_driver)) {
1141                 printk(VIOCONS_KERN_WARN "couldn't register console driver\n");
1142                 put_tty_driver(viotty_driver);
1143                 viotty_driver = NULL;
1144         }
1145
1146         unregister_console(&viocons_early);
1147         register_console(&viocons);
1148
1149         return 0;
1150 }
1151
1152 static int __init viocons_init(void)
1153 {
1154         int i;
1155
1156         if (!firmware_has_feature(FW_FEATURE_ISERIES))
1157                 return -ENODEV;
1158
1159         printk(VIOCONS_KERN_INFO "registering console\n");
1160         for (i = 0; i < VTTY_PORTS; i++) {
1161                 port_info[i].lp = HvLpIndexInvalid;
1162                 port_info[i].magic = VIOTTY_MAGIC;
1163         }
1164         HvCall_setLogBufferFormatAndCodepage(HvCall_LogBuffer_ASCII, 437);
1165         add_preferred_console("viocons", 0, NULL);
1166         register_console(&viocons_early);
1167         return 0;
1168 }
1169
1170 console_initcall(viocons_init);
1171 module_init(viocons_init2);