aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/system/device-emulation.rst1
-rw-r--r--docs/system/devices/keyboard.rst129
-rw-r--r--docs/system/target-sparc.rst2
-rw-r--r--hw/char/escc.c79
-rw-r--r--include/hw/char/escc.h1
5 files changed, 210 insertions, 2 deletions
diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst
index 8d4a182..4491c4c 100644
--- a/docs/system/device-emulation.rst
+++ b/docs/system/device-emulation.rst
@@ -86,6 +86,7 @@ Emulated Devices
devices/ccid.rst
devices/cxl.rst
devices/ivshmem.rst
+ devices/keyboard.rst
devices/net.rst
devices/nvme.rst
devices/usb.rst
diff --git a/docs/system/devices/keyboard.rst b/docs/system/devices/keyboard.rst
new file mode 100644
index 0000000..a8f9fbe
--- /dev/null
+++ b/docs/system/devices/keyboard.rst
@@ -0,0 +1,129 @@
+.. _keyboard:
+
+Sparc32 keyboard
+----------------
+SUN Type 4, 5 and 5c keyboards have dip switches to choose the language layout
+of the keyboard. Solaris makes an ioctl to query the value of the dipswitches
+and uses that value to select keyboard layout. Also the SUN bios like the one
+in the file ss5.bin uses this value to support at least some keyboard layouts.
+However, the OpenBIOS provided with qemu is hardcoded to always use an
+US keyboard layout.
+
+With the escc.chnA-sunkbd-layout driver property it is possible to select
+keyboard layout. Example:
+
+-global escc.chnA-sunkbd-layout=de
+
+Depending on type of keyboard, the keyboard can have 6 or 5 dip-switches to
+select keyboard layout, giving up to 64 different layouts. Not all
+combinations are supported by Solaris and even less by Sun OpenBoot BIOS.
+
+The dip switch settings can be given as hexadecimal number, decimal number
+or in some cases as a language string. Examples:
+
+-global escc.chnA-sunkbd-layout=0x2b
+
+-global escc.chnA-sunkbd-layout=43
+
+-global escc.chnA-sunkbd-layout=sv
+
+The above 3 examples all select a swedish keyboard layout. Table 3-15 at
+https://docs.oracle.com/cd/E19683-01/806-6642/new-43/index.html explains which
+keytable file is used for different dip switch settings. The information
+in that table can be summarized in this table:
+
+.. list-table:: Language selection values for escc.chnA-sunkbd-layout
+ :widths: 10 10 10
+ :header-rows: 1
+
+ * - Hexadecimal value
+ - Decimal value
+ - Language code
+ * - 0x21
+ - 33
+ - en-us
+ * - 0x23
+ - 35
+ - fr
+ * - 0x24
+ - 36
+ - da
+ * - 0x25
+ - 37
+ - de
+ * - 0x26
+ - 38
+ - it
+ * - 0x27
+ - 39
+ - nl
+ * - 0x28
+ - 40
+ - no
+ * - 0x29
+ - 41
+ - pt
+ * - 0x2a
+ - 42
+ - es
+ * - 0x2b
+ - 43
+ - sv
+ * - 0x2c
+ - 44
+ - fr-ch
+ * - 0x2d
+ - 45
+ - de-ch
+ * - 0x2e
+ - 46
+ - en-gb
+ * - 0x2f
+ - 47
+ - ko
+ * - 0x30
+ - 48
+ - tw
+ * - 0x31
+ - 49
+ - ja
+ * - 0x32
+ - 50
+ - fr-ca
+ * - 0x33
+ - 51
+ - hu
+ * - 0x34
+ - 52
+ - pl
+ * - 0x35
+ - 53
+ - cz
+ * - 0x36
+ - 54
+ - ru
+ * - 0x37
+ - 55
+ - lv
+ * - 0x38
+ - 56
+ - tr
+ * - 0x39
+ - 57
+ - gr
+ * - 0x3a
+ - 58
+ - ar
+ * - 0x3b
+ - 59
+ - lt
+ * - 0x3c
+ - 60
+ - nl-be
+ * - 0x3c
+ - 60
+ - be
+
+Not all dip switch values have a corresponding language code and both "be" and
+"nl-be" correspond to the same dip switch value. By default, if no value is
+given to escc.chnA-sunkbd-layout 0x21 (en-us) will be used.
diff --git a/docs/system/target-sparc.rst b/docs/system/target-sparc.rst
index b55f8d0..9ec8c90 100644
--- a/docs/system/target-sparc.rst
+++ b/docs/system/target-sparc.rst
@@ -38,7 +38,7 @@ QEMU emulates the following sun4m peripherals:
- Non Volatile RAM M48T02/M48T08
- Slave I/O: timers, interrupt controllers, Zilog serial ports,
- keyboard and power/reset logic
+ :ref:`keyboard` and power/reset logic
- ESP SCSI controller with hard disk and CD-ROM support
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 17a908c..4f3872b 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -31,6 +31,8 @@
#include "qemu/module.h"
#include "hw/char/escc.h"
#include "ui/console.h"
+
+#include "qemu/cutils.h"
#include "trace.h"
/*
@@ -190,6 +192,7 @@
#define R_MISC1I 14
#define R_EXTINT 15
+static uint8_t sunkbd_layout_dip_switch(const char *sunkbd_layout);
static void handle_kbd_command(ESCCChannelState *s, int val);
static int serial_can_receive(void *opaque);
static void serial_receive_byte(ESCCChannelState *s, int ch);
@@ -846,6 +849,79 @@ static QemuInputHandler sunkbd_handler = {
.event = sunkbd_handle_event,
};
+static uint8_t sunkbd_layout_dip_switch(const char *kbd_layout)
+{
+ /* Return the value of the dip-switches in a SUN Type 5 keyboard */
+ static uint8_t ret = 0xff;
+
+ if ((ret == 0xff) && kbd_layout) {
+ int i;
+ struct layout_values {
+ const char *lang;
+ uint8_t dip;
+ } languages[] =
+ /*
+ * Dip values from table 3-16 Layouts for Type 4, 5 and 5c Keyboards
+ */
+ {
+ {"en-us", 0x21}, /* U.S.A. (US5.kt) */
+ /* 0x22 is some other US (US_UNIX5.kt) */
+ {"fr", 0x23}, /* France (France5.kt) */
+ {"da", 0x24}, /* Denmark (Denmark5.kt) */
+ {"de", 0x25}, /* Germany (Germany5.kt) */
+ {"it", 0x26}, /* Italy (Italy5.kt) */
+ {"nl", 0x27}, /* The Netherlands (Netherland5.kt) */
+ {"no", 0x28}, /* Norway (Norway.kt) */
+ {"pt", 0x29}, /* Portugal (Portugal5.kt) */
+ {"es", 0x2a}, /* Spain (Spain5.kt) */
+ {"sv", 0x2b}, /* Sweden (Sweden5.kt) */
+ {"fr-ch", 0x2c}, /* Switzerland/French (Switzer_Fr5.kt) */
+ {"de-ch", 0x2d}, /* Switzerland/German (Switzer_Ge5.kt) */
+ {"en-gb", 0x2e}, /* Great Britain (UK5.kt) */
+ {"ko", 0x2f}, /* Korea (Korea5.kt) */
+ {"tw", 0x30}, /* Taiwan (Taiwan5.kt) */
+ {"ja", 0x31}, /* Japan (Japan5.kt) */
+ {"fr-ca", 0x32}, /* Canada/French (Canada_Fr5.kt) */
+ {"hu", 0x33}, /* Hungary (Hungary5.kt) */
+ {"pl", 0x34}, /* Poland (Poland5.kt) */
+ {"cz", 0x35}, /* Czech (Czech5.kt) */
+ {"ru", 0x36}, /* Russia (Russia5.kt) */
+ {"lv", 0x37}, /* Latvia (Latvia5.kt) */
+ {"tr", 0x38}, /* Turkey-Q5 (TurkeyQ5.kt) */
+ {"gr", 0x39}, /* Greece (Greece5.kt) */
+ {"ar", 0x3a}, /* Arabic (Arabic5.kt) */
+ {"lt", 0x3b}, /* Lithuania (Lithuania5.kt) */
+ {"nl-be", 0x3c}, /* Belgium (Belgian5.kt) */
+ {"be", 0x3c}, /* Belgium (Belgian5.kt) */
+ };
+
+ for (i = 0;
+ i < sizeof(languages) / sizeof(struct layout_values);
+ i++) {
+ if (!strcmp(kbd_layout, languages[i].lang)) {
+ ret = languages[i].dip;
+ return ret;
+ }
+ }
+
+ /* Found no known language code */
+ if ((kbd_layout[0] >= '0') && (kbd_layout[0] <= '9')) {
+ unsigned int tmp;
+
+ /* As a fallback we also accept numeric dip switch value */
+ if (!qemu_strtoui(kbd_layout, NULL, 0, &tmp)) {
+ ret = tmp;
+ }
+ }
+ }
+
+ if (ret == 0xff) {
+ /* Final fallback if keyboard_layout was not set or recognized */
+ ret = 0x21; /* en-us layout */
+ }
+ return ret;
+}
+
static void handle_kbd_command(ESCCChannelState *s, int val)
{
trace_escc_kbd_command(val);
@@ -867,7 +943,7 @@ static void handle_kbd_command(ESCCChannelState *s, int val)
case 0xf:
clear_queue(s);
put_queue(s, 0xfe);
- put_queue(s, 0x21); /* en-us layout */
+ put_queue(s, sunkbd_layout_dip_switch(s->sunkbd_layout));
break;
default:
break;
@@ -976,6 +1052,7 @@ static Property escc_properties[] = {
DEFINE_PROP_UINT32("chnAtype", ESCCState, chn[1].type, 0),
DEFINE_PROP_CHR("chrB", ESCCState, chn[0].chr),
DEFINE_PROP_CHR("chrA", ESCCState, chn[1].chr),
+ DEFINE_PROP_STRING("chnA-sunkbd-layout", ESCCState, chn[1].sunkbd_layout),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h
index 7e9482d..5669a5b 100644
--- a/include/hw/char/escc.h
+++ b/include/hw/char/escc.h
@@ -45,6 +45,7 @@ typedef struct ESCCChannelState {
ESCCChnType type;
uint8_t rx, tx;
QemuInputHandlerState *hs;
+ char *sunkbd_layout;
} ESCCChannelState;
struct ESCCState {