162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * hvconsole.c
462306a36Sopenharmony_ci * Copyright (C) 2004 Hollis Blanchard, IBM Corporation
562306a36Sopenharmony_ci * Copyright (C) 2004 IBM Corporation
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Additional Author(s):
862306a36Sopenharmony_ci *  Ryan S. Arnold <rsa@us.ibm.com>
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * LPAR console support.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/kernel.h>
1462306a36Sopenharmony_ci#include <linux/export.h>
1562306a36Sopenharmony_ci#include <linux/errno.h>
1662306a36Sopenharmony_ci#include <asm/hvcall.h>
1762306a36Sopenharmony_ci#include <asm/hvconsole.h>
1862306a36Sopenharmony_ci#include <asm/plpar_wrappers.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/**
2162306a36Sopenharmony_ci * hvc_get_chars - retrieve characters from firmware for denoted vterm adapter
2262306a36Sopenharmony_ci * @vtermno: The vtermno or unit_address of the adapter from which to fetch the
2362306a36Sopenharmony_ci *	data.
2462306a36Sopenharmony_ci * @buf: The character buffer into which to put the character data fetched from
2562306a36Sopenharmony_ci *	firmware.
2662306a36Sopenharmony_ci * @count: not used?
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_ciint hvc_get_chars(uint32_t vtermno, char *buf, int count)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	long ret;
3162306a36Sopenharmony_ci	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
3262306a36Sopenharmony_ci	unsigned long *lbuf = (unsigned long *)buf;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	ret = plpar_hcall(H_GET_TERM_CHAR, retbuf, vtermno);
3562306a36Sopenharmony_ci	lbuf[0] = be64_to_cpu(retbuf[1]);
3662306a36Sopenharmony_ci	lbuf[1] = be64_to_cpu(retbuf[2]);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (ret == H_SUCCESS)
3962306a36Sopenharmony_ci		return retbuf[0];
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	return 0;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ciEXPORT_SYMBOL(hvc_get_chars);
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/**
4862306a36Sopenharmony_ci * hvc_put_chars: send characters to firmware for denoted vterm adapter
4962306a36Sopenharmony_ci * @vtermno: The vtermno or unit_address of the adapter from which the data
5062306a36Sopenharmony_ci *	originated.
5162306a36Sopenharmony_ci * @buf: The character buffer that contains the character data to send to
5262306a36Sopenharmony_ci *	firmware. Must be at least 16 bytes, even if count is less than 16.
5362306a36Sopenharmony_ci * @count: Send this number of characters.
5462306a36Sopenharmony_ci */
5562306a36Sopenharmony_ciint hvc_put_chars(uint32_t vtermno, const char *buf, int count)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	unsigned long *lbuf = (unsigned long *) buf;
5862306a36Sopenharmony_ci	long ret;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	/* hcall will ret H_PARAMETER if 'count' exceeds firmware max.*/
6262306a36Sopenharmony_ci	if (count > MAX_VIO_PUT_CHARS)
6362306a36Sopenharmony_ci		count = MAX_VIO_PUT_CHARS;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count,
6662306a36Sopenharmony_ci				 cpu_to_be64(lbuf[0]),
6762306a36Sopenharmony_ci				 cpu_to_be64(lbuf[1]));
6862306a36Sopenharmony_ci	if (ret == H_SUCCESS)
6962306a36Sopenharmony_ci		return count;
7062306a36Sopenharmony_ci	if (ret == H_BUSY)
7162306a36Sopenharmony_ci		return -EAGAIN;
7262306a36Sopenharmony_ci	return -EIO;
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ciEXPORT_SYMBOL(hvc_put_chars);
76