13cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou/* 23cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * Beat hypervisor console driver 33cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * 43cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * (C) Copyright 2006 TOSHIBA CORPORATION 53cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * 63cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * This code is based on drivers/char/hvc_rtas.c: 73cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * (C) Copyright IBM Corporation 2001-2005 83cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * (C) Copyright Red Hat, Inc. 2005 93cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * 103cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * This program is free software; you can redistribute it and/or modify 113cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * it under the terms of the GNU General Public License as published by 123cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * the Free Software Foundation; either version 2 of the License, or 133cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * (at your option) any later version. 143cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * 153cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * This program is distributed in the hope that it will be useful, 163cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * but WITHOUT ANY WARRANTY; without even the implied warranty of 173cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 183cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * GNU General Public License for more details. 193cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * 203cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * You should have received a copy of the GNU General Public License along 213cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * with this program; if not, write to the Free Software Foundation, Inc., 223cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 233cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou */ 243cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 253cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou#include <linux/module.h> 263cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou#include <linux/init.h> 273cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou#include <linux/err.h> 283cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou#include <linux/string.h> 293cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou#include <linux/console.h> 303cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou#include <asm/prom.h> 313cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou#include <asm/hvconsole.h> 323cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou#include <asm/firmware.h> 333cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 343cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou#include "hvc_console.h" 353cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 363cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kouextern int64_t beat_get_term_char(uint64_t, uint64_t *, uint64_t *, uint64_t *); 373cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kouextern int64_t beat_put_term_char(uint64_t, uint64_t, uint64_t, uint64_t); 383cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 393cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Koustruct hvc_struct *hvc_beat_dev = NULL; 403cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 413cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou/* bug: only one queue is available regardless of vtermno */ 423cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Koustatic int hvc_beat_get_chars(uint32_t vtermno, char *buf, int cnt) 433cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou{ 443cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou static unsigned char q[sizeof(unsigned long) * 2] 453cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou __attribute__((aligned(sizeof(unsigned long)))); 463cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou static int qlen = 0; 4719b0bd025d6647549e07becf02b99e5168c17432Ingo Molnar u64 got; 483cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 493cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kouagain: 503cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou if (qlen) { 513cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou if (qlen > cnt) { 523cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou memcpy(buf, q, cnt); 533cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou qlen -= cnt; 543cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou memmove(q + cnt, q, qlen); 553cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou return cnt; 563cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou } else { /* qlen <= cnt */ 573cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou int r; 583cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 593cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou memcpy(buf, q, qlen); 603cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou r = qlen; 613cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou qlen = 0; 623cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou return r; 633cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou } 643cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou } 653cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou if (beat_get_term_char(vtermno, &got, 6619b0bd025d6647549e07becf02b99e5168c17432Ingo Molnar ((u64 *)q), ((u64 *)q) + 1) == 0) { 673cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou qlen = got; 683cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou goto again; 693cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou } 703cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou return 0; 713cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou} 723cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 733cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Koustatic int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt) 743cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou{ 753cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou unsigned long kb[2]; 763cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou int rest, nlen; 773cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 783cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou for (rest = cnt; rest > 0; rest -= nlen) { 793cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou nlen = (rest > 16) ? 16 : rest; 803cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou memcpy(kb, buf, nlen); 8155045d47d7a8c4c61bc0ca6f2fac5087dd598bc3Ishizaki Kou beat_put_term_char(vtermno, nlen, kb[0], kb[1]); 8255045d47d7a8c4c61bc0ca6f2fac5087dd598bc3Ishizaki Kou buf += nlen; 833cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou } 843cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou return cnt; 853cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou} 863cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 871dff399616a79b8ef5d61ad68f2ef1e1f590b465Rusty Russellstatic const struct hv_ops hvc_beat_get_put_ops = { 883cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou .get_chars = hvc_beat_get_chars, 893cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou .put_chars = hvc_beat_put_chars, 903cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou}; 913cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 923cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Koustatic int hvc_beat_useit = 1; 933cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 943cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Koustatic int hvc_beat_config(char *p) 953cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou{ 963cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou hvc_beat_useit = simple_strtoul(p, NULL, 0); 973cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou return 0; 983cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou} 993cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 100301d9cb80b4f64ba24d4b141ad3ca58165a29afbIshizaki Koustatic int __init hvc_beat_console_init(void) 1013cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou{ 10271a157e8edca55198e808f8561dd49017a54ee34Grant Likely if (hvc_beat_useit && of_machine_is_compatible("Beat")) { 1033cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou hvc_instantiate(0, 0, &hvc_beat_get_put_ops); 1043cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou } 1053cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou return 0; 1063cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou} 1073cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 1083cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou/* temp */ 109301d9cb80b4f64ba24d4b141ad3ca58165a29afbIshizaki Koustatic int __init hvc_beat_init(void) 1103cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou{ 1113cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou struct hvc_struct *hp; 1123cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 1133cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou if (!firmware_has_feature(FW_FEATURE_BEAT)) 1143cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou return -ENODEV; 1153cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 116d4e33fac2408d37f7b52e80ca2a89f9fb482914fAlan Cox hp = hvc_alloc(0, 0, &hvc_beat_get_put_ops, 16); 1173cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou if (IS_ERR(hp)) 1183cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou return PTR_ERR(hp); 1193cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou hvc_beat_dev = hp; 1203cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou return 0; 1213cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou} 1223cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 1233cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Koustatic void __exit hvc_beat_exit(void) 1243cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou{ 1253cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou if (hvc_beat_dev) 1263cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou hvc_remove(hvc_beat_dev); 1273cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou} 1283cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 1293cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Koumodule_init(hvc_beat_init); 1303cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Koumodule_exit(hvc_beat_exit); 1313cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 1323cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou__setup("hvc_beat=", hvc_beat_config); 1333cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kou 1343cdc20e51791bd2fd67781e65640a4650f99c63eIshizaki Kouconsole_initcall(hvc_beat_console_init); 135