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