1708d4f09SSam Ravnborg /* 2708d4f09SSam Ravnborg * console.c: Routines that deal with sending and receiving IO 3708d4f09SSam Ravnborg * to/from the current console device using the PROM. 4708d4f09SSam Ravnborg * 5708d4f09SSam Ravnborg * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 6708d4f09SSam Ravnborg * Copyright (C) 1998 Pete Zaitcev <zaitcev@yahoo.com> 7708d4f09SSam Ravnborg */ 8708d4f09SSam Ravnborg 9708d4f09SSam Ravnborg #include <linux/types.h> 10708d4f09SSam Ravnborg #include <linux/kernel.h> 11708d4f09SSam Ravnborg #include <linux/sched.h> 12708d4f09SSam Ravnborg #include <asm/openprom.h> 13708d4f09SSam Ravnborg #include <asm/oplib.h> 14708d4f09SSam Ravnborg #include <asm/system.h> 15708d4f09SSam Ravnborg #include <linux/string.h> 16708d4f09SSam Ravnborg 17708d4f09SSam Ravnborg extern void restore_current(void); 18708d4f09SSam Ravnborg 19708d4f09SSam Ravnborg /* Non blocking get character from console input device, returns -1 20708d4f09SSam Ravnborg * if no input was taken. This can be used for polling. 21708d4f09SSam Ravnborg */ 22e62cac1fSDavid S. Miller static int prom_nbgetchar(char *buf) 23708d4f09SSam Ravnborg { 24708d4f09SSam Ravnborg unsigned long flags; 25e62cac1fSDavid S. Miller int i = -1; 26708d4f09SSam Ravnborg 27708d4f09SSam Ravnborg spin_lock_irqsave(&prom_lock, flags); 28708d4f09SSam Ravnborg switch(prom_vers) { 29708d4f09SSam Ravnborg case PROM_V0: 30708d4f09SSam Ravnborg i = (*(romvec->pv_nbgetchar))(); 31e62cac1fSDavid S. Miller if (i != -1) { 32e62cac1fSDavid S. Miller *buf = i; 33e62cac1fSDavid S. Miller i = 0; 34e62cac1fSDavid S. Miller } 35708d4f09SSam Ravnborg break; 36708d4f09SSam Ravnborg case PROM_V2: 37708d4f09SSam Ravnborg case PROM_V3: 38e62cac1fSDavid S. Miller if ((*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin, 39e62cac1fSDavid S. Miller buf, 0x1) == 1) 40e62cac1fSDavid S. Miller i = 0; 41708d4f09SSam Ravnborg break; 42708d4f09SSam Ravnborg default: 43708d4f09SSam Ravnborg break; 44708d4f09SSam Ravnborg }; 45708d4f09SSam Ravnborg restore_current(); 46708d4f09SSam Ravnborg spin_unlock_irqrestore(&prom_lock, flags); 47708d4f09SSam Ravnborg return i; /* Ugh, we could spin forever on unsupported proms ;( */ 48708d4f09SSam Ravnborg } 49708d4f09SSam Ravnborg 50708d4f09SSam Ravnborg /* Non blocking put character to console device, returns -1 if 51708d4f09SSam Ravnborg * unsuccessful. 52708d4f09SSam Ravnborg */ 53e62cac1fSDavid S. Miller static int prom_nbputchar(const char *buf) 54708d4f09SSam Ravnborg { 55708d4f09SSam Ravnborg unsigned long flags; 56708d4f09SSam Ravnborg int i = -1; 57708d4f09SSam Ravnborg 58708d4f09SSam Ravnborg spin_lock_irqsave(&prom_lock, flags); 59708d4f09SSam Ravnborg switch(prom_vers) { 60708d4f09SSam Ravnborg case PROM_V0: 61e62cac1fSDavid S. Miller i = (*(romvec->pv_nbputchar))(*buf); 62708d4f09SSam Ravnborg break; 63708d4f09SSam Ravnborg case PROM_V2: 64708d4f09SSam Ravnborg case PROM_V3: 65e62cac1fSDavid S. Miller if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, 66e62cac1fSDavid S. Miller buf, 0x1) == 1) 67708d4f09SSam Ravnborg i = 0; 68708d4f09SSam Ravnborg break; 69708d4f09SSam Ravnborg default: 70708d4f09SSam Ravnborg break; 71708d4f09SSam Ravnborg }; 72708d4f09SSam Ravnborg restore_current(); 73708d4f09SSam Ravnborg spin_unlock_irqrestore(&prom_lock, flags); 74708d4f09SSam Ravnborg return i; /* Ugh, we could spin forever on unsupported proms ;( */ 75708d4f09SSam Ravnborg } 76708d4f09SSam Ravnborg 77708d4f09SSam Ravnborg /* Blocking version of get character routine above. */ 78e62cac1fSDavid S. Miller void prom_getchar(char *buf) 79708d4f09SSam Ravnborg { 80e62cac1fSDavid S. Miller while (1) { 81e62cac1fSDavid S. Miller int err = prom_nbgetchar(buf); 82e62cac1fSDavid S. Miller if (!err) 83e62cac1fSDavid S. Miller break; 84e62cac1fSDavid S. Miller } 85708d4f09SSam Ravnborg } 86708d4f09SSam Ravnborg 87708d4f09SSam Ravnborg /* Blocking version of put character routine above. */ 88e62cac1fSDavid S. Miller void prom_putchar(const char *buf) 89708d4f09SSam Ravnborg { 90e62cac1fSDavid S. Miller while (1) { 91e62cac1fSDavid S. Miller int err = prom_nbputchar(buf); 92e62cac1fSDavid S. Miller if (!err) 93e62cac1fSDavid S. Miller break; 94e62cac1fSDavid S. Miller } 95708d4f09SSam Ravnborg } 96