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