parisc: Add soft power switch button emulation for QEMU
Emulate the soft power switch button at the address of pad0[2] in PAGE0.
With that change it's now possible to use the qemu menu to force a
shutdown.
Signed-off-by: Helge Deller <deller@gmx.de>
diff --git a/src/parisc/parisc.c b/src/parisc/parisc.c
index 17d0ae9..14196ef 100644
--- a/src/parisc/parisc.c
+++ b/src/parisc/parisc.c
@@ -135,6 +135,13 @@
static unsigned int chassis_code = 0;
+/*
+ * For QEMU we emulate the power switch button flag in pad0[2] in PAGE0.
+ * Bit 31 (the lowest bit) is the status of the power switch.
+ * This bit is "1" if the button is NOT pressed.
+ */
+#define powersw_button PAGE0->pad0[2]
+
void __VISIBLE __noreturn hlt(void)
{
if (pdc_debug)
@@ -144,12 +151,22 @@
while (1);
}
+static void check_powersw_button(void)
+{
+ /* halt immediately if power button was pressed. */
+ if ((powersw_button & 1) == 0) {
+ printf("SeaBIOS machine power switch was pressed.\n");
+ hlt();
+ }
+}
+
void __noreturn reset(void)
{
if (pdc_debug)
printf("RESET initiated from %p\n", __builtin_return_address(0));
printf("SeaBIOS wants SYSTEM RESET.\n"
"***************************\n");
+ check_powersw_button();
PAGE0->imm_soft_boot = 1;
asm volatile("\t.word 0xfffdead1": : :"memory");
while (1);
@@ -1266,10 +1283,17 @@
static int pdc_soft_power(unsigned int *arg)
{
unsigned long option = ARG1;
+ unsigned long *result = (unsigned long *)ARG2;
switch (option) {
+ case PDC_SOFT_POWER_INFO:
+ result[0] = (unsigned long) &(powersw_button);
+ return PDC_OK;
case PDC_SOFT_POWER_ENABLE:
- /* put soft power button under hardware (ARG3=0) or software (ARG3=1) control. */
+ /* put soft power button under hardware (ARG3=0) or
+ * software (ARG3=1) control. */
+ powersw_button = (ARG3 & 1) << 8 | (powersw_button & 1);
+ check_powersw_button();
return PDC_OK;
}
// dprintf(0, "\n\nSeaBIOS: PDC_SOFT_POWER called with ARG2=%x ARG3=%x ARG4=%x\n", ARG2, ARG3, ARG4);
@@ -1729,6 +1753,7 @@
/* Put QEMU/SeaBIOS marker in PAGE0.
* The Linux kernel will search for it. */
memcpy((char*)&PAGE0->pad0, "SeaBIOS", 8);
+ powersw_button = 0x01; /* button not pressed, hw controlled. */
PAGE0->imm_hpa = MEMORY_HPA;
PAGE0->imm_spa_size = ram_size;
diff --git a/src/parisc/pdc.h b/src/parisc/pdc.h
index 1521172..23af5cc 100644
--- a/src/parisc/pdc.h
+++ b/src/parisc/pdc.h
@@ -401,7 +401,8 @@
int vec_pad[10];
/* [0x040] reserved processor dependent */
- int pad0[112];
+ int pad0[112]; /* in QEMU pad0[0] holds "SeaBIOS\0" */
+ /* and pad0[2] holds soft power button */
/* [0x200] reserved */
int pad1[84];