|
Pablo Greco |
e6a3ae |
From 363d844cccb965c9eb0e0e6b5ca100e9532a2f0a Mon Sep 17 00:00:00 2001
|
|
Pablo Greco |
e6a3ae |
From: Thomas Huth <thuth@redhat.com>
|
|
Pablo Greco |
e6a3ae |
Date: Mon, 14 Oct 2019 10:06:37 +0100
|
|
Pablo Greco |
e6a3ae |
Subject: [PATCH 12/21] s390-bios: Support for running format-0/1 channel
|
|
Pablo Greco |
e6a3ae |
programs
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
RH-Author: Thomas Huth <thuth@redhat.com>
|
|
Pablo Greco |
e6a3ae |
Message-id: <20191014100645.22862-10-thuth@redhat.com>
|
|
Pablo Greco |
e6a3ae |
Patchwork-id: 91783
|
|
Pablo Greco |
e6a3ae |
O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 09/17] s390-bios: Support for running format-0/1 channel programs
|
|
Pablo Greco |
e6a3ae |
Bugzilla: 1664376
|
|
Pablo Greco |
e6a3ae |
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
|
Pablo Greco |
e6a3ae |
RH-Acked-by: David Hildenbrand <david@redhat.com>
|
|
Pablo Greco |
e6a3ae |
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
From: "Jason J. Herne" <jjherne@linux.ibm.com>
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
Introduce a library function for executing format-0 and format-1
|
|
Pablo Greco |
e6a3ae |
channel programs and waiting for their completion before continuing
|
|
Pablo Greco |
e6a3ae |
execution.
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
Add cu_type() to channel io library. This will be used to query control
|
|
Pablo Greco |
e6a3ae |
unit type which is used to determine if we are booting a virtio device or a
|
|
Pablo Greco |
e6a3ae |
real dasd device.
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
|
|
Pablo Greco |
e6a3ae |
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
|
|
Pablo Greco |
e6a3ae |
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
|
|
Pablo Greco |
e6a3ae |
Message-Id: <1554388475-18329-9-git-send-email-jjherne@linux.ibm.com>
|
|
Pablo Greco |
e6a3ae |
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
|
Pablo Greco |
e6a3ae |
(cherry picked from commit 3083a1bbb8716e9052fe375f68f330107ee13127)
|
|
Pablo Greco |
e6a3ae |
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
Pablo Greco |
e6a3ae |
---
|
|
Pablo Greco |
e6a3ae |
pc-bios/s390-ccw/cio.c | 144 ++++++++++++++++++++++++++++++++++++++++++++
|
|
Pablo Greco |
e6a3ae |
pc-bios/s390-ccw/cio.h | 130 ++++++++++++++++++++++++++++++++++++++-
|
|
Pablo Greco |
e6a3ae |
pc-bios/s390-ccw/s390-ccw.h | 1 +
|
|
Pablo Greco |
e6a3ae |
pc-bios/s390-ccw/start.S | 29 +++++++++
|
|
Pablo Greco |
e6a3ae |
4 files changed, 301 insertions(+), 3 deletions(-)
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c
|
|
Pablo Greco |
e6a3ae |
index 87c6b34..c43e50b 100644
|
|
Pablo Greco |
e6a3ae |
--- a/pc-bios/s390-ccw/cio.c
|
|
Pablo Greco |
e6a3ae |
+++ b/pc-bios/s390-ccw/cio.c
|
|
Pablo Greco |
e6a3ae |
@@ -13,10 +13,14 @@
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
#include "libc.h"
|
|
Pablo Greco |
e6a3ae |
#include "s390-ccw.h"
|
|
Pablo Greco |
e6a3ae |
+#include "s390-arch.h"
|
|
Pablo Greco |
e6a3ae |
+#include "helper.h"
|
|
Pablo Greco |
e6a3ae |
#include "cio.h"
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
+static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb);
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
int enable_mss_facility(void)
|
|
Pablo Greco |
e6a3ae |
{
|
|
Pablo Greco |
e6a3ae |
int ret;
|
|
Pablo Greco |
e6a3ae |
@@ -42,3 +46,143 @@ void enable_subchannel(SubChannelId schid)
|
|
Pablo Greco |
e6a3ae |
schib.pmcw.ena = 1;
|
|
Pablo Greco |
e6a3ae |
msch(schid, &schib);
|
|
Pablo Greco |
e6a3ae |
}
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+uint16_t cu_type(SubChannelId schid)
|
|
Pablo Greco |
e6a3ae |
+{
|
|
Pablo Greco |
e6a3ae |
+ Ccw1 sense_id_ccw;
|
|
Pablo Greco |
e6a3ae |
+ SenseId sense_data;
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ sense_id_ccw.cmd_code = CCW_CMD_SENSE_ID;
|
|
Pablo Greco |
e6a3ae |
+ sense_id_ccw.cda = ptr2u32(&sense_data);
|
|
Pablo Greco |
e6a3ae |
+ sense_id_ccw.count = sizeof(sense_data);
|
|
Pablo Greco |
e6a3ae |
+ sense_id_ccw.flags |= CCW_FLAG_SLI;
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) {
|
|
Pablo Greco |
e6a3ae |
+ panic("Failed to run SenseID CCw\n");
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ return sense_data.cu_type;
|
|
Pablo Greco |
e6a3ae |
+}
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
|
|
Pablo Greco |
e6a3ae |
+ uint16_t data_size)
|
|
Pablo Greco |
e6a3ae |
+{
|
|
Pablo Greco |
e6a3ae |
+ Ccw1 senseCcw;
|
|
Pablo Greco |
e6a3ae |
+ Irb irb;
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ senseCcw.cmd_code = CCW_CMD_BASIC_SENSE;
|
|
Pablo Greco |
e6a3ae |
+ senseCcw.cda = ptr2u32(sense_data);
|
|
Pablo Greco |
e6a3ae |
+ senseCcw.count = data_size;
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb);
|
|
Pablo Greco |
e6a3ae |
+}
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+static bool irb_error(Irb *irb)
|
|
Pablo Greco |
e6a3ae |
+{
|
|
Pablo Greco |
e6a3ae |
+ if (irb->scsw.cstat) {
|
|
Pablo Greco |
e6a3ae |
+ return true;
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+ return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND);
|
|
Pablo Greco |
e6a3ae |
+}
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/*
|
|
Pablo Greco |
e6a3ae |
+ * Handles executing ssch, tsch and returns the irb obtained from tsch.
|
|
Pablo Greco |
e6a3ae |
+ * Returns 0 on success, -1 if unexpected status pending and we need to retry,
|
|
Pablo Greco |
e6a3ae |
+ * otherwise returns condition code from ssch/tsch for error cases.
|
|
Pablo Greco |
e6a3ae |
+ */
|
|
Pablo Greco |
e6a3ae |
+static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb)
|
|
Pablo Greco |
e6a3ae |
+{
|
|
Pablo Greco |
e6a3ae |
+ CmdOrb orb = {};
|
|
Pablo Greco |
e6a3ae |
+ int rc;
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ IPL_assert(fmt == 0 || fmt == 1, "Invalid ccw format");
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ /* ccw_addr must be <= 24 bits and point to at least one whole ccw. */
|
|
Pablo Greco |
e6a3ae |
+ if (fmt == 0) {
|
|
Pablo Greco |
e6a3ae |
+ IPL_assert(ccw_addr <= 0xFFFFFF - 8, "Invalid ccw address");
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ orb.fmt = fmt;
|
|
Pablo Greco |
e6a3ae |
+ orb.pfch = 1; /* QEMU's cio implementation requires prefetch */
|
|
Pablo Greco |
e6a3ae |
+ orb.c64 = 1; /* QEMU's cio implementation requires 64-bit idaws */
|
|
Pablo Greco |
e6a3ae |
+ orb.lpm = 0xFF; /* All paths allowed */
|
|
Pablo Greco |
e6a3ae |
+ orb.cpa = ccw_addr;
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ rc = ssch(schid, &orb;;
|
|
Pablo Greco |
e6a3ae |
+ if (rc == 1 || rc == 2) {
|
|
Pablo Greco |
e6a3ae |
+ /* Subchannel status pending or busy. Eat status and ask for retry. */
|
|
Pablo Greco |
e6a3ae |
+ tsch(schid, irb);
|
|
Pablo Greco |
e6a3ae |
+ return -1;
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+ if (rc) {
|
|
Pablo Greco |
e6a3ae |
+ print_int("ssch failed with cc=", rc);
|
|
Pablo Greco |
e6a3ae |
+ return rc;
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ consume_io_int();
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ /* collect status */
|
|
Pablo Greco |
e6a3ae |
+ rc = tsch(schid, irb);
|
|
Pablo Greco |
e6a3ae |
+ if (rc) {
|
|
Pablo Greco |
e6a3ae |
+ print_int("tsch failed with cc=", rc);
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ return rc;
|
|
Pablo Greco |
e6a3ae |
+}
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/*
|
|
Pablo Greco |
e6a3ae |
+ * Executes a channel program at a given subchannel. The request to run the
|
|
Pablo Greco |
e6a3ae |
+ * channel program is sent to the subchannel, we then wait for the interrupt
|
|
Pablo Greco |
e6a3ae |
+ * signaling completion of the I/O operation(s) performed by the channel
|
|
Pablo Greco |
e6a3ae |
+ * program. Lastly we verify that the i/o operation completed without error and
|
|
Pablo Greco |
e6a3ae |
+ * that the interrupt we received was for the subchannel used to run the
|
|
Pablo Greco |
e6a3ae |
+ * channel program.
|
|
Pablo Greco |
e6a3ae |
+ *
|
|
Pablo Greco |
e6a3ae |
+ * Note: This function assumes it is running in an environment where no other
|
|
Pablo Greco |
e6a3ae |
+ * cpus are generating or receiving I/O interrupts. So either run it in a
|
|
Pablo Greco |
e6a3ae |
+ * single-cpu environment or make sure all other cpus are not doing I/O and
|
|
Pablo Greco |
e6a3ae |
+ * have I/O interrupts masked off. We also assume that only one device is
|
|
Pablo Greco |
e6a3ae |
+ * active (generating i/o interrupts).
|
|
Pablo Greco |
e6a3ae |
+ *
|
|
Pablo Greco |
e6a3ae |
+ * Returns non-zero on error.
|
|
Pablo Greco |
e6a3ae |
+ */
|
|
Pablo Greco |
e6a3ae |
+int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt)
|
|
Pablo Greco |
e6a3ae |
+{
|
|
Pablo Greco |
e6a3ae |
+ Irb irb = {};
|
|
Pablo Greco |
e6a3ae |
+ SenseDataEckdDasd sd;
|
|
Pablo Greco |
e6a3ae |
+ int rc, retries = 0;
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ while (true) {
|
|
Pablo Greco |
e6a3ae |
+ rc = __do_cio(schid, ccw_addr, fmt, &irb);
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ if (rc == -1) {
|
|
Pablo Greco |
e6a3ae |
+ retries++;
|
|
Pablo Greco |
e6a3ae |
+ continue;
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+ if (rc) {
|
|
Pablo Greco |
e6a3ae |
+ /* ssch/tsch error. Message already reported by __do_cio */
|
|
Pablo Greco |
e6a3ae |
+ break;
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ if (!irb_error(&irb)) {
|
|
Pablo Greco |
e6a3ae |
+ break;
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ /*
|
|
Pablo Greco |
e6a3ae |
+ * Unexpected unit check, or interface-control-check. Use sense to
|
|
Pablo Greco |
e6a3ae |
+ * clear (unit check only) then retry.
|
|
Pablo Greco |
e6a3ae |
+ */
|
|
Pablo Greco |
e6a3ae |
+ if ((unit_check(&irb) || iface_ctrl_check(&irb)) && retries <= 2) {
|
|
Pablo Greco |
e6a3ae |
+ if (unit_check(&irb)) {
|
|
Pablo Greco |
e6a3ae |
+ basic_sense(schid, cutype, &sd, sizeof(sd));
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+ retries++;
|
|
Pablo Greco |
e6a3ae |
+ continue;
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ rc = -1;
|
|
Pablo Greco |
e6a3ae |
+ break;
|
|
Pablo Greco |
e6a3ae |
+ }
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+ return rc;
|
|
Pablo Greco |
e6a3ae |
+}
|
|
Pablo Greco |
e6a3ae |
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
|
|
Pablo Greco |
e6a3ae |
index 218fd96..1637e32 100644
|
|
Pablo Greco |
e6a3ae |
--- a/pc-bios/s390-ccw/cio.h
|
|
Pablo Greco |
e6a3ae |
+++ b/pc-bios/s390-ccw/cio.h
|
|
Pablo Greco |
e6a3ae |
@@ -70,9 +70,46 @@ struct scsw {
|
|
Pablo Greco |
e6a3ae |
__u16 count;
|
|
Pablo Greco |
e6a3ae |
} __attribute__ ((packed));
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
-#define SCSW_FCTL_CLEAR_FUNC 0x1000
|
|
Pablo Greco |
e6a3ae |
-#define SCSW_FCTL_HALT_FUNC 0x2000
|
|
Pablo Greco |
e6a3ae |
+/* Function Control */
|
|
Pablo Greco |
e6a3ae |
#define SCSW_FCTL_START_FUNC 0x4000
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_FCTL_HALT_FUNC 0x2000
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_FCTL_CLEAR_FUNC 0x1000
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/* Activity Control */
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_ACTL_RESUME_PEND 0x0800
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_ACTL_START_PEND 0x0400
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_ACTL_HALT_PEND 0x0200
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_ACTL_CLEAR_PEND 0x0100
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_ACTL_CH_ACTIVE 0x0080
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_ACTL_DEV_ACTIVE 0x0040
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_ACTL_SUSPENDED 0x0020
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/* Status Control */
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_SCTL_ALERT 0x0010
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_SCTL_INTERMED 0x0008
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_SCTL_PRIMARY 0x0004
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_SCTL_SECONDARY 0x0002
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_SCTL_STATUS_PEND 0x0001
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/* SCSW Device Status Flags */
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_DSTAT_ATTN 0x80
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_DSTAT_STATMOD 0x40
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_DSTAT_CUEND 0x20
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_DSTAT_BUSY 0x10
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_DSTAT_CHEND 0x08
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_DSTAT_DEVEND 0x04
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_DSTAT_UCHK 0x02
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_DSTAT_UEXCP 0x01
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/* SCSW Subchannel Status Flags */
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_CSTAT_PCINT 0x80
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_CSTAT_BADLEN 0x40
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_CSTAT_PROGCHK 0x20
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_CSTAT_PROTCHK 0x10
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_CSTAT_CHDCHK 0x08
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_CSTAT_CHCCHK 0x04
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_CSTAT_ICCHK 0x02
|
|
Pablo Greco |
e6a3ae |
+#define SCSW_CSTAT_CHAINCHK 0x01
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
/*
|
|
Pablo Greco |
e6a3ae |
* subchannel information block
|
|
Pablo Greco |
e6a3ae |
@@ -127,7 +164,23 @@ struct tpi_info {
|
|
Pablo Greco |
e6a3ae |
__u32 reserved4:12;
|
|
Pablo Greco |
e6a3ae |
} __attribute__ ((packed, aligned(4)));
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
-/* channel command word (type 1) */
|
|
Pablo Greco |
e6a3ae |
+/* channel command word (format 0) */
|
|
Pablo Greco |
e6a3ae |
+typedef struct ccw0 {
|
|
Pablo Greco |
e6a3ae |
+ __u8 cmd_code;
|
|
Pablo Greco |
e6a3ae |
+ __u32 cda:24;
|
|
Pablo Greco |
e6a3ae |
+ __u32 chainData:1;
|
|
Pablo Greco |
e6a3ae |
+ __u32 chain:1;
|
|
Pablo Greco |
e6a3ae |
+ __u32 sli:1;
|
|
Pablo Greco |
e6a3ae |
+ __u32 skip:1;
|
|
Pablo Greco |
e6a3ae |
+ __u32 pci:1;
|
|
Pablo Greco |
e6a3ae |
+ __u32 ida:1;
|
|
Pablo Greco |
e6a3ae |
+ __u32 suspend:1;
|
|
Pablo Greco |
e6a3ae |
+ __u32 mida:1;
|
|
Pablo Greco |
e6a3ae |
+ __u8 reserved;
|
|
Pablo Greco |
e6a3ae |
+ __u16 count;
|
|
Pablo Greco |
e6a3ae |
+} __attribute__ ((packed, aligned(8))) Ccw0;
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/* channel command word (format 1) */
|
|
Pablo Greco |
e6a3ae |
typedef struct ccw1 {
|
|
Pablo Greco |
e6a3ae |
__u8 cmd_code;
|
|
Pablo Greco |
e6a3ae |
__u8 flags;
|
|
Pablo Greco |
e6a3ae |
@@ -135,6 +188,10 @@ typedef struct ccw1 {
|
|
Pablo Greco |
e6a3ae |
__u32 cda;
|
|
Pablo Greco |
e6a3ae |
} __attribute__ ((packed, aligned(8))) Ccw1;
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
+/* do_cio() CCW formats */
|
|
Pablo Greco |
e6a3ae |
+#define CCW_FMT0 0x00
|
|
Pablo Greco |
e6a3ae |
+#define CCW_FMT1 0x01
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
#define CCW_FLAG_DC 0x80
|
|
Pablo Greco |
e6a3ae |
#define CCW_FLAG_CC 0x40
|
|
Pablo Greco |
e6a3ae |
#define CCW_FLAG_SLI 0x20
|
|
Pablo Greco |
e6a3ae |
@@ -190,6 +247,11 @@ struct ciw {
|
|
Pablo Greco |
e6a3ae |
__u16 count;
|
|
Pablo Greco |
e6a3ae |
};
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
+#define CU_TYPE_UNKNOWN 0x0000
|
|
Pablo Greco |
e6a3ae |
+#define CU_TYPE_DASD_2107 0x2107
|
|
Pablo Greco |
e6a3ae |
+#define CU_TYPE_VIRTIO 0x3832
|
|
Pablo Greco |
e6a3ae |
+#define CU_TYPE_DASD_3990 0x3990
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
/*
|
|
Pablo Greco |
e6a3ae |
* sense-id response buffer layout
|
|
Pablo Greco |
e6a3ae |
*/
|
|
Pablo Greco |
e6a3ae |
@@ -205,6 +267,64 @@ typedef struct senseid {
|
|
Pablo Greco |
e6a3ae |
struct ciw ciw[62];
|
|
Pablo Greco |
e6a3ae |
} __attribute__ ((packed, aligned(4))) SenseId;
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
+/*
|
|
Pablo Greco |
e6a3ae |
+ * architected values for first sense byte - common_status. Bits 0-5 of this
|
|
Pablo Greco |
e6a3ae |
+ * field are common to all device types.
|
|
Pablo Greco |
e6a3ae |
+ */
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT0_CMD_REJECT 0x80
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT0_INTERVENTION_REQ 0x40
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT0_BUS_OUT_CHECK 0x20
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT0_EQUIPMENT_CHECK 0x10
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT0_DATA_CHECK 0x08
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT0_OVERRUN 0x04
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT0_INCOMPL_DOMAIN 0x01
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/* ECKD DASD status[0] byte */
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT1_PERM_ERR 0x80
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT1_INV_TRACK_FORMAT 0x40
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT1_EOC 0x20
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT1_MESSAGE_TO_OPER 0x10
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT1_NO_REC_FOUND 0x08
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT1_FILE_PROTECTED 0x04
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT1_WRITE_INHIBITED 0x02
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT1_IMPRECISE_END 0x01
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/* ECKD DASD status[1] byte */
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT2_REQ_INH_WRITE 0x80
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT2_CORRECTABLE 0x40
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT2_FIRST_LOG_ERR 0x20
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT2_ENV_DATA_PRESENT 0x10
|
|
Pablo Greco |
e6a3ae |
+#define SNS_STAT2_IMPRECISE_END 0x04
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/* ECKD DASD 24-byte Sense fmt_msg codes */
|
|
Pablo Greco |
e6a3ae |
+#define SENSE24_FMT_PROG_SYS 0x0
|
|
Pablo Greco |
e6a3ae |
+#define SENSE24_FMT_EQUIPMENT 0x2
|
|
Pablo Greco |
e6a3ae |
+#define SENSE24_FMT_CONTROLLER 0x3
|
|
Pablo Greco |
e6a3ae |
+#define SENSE24_FMT_MISC 0xF
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+/* basic sense response buffer layout */
|
|
Pablo Greco |
e6a3ae |
+typedef struct SenseDataEckdDasd {
|
|
Pablo Greco |
e6a3ae |
+ uint8_t common_status;
|
|
Pablo Greco |
e6a3ae |
+ uint8_t status[2];
|
|
Pablo Greco |
e6a3ae |
+ uint8_t res_count;
|
|
Pablo Greco |
e6a3ae |
+ uint8_t phys_drive_id;
|
|
Pablo Greco |
e6a3ae |
+ uint8_t low_cyl_addr;
|
|
Pablo Greco |
e6a3ae |
+ uint8_t head_high_cyl_addr;
|
|
Pablo Greco |
e6a3ae |
+ uint8_t fmt_msg;
|
|
Pablo Greco |
e6a3ae |
+ uint64_t fmt_dependent_info[2];
|
|
Pablo Greco |
e6a3ae |
+ uint8_t reserved;
|
|
Pablo Greco |
e6a3ae |
+ uint8_t program_action_code;
|
|
Pablo Greco |
e6a3ae |
+ uint16_t config_info;
|
|
Pablo Greco |
e6a3ae |
+ uint8_t mcode_hicyl;
|
|
Pablo Greco |
e6a3ae |
+ uint8_t cyl_head_addr[3];
|
|
Pablo Greco |
e6a3ae |
+} __attribute__ ((packed, aligned(4))) SenseDataEckdDasd;
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+#define ECKD_SENSE24_GET_FMT(sd) (sd->fmt_msg & 0xF0 >> 4)
|
|
Pablo Greco |
e6a3ae |
+#define ECKD_SENSE24_GET_MSG(sd) (sd->fmt_msg & 0x0F)
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
+#define unit_check(irb) ((irb)->scsw.dstat & SCSW_DSTAT_UCHK)
|
|
Pablo Greco |
e6a3ae |
+#define iface_ctrl_check(irb) ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK)
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
/* interruption response block */
|
|
Pablo Greco |
e6a3ae |
typedef struct irb {
|
|
Pablo Greco |
e6a3ae |
struct scsw scsw;
|
|
Pablo Greco |
e6a3ae |
@@ -215,6 +335,10 @@ typedef struct irb {
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
int enable_mss_facility(void);
|
|
Pablo Greco |
e6a3ae |
void enable_subchannel(SubChannelId schid);
|
|
Pablo Greco |
e6a3ae |
+uint16_t cu_type(SubChannelId schid);
|
|
Pablo Greco |
e6a3ae |
+int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
|
|
Pablo Greco |
e6a3ae |
+ uint16_t data_size);
|
|
Pablo Greco |
e6a3ae |
+int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt);
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
/*
|
|
Pablo Greco |
e6a3ae |
* Some S390 specific IO instructions as inline
|
|
Pablo Greco |
e6a3ae |
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
|
|
Pablo Greco |
e6a3ae |
index b39ee5d..11bce7d 100644
|
|
Pablo Greco |
e6a3ae |
--- a/pc-bios/s390-ccw/s390-ccw.h
|
|
Pablo Greco |
e6a3ae |
+++ b/pc-bios/s390-ccw/s390-ccw.h
|
|
Pablo Greco |
e6a3ae |
@@ -52,6 +52,7 @@ typedef unsigned long long __u64;
|
|
Pablo Greco |
e6a3ae |
/* start.s */
|
|
Pablo Greco |
e6a3ae |
void disabled_wait(void);
|
|
Pablo Greco |
e6a3ae |
void consume_sclp_int(void);
|
|
Pablo Greco |
e6a3ae |
+void consume_io_int(void);
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
/* main.c */
|
|
Pablo Greco |
e6a3ae |
void panic(const char *string);
|
|
Pablo Greco |
e6a3ae |
diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S
|
|
Pablo Greco |
e6a3ae |
index eb8d024..fe2a4c3 100644
|
|
Pablo Greco |
e6a3ae |
--- a/pc-bios/s390-ccw/start.S
|
|
Pablo Greco |
e6a3ae |
+++ b/pc-bios/s390-ccw/start.S
|
|
Pablo Greco |
e6a3ae |
@@ -71,6 +71,26 @@ consume_sclp_int:
|
|
Pablo Greco |
e6a3ae |
larl %r1, enabled_wait_psw
|
|
Pablo Greco |
e6a3ae |
lpswe 0(%r1)
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
+/*
|
|
Pablo Greco |
e6a3ae |
+ * void consume_io_int(void)
|
|
Pablo Greco |
e6a3ae |
+ *
|
|
Pablo Greco |
e6a3ae |
+ * eats one I/O interrupt
|
|
Pablo Greco |
e6a3ae |
+ */
|
|
Pablo Greco |
e6a3ae |
+ .globl consume_io_int
|
|
Pablo Greco |
e6a3ae |
+consume_io_int:
|
|
Pablo Greco |
e6a3ae |
+ /* enable I/O interrupts in cr6 */
|
|
Pablo Greco |
e6a3ae |
+ stctg %c6,%c6,0(%r15)
|
|
Pablo Greco |
e6a3ae |
+ oi 4(%r15), 0xff
|
|
Pablo Greco |
e6a3ae |
+ lctlg %c6,%c6,0(%r15)
|
|
Pablo Greco |
e6a3ae |
+ /* prepare i/o call handler */
|
|
Pablo Greco |
e6a3ae |
+ larl %r1, io_new_code
|
|
Pablo Greco |
e6a3ae |
+ stg %r1, 0x1f8
|
|
Pablo Greco |
e6a3ae |
+ larl %r1, io_new_mask
|
|
Pablo Greco |
e6a3ae |
+ mvc 0x1f0(8),0(%r1)
|
|
Pablo Greco |
e6a3ae |
+ /* load enabled wait PSW */
|
|
Pablo Greco |
e6a3ae |
+ larl %r1, enabled_wait_psw
|
|
Pablo Greco |
e6a3ae |
+ lpswe 0(%r1)
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
external_new_code:
|
|
Pablo Greco |
e6a3ae |
/* disable service interrupts in cr0 */
|
|
Pablo Greco |
e6a3ae |
stctg 0,0,0(15)
|
|
Pablo Greco |
e6a3ae |
@@ -78,6 +98,13 @@ external_new_code:
|
|
Pablo Greco |
e6a3ae |
lctlg 0,0,0(15)
|
|
Pablo Greco |
e6a3ae |
br 14
|
|
Pablo Greco |
e6a3ae |
|
|
Pablo Greco |
e6a3ae |
+io_new_code:
|
|
Pablo Greco |
e6a3ae |
+ /* disable I/O interrupts in cr6 */
|
|
Pablo Greco |
e6a3ae |
+ stctg %c6,%c6,0(%r15)
|
|
Pablo Greco |
e6a3ae |
+ ni 4(%r15), 0x00
|
|
Pablo Greco |
e6a3ae |
+ lctlg %c6,%c6,0(%r15)
|
|
Pablo Greco |
e6a3ae |
+ br %r14
|
|
Pablo Greco |
e6a3ae |
+
|
|
Pablo Greco |
e6a3ae |
.align 8
|
|
Pablo Greco |
e6a3ae |
disabled_wait_psw:
|
|
Pablo Greco |
e6a3ae |
.quad 0x0002000180000000,0x0000000000000000
|
|
Pablo Greco |
e6a3ae |
@@ -85,3 +112,5 @@ enabled_wait_psw:
|
|
Pablo Greco |
e6a3ae |
.quad 0x0302000180000000,0x0000000000000000
|
|
Pablo Greco |
e6a3ae |
external_new_mask:
|
|
Pablo Greco |
e6a3ae |
.quad 0x0000000180000000
|
|
Pablo Greco |
e6a3ae |
+io_new_mask:
|
|
Pablo Greco |
e6a3ae |
+ .quad 0x0000000180000000
|
|
Pablo Greco |
e6a3ae |
--
|
|
Pablo Greco |
e6a3ae |
1.8.3.1
|
|
Pablo Greco |
e6a3ae |
|