Commit 3bb4c3e8 authored by Ryan S. Arnold's avatar Ryan S. Arnold Committed by Linus Torvalds

[PATCH] ppc64: HVCS driver

* include/asm-ppc64/hvcserver.h

  New file added to wrap ppc64 architecture specific firmware calls for
  use by HVCS.  This file provides a struct hvcs_partner_info definition,
  headers for partner info gathering and vterm connection and termination
  interfaces.

* arch/ppc64/kernel/Makefile

  Added build directive for hvcserver.o when HVCS is configured.

* arch/ppc64/kernel/hvconsole.c

  Exported hvc_put_chars() and hvc_get_chars() for use by HVCS.

* arch/ppc64/kernel/hvcserver.c

  Body of hvcserver module which accompanies the hvcs module and provides
  ppc64 architecture firmware calls for use by HVCS.  This file provides
  function bodies for partner info gathering and vterm connection and
  termination interfaces.

* drivers/char/Kconfig

  Added CONFIG_HVCS option for both built-in version and module version
  of hvcs.

* drivers/char/Makefile

  Added build directive for hvcs.o when CONFIG_HVCS is configured.

* drivers/char/hvcs.c

  This is the device driver for the IBM Hypervisor Virtual Console
  Server, "hvcs".  The IBM hvcs provides a tty driver interface to allow
  Linux user space applications access to the system consoles of logically
  partitioned operating systems, e.g.  Linux, running on the same
  partitioned Power5 ppc64 system.  Physical hardware consoles per
  partition are not practical on this hardware so system consoles are
  accessed by this driver using inter-partition firmware interfaces to
  virtual terminal devices.

* Documentation/powerpc/hvcs.txt

  HVCS installation and usage documentation.

