162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * console.c: Routines that deal with sending and receiving IO 462306a36Sopenharmony_ci * to/from the current console device using the PROM. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/types.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/sched.h> 1262306a36Sopenharmony_ci#include <asm/openprom.h> 1362306a36Sopenharmony_ci#include <asm/oplib.h> 1462306a36Sopenharmony_ci#include <linux/string.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* Non blocking get character from console input device, returns -1 1762306a36Sopenharmony_ci * if no input was taken. This can be used for polling. 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ciint 2062306a36Sopenharmony_ciprom_nbgetchar(void) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci int i = -1; 2362306a36Sopenharmony_ci unsigned long flags; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci local_irq_save(flags); 2662306a36Sopenharmony_ci i = (*(romvec->pv_nbgetchar))(); 2762306a36Sopenharmony_ci local_irq_restore(flags); 2862306a36Sopenharmony_ci return i; /* Ugh, we could spin forever on unsupported proms ;( */ 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* Non blocking put character to console device, returns -1 if 3262306a36Sopenharmony_ci * unsuccessful. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ciint 3562306a36Sopenharmony_ciprom_nbputchar(char c) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci unsigned long flags; 3862306a36Sopenharmony_ci int i = -1; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci local_irq_save(flags); 4162306a36Sopenharmony_ci i = (*(romvec->pv_nbputchar))(c); 4262306a36Sopenharmony_ci local_irq_restore(flags); 4362306a36Sopenharmony_ci return i; /* Ugh, we could spin forever on unsupported proms ;( */ 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* Blocking version of get character routine above. */ 4762306a36Sopenharmony_cichar 4862306a36Sopenharmony_ciprom_getchar(void) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci int character; 5162306a36Sopenharmony_ci while((character = prom_nbgetchar()) == -1) ; 5262306a36Sopenharmony_ci return (char) character; 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* Blocking version of put character routine above. */ 5662306a36Sopenharmony_civoid 5762306a36Sopenharmony_ciprom_putchar(char c) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci while(prom_nbputchar(c) == -1) ; 6062306a36Sopenharmony_ci return; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* Query for input device type */ 6462306a36Sopenharmony_ci#if 0 6562306a36Sopenharmony_cienum prom_input_device 6662306a36Sopenharmony_ciprom_query_input_device() 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci unsigned long flags; 6962306a36Sopenharmony_ci int st_p; 7062306a36Sopenharmony_ci char propb[64]; 7162306a36Sopenharmony_ci char *p; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci switch(prom_vers) { 7462306a36Sopenharmony_ci case PROM_V0: 7562306a36Sopenharmony_ci case PROM_V2: 7662306a36Sopenharmony_ci default: 7762306a36Sopenharmony_ci switch(*romvec->pv_stdin) { 7862306a36Sopenharmony_ci case PROMDEV_KBD: return PROMDEV_IKBD; 7962306a36Sopenharmony_ci case PROMDEV_TTYA: return PROMDEV_ITTYA; 8062306a36Sopenharmony_ci case PROMDEV_TTYB: return PROMDEV_ITTYB; 8162306a36Sopenharmony_ci default: 8262306a36Sopenharmony_ci return PROMDEV_I_UNK; 8362306a36Sopenharmony_ci }; 8462306a36Sopenharmony_ci case PROM_V3: 8562306a36Sopenharmony_ci case PROM_P1275: 8662306a36Sopenharmony_ci local_irq_save(flags); 8762306a36Sopenharmony_ci st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin); 8862306a36Sopenharmony_ci __asm__ __volatile__("ld [%0], %%g6\n\t" : : 8962306a36Sopenharmony_ci "r" (¤t_set[smp_processor_id()]) : 9062306a36Sopenharmony_ci "memory"); 9162306a36Sopenharmony_ci local_irq_restore(flags); 9262306a36Sopenharmony_ci if(prom_node_has_property(st_p, "keyboard")) 9362306a36Sopenharmony_ci return PROMDEV_IKBD; 9462306a36Sopenharmony_ci prom_getproperty(st_p, "device_type", propb, sizeof(propb)); 9562306a36Sopenharmony_ci if(strncmp(propb, "serial", sizeof("serial"))) 9662306a36Sopenharmony_ci return PROMDEV_I_UNK; 9762306a36Sopenharmony_ci prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb)); 9862306a36Sopenharmony_ci p = propb; 9962306a36Sopenharmony_ci while(*p) p++; p -= 2; 10062306a36Sopenharmony_ci if(p[0] == ':') { 10162306a36Sopenharmony_ci if(p[1] == 'a') 10262306a36Sopenharmony_ci return PROMDEV_ITTYA; 10362306a36Sopenharmony_ci else if(p[1] == 'b') 10462306a36Sopenharmony_ci return PROMDEV_ITTYB; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci return PROMDEV_I_UNK; 10762306a36Sopenharmony_ci }; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci#endif 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* Query for output device type */ 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#if 0 11462306a36Sopenharmony_cienum prom_output_device 11562306a36Sopenharmony_ciprom_query_output_device() 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci unsigned long flags; 11862306a36Sopenharmony_ci int st_p; 11962306a36Sopenharmony_ci char propb[64]; 12062306a36Sopenharmony_ci char *p; 12162306a36Sopenharmony_ci int propl; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci switch(prom_vers) { 12462306a36Sopenharmony_ci case PROM_V0: 12562306a36Sopenharmony_ci switch(*romvec->pv_stdin) { 12662306a36Sopenharmony_ci case PROMDEV_SCREEN: return PROMDEV_OSCREEN; 12762306a36Sopenharmony_ci case PROMDEV_TTYA: return PROMDEV_OTTYA; 12862306a36Sopenharmony_ci case PROMDEV_TTYB: return PROMDEV_OTTYB; 12962306a36Sopenharmony_ci }; 13062306a36Sopenharmony_ci break; 13162306a36Sopenharmony_ci case PROM_V2: 13262306a36Sopenharmony_ci case PROM_V3: 13362306a36Sopenharmony_ci case PROM_P1275: 13462306a36Sopenharmony_ci local_irq_save(flags); 13562306a36Sopenharmony_ci st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout); 13662306a36Sopenharmony_ci __asm__ __volatile__("ld [%0], %%g6\n\t" : : 13762306a36Sopenharmony_ci "r" (¤t_set[smp_processor_id()]) : 13862306a36Sopenharmony_ci "memory"); 13962306a36Sopenharmony_ci local_irq_restore(flags); 14062306a36Sopenharmony_ci propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb)); 14162306a36Sopenharmony_ci if (propl >= 0 && propl == sizeof("display") && 14262306a36Sopenharmony_ci strncmp("display", propb, sizeof("display")) == 0) 14362306a36Sopenharmony_ci { 14462306a36Sopenharmony_ci return PROMDEV_OSCREEN; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci if(prom_vers == PROM_V3) { 14762306a36Sopenharmony_ci if(strncmp("serial", propb, sizeof("serial"))) 14862306a36Sopenharmony_ci return PROMDEV_O_UNK; 14962306a36Sopenharmony_ci prom_getproperty(prom_root_node, "stdout-path", propb, sizeof(propb)); 15062306a36Sopenharmony_ci p = propb; 15162306a36Sopenharmony_ci while(*p) p++; p -= 2; 15262306a36Sopenharmony_ci if(p[0]==':') { 15362306a36Sopenharmony_ci if(p[1] == 'a') 15462306a36Sopenharmony_ci return PROMDEV_OTTYA; 15562306a36Sopenharmony_ci else if(p[1] == 'b') 15662306a36Sopenharmony_ci return PROMDEV_OTTYB; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci return PROMDEV_O_UNK; 15962306a36Sopenharmony_ci } else { 16062306a36Sopenharmony_ci /* This works on SS-2 (an early OpenFirmware) still. */ 16162306a36Sopenharmony_ci switch(*romvec->pv_stdin) { 16262306a36Sopenharmony_ci case PROMDEV_TTYA: return PROMDEV_OTTYA; 16362306a36Sopenharmony_ci case PROMDEV_TTYB: return PROMDEV_OTTYB; 16462306a36Sopenharmony_ci }; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci break; 16762306a36Sopenharmony_ci }; 16862306a36Sopenharmony_ci return PROMDEV_O_UNK; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci#endif 171