18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * console.c: Routines that deal with sending and receiving IO
48c2ecf20Sopenharmony_ci *            to/from the current console device using the PROM.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/types.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/sched.h>
128c2ecf20Sopenharmony_ci#include <asm/openprom.h>
138c2ecf20Sopenharmony_ci#include <asm/oplib.h>
148c2ecf20Sopenharmony_ci#include <linux/string.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* Non blocking get character from console input device, returns -1
178c2ecf20Sopenharmony_ci * if no input was taken.  This can be used for polling.
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_ciint
208c2ecf20Sopenharmony_ciprom_nbgetchar(void)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	int i = -1;
238c2ecf20Sopenharmony_ci	unsigned long flags;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	local_irq_save(flags);
268c2ecf20Sopenharmony_ci		i = (*(romvec->pv_nbgetchar))();
278c2ecf20Sopenharmony_ci	local_irq_restore(flags);
288c2ecf20Sopenharmony_ci	return i; /* Ugh, we could spin forever on unsupported proms ;( */
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/* Non blocking put character to console device, returns -1 if
328c2ecf20Sopenharmony_ci * unsuccessful.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ciint
358c2ecf20Sopenharmony_ciprom_nbputchar(char c)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	unsigned long flags;
388c2ecf20Sopenharmony_ci	int i = -1;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	local_irq_save(flags);
418c2ecf20Sopenharmony_ci		i = (*(romvec->pv_nbputchar))(c);
428c2ecf20Sopenharmony_ci	local_irq_restore(flags);
438c2ecf20Sopenharmony_ci	return i; /* Ugh, we could spin forever on unsupported proms ;( */
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* Blocking version of get character routine above. */
478c2ecf20Sopenharmony_cichar
488c2ecf20Sopenharmony_ciprom_getchar(void)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	int character;
518c2ecf20Sopenharmony_ci	while((character = prom_nbgetchar()) == -1) ;
528c2ecf20Sopenharmony_ci	return (char) character;
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/* Blocking version of put character routine above. */
568c2ecf20Sopenharmony_civoid
578c2ecf20Sopenharmony_ciprom_putchar(char c)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	while(prom_nbputchar(c) == -1) ;
608c2ecf20Sopenharmony_ci	return;
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/* Query for input device type */
648c2ecf20Sopenharmony_ci#if 0
658c2ecf20Sopenharmony_cienum prom_input_device
668c2ecf20Sopenharmony_ciprom_query_input_device()
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	unsigned long flags;
698c2ecf20Sopenharmony_ci	int st_p;
708c2ecf20Sopenharmony_ci	char propb[64];
718c2ecf20Sopenharmony_ci	char *p;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	switch(prom_vers) {
748c2ecf20Sopenharmony_ci	case PROM_V0:
758c2ecf20Sopenharmony_ci	case PROM_V2:
768c2ecf20Sopenharmony_ci	default:
778c2ecf20Sopenharmony_ci		switch(*romvec->pv_stdin) {
788c2ecf20Sopenharmony_ci		case PROMDEV_KBD:	return PROMDEV_IKBD;
798c2ecf20Sopenharmony_ci		case PROMDEV_TTYA:	return PROMDEV_ITTYA;
808c2ecf20Sopenharmony_ci		case PROMDEV_TTYB:	return PROMDEV_ITTYB;
818c2ecf20Sopenharmony_ci		default:
828c2ecf20Sopenharmony_ci			return PROMDEV_I_UNK;
838c2ecf20Sopenharmony_ci		};
848c2ecf20Sopenharmony_ci	case PROM_V3:
858c2ecf20Sopenharmony_ci	case PROM_P1275:
868c2ecf20Sopenharmony_ci		local_irq_save(flags);
878c2ecf20Sopenharmony_ci		st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
888c2ecf20Sopenharmony_ci		__asm__ __volatile__("ld [%0], %%g6\n\t" : :
898c2ecf20Sopenharmony_ci				     "r" (&current_set[smp_processor_id()]) :
908c2ecf20Sopenharmony_ci				     "memory");
918c2ecf20Sopenharmony_ci		local_irq_restore(flags);
928c2ecf20Sopenharmony_ci		if(prom_node_has_property(st_p, "keyboard"))
938c2ecf20Sopenharmony_ci			return PROMDEV_IKBD;
948c2ecf20Sopenharmony_ci		prom_getproperty(st_p, "device_type", propb, sizeof(propb));
958c2ecf20Sopenharmony_ci		if(strncmp(propb, "serial", sizeof("serial")))
968c2ecf20Sopenharmony_ci			return PROMDEV_I_UNK;
978c2ecf20Sopenharmony_ci		prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
988c2ecf20Sopenharmony_ci		p = propb;
998c2ecf20Sopenharmony_ci		while(*p) p++; p -= 2;
1008c2ecf20Sopenharmony_ci		if(p[0] == ':') {
1018c2ecf20Sopenharmony_ci			if(p[1] == 'a')
1028c2ecf20Sopenharmony_ci				return PROMDEV_ITTYA;
1038c2ecf20Sopenharmony_ci			else if(p[1] == 'b')
1048c2ecf20Sopenharmony_ci				return PROMDEV_ITTYB;
1058c2ecf20Sopenharmony_ci		}
1068c2ecf20Sopenharmony_ci		return PROMDEV_I_UNK;
1078c2ecf20Sopenharmony_ci	};
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci#endif
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci/* Query for output device type */
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci#if 0
1148c2ecf20Sopenharmony_cienum prom_output_device
1158c2ecf20Sopenharmony_ciprom_query_output_device()
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	unsigned long flags;
1188c2ecf20Sopenharmony_ci	int st_p;
1198c2ecf20Sopenharmony_ci	char propb[64];
1208c2ecf20Sopenharmony_ci	char *p;
1218c2ecf20Sopenharmony_ci	int propl;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	switch(prom_vers) {
1248c2ecf20Sopenharmony_ci	case PROM_V0:
1258c2ecf20Sopenharmony_ci		switch(*romvec->pv_stdin) {
1268c2ecf20Sopenharmony_ci		case PROMDEV_SCREEN:	return PROMDEV_OSCREEN;
1278c2ecf20Sopenharmony_ci		case PROMDEV_TTYA:	return PROMDEV_OTTYA;
1288c2ecf20Sopenharmony_ci		case PROMDEV_TTYB:	return PROMDEV_OTTYB;
1298c2ecf20Sopenharmony_ci		};
1308c2ecf20Sopenharmony_ci		break;
1318c2ecf20Sopenharmony_ci	case PROM_V2:
1328c2ecf20Sopenharmony_ci	case PROM_V3:
1338c2ecf20Sopenharmony_ci	case PROM_P1275:
1348c2ecf20Sopenharmony_ci		local_irq_save(flags);
1358c2ecf20Sopenharmony_ci		st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
1368c2ecf20Sopenharmony_ci		__asm__ __volatile__("ld [%0], %%g6\n\t" : :
1378c2ecf20Sopenharmony_ci				     "r" (&current_set[smp_processor_id()]) :
1388c2ecf20Sopenharmony_ci				     "memory");
1398c2ecf20Sopenharmony_ci		local_irq_restore(flags);
1408c2ecf20Sopenharmony_ci		propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
1418c2ecf20Sopenharmony_ci		if (propl >= 0 && propl == sizeof("display") &&
1428c2ecf20Sopenharmony_ci			strncmp("display", propb, sizeof("display")) == 0)
1438c2ecf20Sopenharmony_ci		{
1448c2ecf20Sopenharmony_ci			return PROMDEV_OSCREEN;
1458c2ecf20Sopenharmony_ci		}
1468c2ecf20Sopenharmony_ci		if(prom_vers == PROM_V3) {
1478c2ecf20Sopenharmony_ci			if(strncmp("serial", propb, sizeof("serial")))
1488c2ecf20Sopenharmony_ci				return PROMDEV_O_UNK;
1498c2ecf20Sopenharmony_ci			prom_getproperty(prom_root_node, "stdout-path", propb, sizeof(propb));
1508c2ecf20Sopenharmony_ci			p = propb;
1518c2ecf20Sopenharmony_ci			while(*p) p++; p -= 2;
1528c2ecf20Sopenharmony_ci			if(p[0]==':') {
1538c2ecf20Sopenharmony_ci				if(p[1] == 'a')
1548c2ecf20Sopenharmony_ci					return PROMDEV_OTTYA;
1558c2ecf20Sopenharmony_ci				else if(p[1] == 'b')
1568c2ecf20Sopenharmony_ci					return PROMDEV_OTTYB;
1578c2ecf20Sopenharmony_ci			}
1588c2ecf20Sopenharmony_ci			return PROMDEV_O_UNK;
1598c2ecf20Sopenharmony_ci		} else {
1608c2ecf20Sopenharmony_ci			/* This works on SS-2 (an early OpenFirmware) still. */
1618c2ecf20Sopenharmony_ci			switch(*romvec->pv_stdin) {
1628c2ecf20Sopenharmony_ci			case PROMDEV_TTYA:	return PROMDEV_OTTYA;
1638c2ecf20Sopenharmony_ci			case PROMDEV_TTYB:	return PROMDEV_OTTYB;
1648c2ecf20Sopenharmony_ci			};
1658c2ecf20Sopenharmony_ci		}
1668c2ecf20Sopenharmony_ci		break;
1678c2ecf20Sopenharmony_ci	};
1688c2ecf20Sopenharmony_ci	return PROMDEV_O_UNK;
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci#endif
171