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