^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * console.c: Routines that deal with sending and receiving IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * to/from the current console device using the PROM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/openprom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/oplib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Non blocking get character from console input device, returns -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * if no input was taken. This can be used for polling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) prom_nbgetchar(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int i = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) i = (*(romvec->pv_nbgetchar))();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return i; /* Ugh, we could spin forever on unsupported proms ;( */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Non blocking put character to console device, returns -1 if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * unsuccessful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) prom_nbputchar(char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int i = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) i = (*(romvec->pv_nbputchar))(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return i; /* Ugh, we could spin forever on unsupported proms ;( */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Blocking version of get character routine above. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) char
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) prom_getchar(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int character;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) while((character = prom_nbgetchar()) == -1) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return (char) character;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* Blocking version of put character routine above. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) prom_putchar(char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) while(prom_nbputchar(c) == -1) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Query for input device type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) enum prom_input_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) prom_query_input_device()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int st_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) char propb[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) switch(prom_vers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) case PROM_V0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) case PROM_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) switch(*romvec->pv_stdin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) case PROMDEV_KBD: return PROMDEV_IKBD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) case PROMDEV_TTYA: return PROMDEV_ITTYA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) case PROMDEV_TTYB: return PROMDEV_ITTYB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return PROMDEV_I_UNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) case PROM_V3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case PROM_P1275:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) __asm__ __volatile__("ld [%0], %%g6\n\t" : :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) "r" (¤t_set[smp_processor_id()]) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if(prom_node_has_property(st_p, "keyboard"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return PROMDEV_IKBD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) prom_getproperty(st_p, "device_type", propb, sizeof(propb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if(strncmp(propb, "serial", sizeof("serial")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return PROMDEV_I_UNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) p = propb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) while(*p) p++; p -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if(p[0] == ':') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if(p[1] == 'a')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return PROMDEV_ITTYA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) else if(p[1] == 'b')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return PROMDEV_ITTYB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return PROMDEV_I_UNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Query for output device type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) enum prom_output_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) prom_query_output_device()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int st_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) char propb[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int propl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) switch(prom_vers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case PROM_V0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) switch(*romvec->pv_stdin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case PROMDEV_SCREEN: return PROMDEV_OSCREEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case PROMDEV_TTYA: return PROMDEV_OTTYA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case PROMDEV_TTYB: return PROMDEV_OTTYB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case PROM_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case PROM_V3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case PROM_P1275:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) __asm__ __volatile__("ld [%0], %%g6\n\t" : :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) "r" (¤t_set[smp_processor_id()]) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (propl >= 0 && propl == sizeof("display") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) strncmp("display", propb, sizeof("display")) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return PROMDEV_OSCREEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if(prom_vers == PROM_V3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if(strncmp("serial", propb, sizeof("serial")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return PROMDEV_O_UNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) prom_getproperty(prom_root_node, "stdout-path", propb, sizeof(propb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) p = propb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) while(*p) p++; p -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if(p[0]==':') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if(p[1] == 'a')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return PROMDEV_OTTYA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) else if(p[1] == 'b')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return PROMDEV_OTTYB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return PROMDEV_O_UNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* This works on SS-2 (an early OpenFirmware) still. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) switch(*romvec->pv_stdin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case PROMDEV_TTYA: return PROMDEV_OTTYA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case PROMDEV_TTYB: return PROMDEV_OTTYB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return PROMDEV_O_UNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #endif