Thanks everyone for all the help with this driver [Andrew Morton, Paul
Mackerras, Ben Herrenschmidt, Dave Hansen, Paul Mackerras, Dave Boutcher,
Hollis Blanchard, Santiago Leon, Brian King, Randy Dunlap].
Signed-off-by: default avatarRyan S. Arnold <rsa@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4928be8a
This diff is collapsed.
...@@ -46,6 +46,7 @@ obj-$(CONFIG_VIOPATH) += viopath.o ...@@ -46,6 +46,7 @@ obj-$(CONFIG_VIOPATH) += viopath.o
obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_LPARCFG) += lparcfg.o
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \
pmac_time.o pmac_nvram.o pmac_low_i2c.o \ pmac_time.o pmac_nvram.o pmac_low_i2c.o \
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <asm/hvcall.h> #include <asm/hvcall.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/hvconsole.h> #include <asm/hvconsole.h>
...@@ -50,6 +51,8 @@ int hvc_get_chars(int index, char *buf, int count) ...@@ -50,6 +51,8 @@ int hvc_get_chars(int index, char *buf, int count)
return 0; return 0;
} }
EXPORT_SYMBOL(hvc_get_chars);
int hvc_put_chars(int index, const char *buf, int count) int hvc_put_chars(int index, const char *buf, int count)
{ {
unsigned long *lbuf = (unsigned long *) buf; unsigned long *lbuf = (unsigned long *) buf;
...@@ -64,6 +67,8 @@ int hvc_put_chars(int index, const char *buf, int count) ...@@ -64,6 +67,8 @@ int hvc_put_chars(int index, const char *buf, int count)
return -1; return -1;
} }
EXPORT_SYMBOL(hvc_put_chars);
/* return the number of client vterms present */ /* return the number of client vterms present */
/* XXX this requires an interface change to handle multiple discontiguous /* XXX this requires an interface change to handle multiple discontiguous
* vterms */ * vterms */
......
/*
* hvcserver.c
* Copyright (C) 2004 Ryan S Arnold, IBM Corporation
*
* PPC64 virtual I/O console server support.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <asm/hvcall.h>
#include <asm/hvcserver.h>
#include <asm/io.h>
#define HVCS_ARCH_VERSION "1.0.0"
MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");
MODULE_DESCRIPTION("IBM hvcs ppc64 API");
MODULE_LICENSE("GPL");
MODULE_VERSION(HVCS_ARCH_VERSION);
/*
* Convert arch specific return codes into relevant errnos. The hvcs
* functions aren't performance sensitive, so this conversion isn't an
* issue.
*/
int hvcs_convert(long to_convert)
{
switch (to_convert) {
case H_Success:
return 0;
case H_Parameter:
return -EINVAL;
case H_Hardware:
return -EIO;
case H_Busy:
case H_LongBusyOrder1msec:
case H_LongBusyOrder10msec:
case H_LongBusyOrder100msec:
case H_LongBusyOrder1sec:
case H_LongBusyOrder10sec:
case H_LongBusyOrder100sec:
return -EBUSY;
case H_Function: /* fall through */
default:
return -EPERM;
}
}
int hvcs_free_partner_info(struct list_head *head)
{
struct hvcs_partner_info *pi;
struct list_head *element;
if (!head) {
return -EINVAL;
}
while (!list_empty(head)) {
element = head->next;
pi = list_entry(element, struct hvcs_partner_info, node);
list_del(element);
kfree(pi);
}
return 0;
}
EXPORT_SYMBOL(hvcs_free_partner_info);
/* Helper function for hvcs_get_partner_info */
int hvcs_next_partner(unsigned int unit_address,
unsigned long last_p_partition_ID,
unsigned long last_p_unit_address, unsigned long *pi_buff)
{
long retval;
retval = plpar_hcall_norets(H_VTERM_PARTNER_INFO, unit_address,
last_p_partition_ID,
last_p_unit_address, virt_to_phys(pi_buff));
return hvcs_convert(retval);
}
/*
* The unit_address parameter is the unit address of the vty-server vdevice
* in whose partner information the caller is interested. This function
* uses a pointer to a list_head instance in which to store the partner info.
* This function returns non-zero on success, or if there is no partner info.
*
* Invocation of this function should always be followed by an invocation of
* hvcs_free_partner_info() using a pointer to the SAME list head instance
* that was used to store the partner_info list.
*/
int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head,
unsigned long *pi_buff)
{
/*
* This is a page sized buffer to be passed to hvcall per invocation.
* NOTE: the first long returned is unit_address. The second long
* returned is the partition ID and starting with pi_buff[2] are
* HVCS_CLC_LENGTH characters, which are diff size than the unsigned
* long, hence the casting mumbojumbo you see later.
*/
unsigned long last_p_partition_ID;
unsigned long last_p_unit_address;
struct hvcs_partner_info *next_partner_info = NULL;
int more = 1;
int retval;
memset(pi_buff, 0x00, PAGE_SIZE);
/* invalid parameters */
if (!head)
return -EINVAL;
last_p_partition_ID = last_p_unit_address = ~0UL;
INIT_LIST_HEAD(head);
if (!pi_buff)
return -ENOMEM;
do {
retval = hvcs_next_partner(unit_address, last_p_partition_ID,
last_p_unit_address, pi_buff);
if (retval) {
/*
* Don't indicate that we've failed if we have
* any list elements.
*/
if (!list_empty(head))
return 0;
return retval;
}
last_p_partition_ID = pi_buff[0];
last_p_unit_address = pi_buff[1];
/* This indicates that there are no further partners */
if (last_p_partition_ID == ~0UL
&& last_p_unit_address == ~0UL)
break;
/* This is a very small struct and will be freed soon in
* hvcs_free_partner_info(). */
next_partner_info = kmalloc(sizeof(struct hvcs_partner_info),
GFP_ATOMIC);
if (!next_partner_info) {
printk(KERN_WARNING "HVCONSOLE: kmalloc() failed to"
" allocate partner info struct.\n");
hvcs_free_partner_info(head);
return -ENOMEM;
}
next_partner_info->unit_address
= (unsigned int)last_p_unit_address;
next_partner_info->partition_ID
= (unsigned int)last_p_partition_ID;
/* copy the Null-term char too */
strncpy(&next_partner_info->location_code[0],
(char *)&pi_buff[2],
strlen((char *)&pi_buff[2]) + 1);
list_add_tail(&(next_partner_info->node), head);
next_partner_info = NULL;
} while (more);
return 0;
}
EXPORT_SYMBOL(hvcs_get_partner_info);
/*
* If this function is called once and -EINVAL is returned it may
* indicate that the partner info needs to be refreshed for the
* target unit address at which point the caller must invoke
* hvcs_get_partner_info() and then call this function again. If,
* for a second time, -EINVAL is returned then it indicates that
* there is probably already a partner connection registered to a
* different vty-server@ vdevice. It is also possible that a second
* -EINVAL may indicate that one of the parms is not valid, for
* instance if the link was removed between the vty-server@ vdevice
* and the vty@ vdevice that you are trying to open. Don't shoot the
* messenger. Firmware implemented it this way.
*/
int hvcs_register_connection( unsigned int unit_address,
unsigned int p_partition_ID, unsigned int p_unit_address)
{
long retval;
retval = plpar_hcall_norets(H_REGISTER_VTERM, unit_address,
p_partition_ID, p_unit_address);
return hvcs_convert(retval);
}
EXPORT_SYMBOL(hvcs_register_connection);
/*
* If -EBUSY is returned continue to call this function
* until 0 is returned.
*/
int hvcs_free_connection(unsigned int unit_address)
{
long retval;
retval = plpar_hcall_norets(H_FREE_VTERM, unit_address);
return hvcs_convert(retval);
}
EXPORT_SYMBOL(hvcs_free_connection);
...@@ -570,6 +570,23 @@ config HVC_CONSOLE ...@@ -570,6 +570,23 @@ config HVC_CONSOLE
console. This driver allows each pSeries partition to have a console console. This driver allows each pSeries partition to have a console
which is accessed via the HMC. which is accessed via the HMC.
config HVCS
tristate "IBM Hypervisor Virtual Console Server support"
depends on PPC_PSERIES
help
Partitionable IBM Power5 ppc64 machines allow hosting of
firmware virtual consoles from one Linux partition by
another Linux partition. This driver allows console data
from Linux partitions to be accessed through TTY device
interfaces in the device tree of a Linux partition running
this driver.
To compile this driver as a module, choose M here: the
module will be called hvcs.ko. Additionally, this module
will depend on arch specific APIs exported from hvcserver.ko
which will also be compiled when this driver is built as a
module.
config QIC02_TAPE config QIC02_TAPE
tristate "QIC-02 tape support" tristate "QIC-02 tape support"
help help
......
...@@ -43,6 +43,7 @@ obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o ...@@ -43,6 +43,7 @@ obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOCONS) += viocons.o
obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_VIOTAPE) += viotape.o
obj-$(CONFIG_HVCS) += hvcs.o
obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_PRINTER) += lp.o
obj-$(CONFIG_TIPAR) += tipar.o obj-$(CONFIG_TIPAR) += tipar.o
......
This diff is collapsed.
/*
* hvcserver.h
* Copyright (C) 2004 Ryan S Arnold, IBM Corporation
*
* PPC64 virtual I/O console server support.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _PPC64_HVCSERVER_H
#define _PPC64_HVCSERVER_H
#include <linux/list.h>
/* Converged Location Code length */
#define HVCS_CLC_LENGTH 79
struct hvcs_partner_info {
struct list_head node;
unsigned int unit_address;
unsigned int partition_ID;
char location_code[HVCS_CLC_LENGTH + 1]; /* CLC + 1 null-term char */
};
extern int hvcs_free_partner_info(struct list_head *head);
extern int hvcs_get_partner_info(unsigned int unit_address,
struct list_head *head, unsigned long *pi_buff);
extern int hvcs_register_connection(unsigned int unit_address,
unsigned int p_partition_ID, unsigned int p_unit_address);
extern int hvcs_free_connection(unsigned int unit_address);
#endif /* _PPC64_HVCSERVER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment