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" (¤t_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" (¤t_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