]> err.no Git - linux-2.6/blob - drivers/char/viocons.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[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 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  */
650 static 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  */
687 static int viotty_chars_in_buffer(struct tty_struct *tty)
688 {
689         return 0;
690 }
691
692 static 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  */
714 static 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  */
820 static 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  */
850 static 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  */
867 static 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  */
980 static 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  */
1002 static 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  */
1037 static 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
1049 static 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
1059 static 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
1148 static 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
1166 console_initcall(viocons_init);
1167 module_init(viocons_init2);