diff mbox

[RFC,v2,3/8] pc-bios/s390-ccw: Move virtio-block related functions into a separate file

Message ID 1499423224-23060-4-git-send-email-thuth@redhat.com
State New
Headers show

Commit Message

Thomas Huth July 7, 2017, 10:26 a.m. UTC
The netboot code is going to link against the code from virtio.c, too,
so we've got to move the virtio-block related code out of the way.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/Makefile     |   2 +-
 pc-bios/s390-ccw/main.c       |   2 +-
 pc-bios/s390-ccw/s390-ccw.h   |   2 +-
 pc-bios/s390-ccw/virtio-blk.c | 296 ++++++++++++++++++++++++++++++++++++++++++
 pc-bios/s390-ccw/virtio.c     | 273 +-------------------------------------
 pc-bios/s390-ccw/virtio.h     |   4 +
 6 files changed, 307 insertions(+), 272 deletions(-)
 create mode 100644 pc-bios/s390-ccw/virtio-blk.c

Comments

Cornelia Huck July 7, 2017, 12:54 p.m. UTC | #1
On Fri,  7 Jul 2017 12:26:59 +0200
Thomas Huth <thuth@redhat.com> wrote:

> The netboot code is going to link against the code from virtio.c, too,
> so we've got to move the virtio-block related code out of the way.
> 
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
>  pc-bios/s390-ccw/Makefile     |   2 +-
>  pc-bios/s390-ccw/main.c       |   2 +-
>  pc-bios/s390-ccw/s390-ccw.h   |   2 +-
>  pc-bios/s390-ccw/virtio-blk.c | 296 ++++++++++++++++++++++++++++++++++++++++++
>  pc-bios/s390-ccw/virtio.c     | 273 +-------------------------------------
>  pc-bios/s390-ccw/virtio.h     |   4 +
>  6 files changed, 307 insertions(+), 272 deletions(-)
>  create mode 100644 pc-bios/s390-ccw/virtio-blk.c
> 

> diff --git a/pc-bios/s390-ccw/virtio-blk.c b/pc-bios/s390-ccw/virtio-blk.c
> new file mode 100644
> index 0000000..6cb77bc
> --- /dev/null
> +++ b/pc-bios/s390-ccw/virtio-blk.c
> @@ -0,0 +1,296 @@
> +/*
> + * Virtio driver bits
> + *
> + * Copyright (c) 2013 Alexander Graf <agraf@suse.de>

The original code carries the same copyright notice, but there's a lot
of IBM code in there. Just saying.

> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or (at
> + * your option) any later version. See the COPYING file in the top-level
> + * directory.
> + */
> +
> +#include "libc.h"
> +#include "s390-ccw.h"
> +#include "virtio.h"
> +#include "virtio-scsi.h"
> +
> +static int virtio_blk_read_many(VDev *vdev,
> +                                ulong sector, void *load_addr, int sec_num)
> +{
> +    VirtioBlkOuthdr out_hdr;
> +    u8 status;
> +    VRing *vr = &vdev->vrings[vdev->cmd_vr_idx];
> +
> +    /* Tell the host we want to read */
> +    out_hdr.type = VIRTIO_BLK_T_IN;
> +    out_hdr.ioprio = 99;
> +    out_hdr.sector = virtio_sector_adjust(sector);
> +
> +    vring_send_buf(vr, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
> +
> +    /* This is where we want to receive data */
> +    vring_send_buf(vr, load_addr, virtio_get_block_size() * sec_num,
> +                   VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
> +                   VRING_DESC_F_NEXT);
> +
> +    /* status field */
> +    vring_send_buf(vr, &status, sizeof(u8),
> +                   VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN);
> +
> +    /* Now we can tell the host to read */
> +    vring_wait_reply();
> +
> +    if (drain_irqs(vr->schid)) {
> +        /* Well, whatever status is supposed to contain... */
> +        status = 1;
> +    }
> +    return status;
> +}
> +
> +int virtio_read_many(ulong sector, void *load_addr, int sec_num)
> +{
> +    VDev *vdev = virtio_get_device();
> +
> +    switch (vdev->senseid.cu_model) {
> +    case VIRTIO_ID_BLOCK:
> +        return virtio_blk_read_many(vdev, sector, load_addr, sec_num);
> +    case VIRTIO_ID_SCSI:
> +        return virtio_scsi_read_many(vdev, sector, load_addr, sec_num);

This is scsi, not blk. Should virtio_read_many() stay in virtio.c?

> +    }
> +    panic("\n! No readable IPL device !\n");
> +    return -1;
> +}

(...)

> +void virtio_assume_scsi(void)
> +{
> +    VDev *vdev = virtio_get_device();
> +
> +    switch (vdev->senseid.cu_model) {
> +    case VIRTIO_ID_BLOCK:
> +        vdev->guessed_disk_nature = VIRTIO_GDN_SCSI;
> +        vdev->config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE;
> +        vdev->config.blk.physical_block_exp = 0;
> +        vdev->blk_factor = 1;
> +        break;
> +    case VIRTIO_ID_SCSI:
> +        vdev->scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE;

More scsi. Maybe the file just needs a different name :)

> +        break;
> +    }
> +}

General ack on splitting out this code.
Thomas Huth July 7, 2017, 1:04 p.m. UTC | #2
On 07.07.2017 14:54, Cornelia Huck wrote:
> On Fri,  7 Jul 2017 12:26:59 +0200
> Thomas Huth <thuth@redhat.com> wrote:
> 
>> The netboot code is going to link against the code from virtio.c, too,
>> so we've got to move the virtio-block related code out of the way.
>>
>> Signed-off-by: Thomas Huth <thuth@redhat.com>
>> ---
>>  pc-bios/s390-ccw/Makefile     |   2 +-
>>  pc-bios/s390-ccw/main.c       |   2 +-
>>  pc-bios/s390-ccw/s390-ccw.h   |   2 +-
>>  pc-bios/s390-ccw/virtio-blk.c | 296 ++++++++++++++++++++++++++++++++++++++++++
>>  pc-bios/s390-ccw/virtio.c     | 273 +-------------------------------------
>>  pc-bios/s390-ccw/virtio.h     |   4 +
>>  6 files changed, 307 insertions(+), 272 deletions(-)
>>  create mode 100644 pc-bios/s390-ccw/virtio-blk.c
>>
> 
>> diff --git a/pc-bios/s390-ccw/virtio-blk.c b/pc-bios/s390-ccw/virtio-blk.c
>> new file mode 100644
>> index 0000000..6cb77bc
>> --- /dev/null
>> +++ b/pc-bios/s390-ccw/virtio-blk.c
>> @@ -0,0 +1,296 @@
>> +/*
>> + * Virtio driver bits
>> + *
>> + * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
> 
> The original code carries the same copyright notice, but there's a lot
> of IBM code in there. Just saying.

Then the IBM folks should maybe add their (c) statement to that file
first? Otherwise, I assume they simply do not care ;-)

[...]
>> +int virtio_read_many(ulong sector, void *load_addr, int sec_num)
>> +{
>> +    VDev *vdev = virtio_get_device();
>> +
>> +    switch (vdev->senseid.cu_model) {
>> +    case VIRTIO_ID_BLOCK:
>> +        return virtio_blk_read_many(vdev, sector, load_addr, sec_num);
>> +    case VIRTIO_ID_SCSI:
>> +        return virtio_scsi_read_many(vdev, sector, load_addr, sec_num);
> 
> This is scsi, not blk. Should virtio_read_many() stay in virtio.c?

No, that does not work since virtio_scsi_read_many() is defined in
virtio-scsi.c which is not linked to the netboot code.

>> +    }
>> +    panic("\n! No readable IPL device !\n");
>> +    return -1;
>> +}
> (...)
>> +void virtio_assume_scsi(void)
>> +{
>> +    VDev *vdev = virtio_get_device();
>> +
>> +    switch (vdev->senseid.cu_model) {
>> +    case VIRTIO_ID_BLOCK:
>> +        vdev->guessed_disk_nature = VIRTIO_GDN_SCSI;
>> +        vdev->config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE;
>> +        vdev->config.blk.physical_block_exp = 0;
>> +        vdev->blk_factor = 1;
>> +        break;
>> +    case VIRTIO_ID_SCSI:
>> +        vdev->scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE;
> 
> More scsi. Maybe the file just needs a different name :)

Do you have a better suggestion?

 Thomas
Cornelia Huck July 7, 2017, 1:06 p.m. UTC | #3
On Fri, 7 Jul 2017 15:04:55 +0200
Thomas Huth <thuth@redhat.com> wrote:

> On 07.07.2017 14:54, Cornelia Huck wrote:
> > On Fri,  7 Jul 2017 12:26:59 +0200
> > Thomas Huth <thuth@redhat.com> wrote:

> >> +void virtio_assume_scsi(void)
> >> +{
> >> +    VDev *vdev = virtio_get_device();
> >> +
> >> +    switch (vdev->senseid.cu_model) {
> >> +    case VIRTIO_ID_BLOCK:
> >> +        vdev->guessed_disk_nature = VIRTIO_GDN_SCSI;
> >> +        vdev->config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE;
> >> +        vdev->config.blk.physical_block_exp = 0;
> >> +        vdev->blk_factor = 1;
> >> +        break;
> >> +    case VIRTIO_ID_SCSI:
> >> +        vdev->scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE;  
> > 
> > More scsi. Maybe the file just needs a different name :)  
> 
> Do you have a better suggestion?

virtio-blockdev.c ?
diff mbox

Patch

diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index fb88c13..4abe7d3 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -9,7 +9,7 @@  $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
 
 .PHONY : all clean build-all
 
-OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o
+OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blk.o
 QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
 QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
 QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 0580eac..401e9db 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -144,7 +144,7 @@  static void virtio_setup(void)
         sclp_print("Network boot device detected\n");
         vdev->netboot_start_addr = iplb.ccw.netboot_start_addr;
     } else {
-        virtio_setup_device(blk_schid);
+        virtio_blk_setup_device(blk_schid);
 
         IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected");
     }
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 43e2d42..6fdc858 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -74,7 +74,7 @@  void sclp_get_loadparm_ascii(char *loadparm);
 unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
                                  ulong subchan_id, void *load_addr);
 bool virtio_is_supported(SubChannelId schid);
-void virtio_setup_device(SubChannelId schid);
+void virtio_blk_setup_device(SubChannelId schid);
 int virtio_read(ulong sector, void *load_addr);
 int enable_mss_facility(void);
 ulong get_second(void);
diff --git a/pc-bios/s390-ccw/virtio-blk.c b/pc-bios/s390-ccw/virtio-blk.c
new file mode 100644
index 0000000..6cb77bc
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio-blk.c
@@ -0,0 +1,296 @@ 
+/*
+ * Virtio driver bits
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "libc.h"
+#include "s390-ccw.h"
+#include "virtio.h"
+#include "virtio-scsi.h"
+
+static int virtio_blk_read_many(VDev *vdev,
+                                ulong sector, void *load_addr, int sec_num)
+{
+    VirtioBlkOuthdr out_hdr;
+    u8 status;
+    VRing *vr = &vdev->vrings[vdev->cmd_vr_idx];
+
+    /* Tell the host we want to read */
+    out_hdr.type = VIRTIO_BLK_T_IN;
+    out_hdr.ioprio = 99;
+    out_hdr.sector = virtio_sector_adjust(sector);
+
+    vring_send_buf(vr, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
+
+    /* This is where we want to receive data */
+    vring_send_buf(vr, load_addr, virtio_get_block_size() * sec_num,
+                   VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
+                   VRING_DESC_F_NEXT);
+
+    /* status field */
+    vring_send_buf(vr, &status, sizeof(u8),
+                   VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN);
+
+    /* Now we can tell the host to read */
+    vring_wait_reply();
+
+    if (drain_irqs(vr->schid)) {
+        /* Well, whatever status is supposed to contain... */
+        status = 1;
+    }
+    return status;
+}
+
+int virtio_read_many(ulong sector, void *load_addr, int sec_num)
+{
+    VDev *vdev = virtio_get_device();
+
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        return virtio_blk_read_many(vdev, sector, load_addr, sec_num);
+    case VIRTIO_ID_SCSI:
+        return virtio_scsi_read_many(vdev, sector, load_addr, sec_num);
+    }
+    panic("\n! No readable IPL device !\n");
+    return -1;
+}
+
+unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
+                                 ulong subchan_id, void *load_addr)
+{
+    u8 status;
+    int sec = rec_list1;
+    int sec_num = ((rec_list2 >> 32) & 0xffff) + 1;
+    int sec_len = rec_list2 >> 48;
+    ulong addr = (ulong)load_addr;
+
+    if (sec_len != virtio_get_block_size()) {
+        return -1;
+    }
+
+    sclp_print(".");
+    status = virtio_read_many(sec, (void *)addr, sec_num);
+    if (status) {
+        panic("I/O Error");
+    }
+    addr += sec_num * virtio_get_block_size();
+
+    return addr;
+}
+
+int virtio_read(ulong sector, void *load_addr)
+{
+    return virtio_read_many(sector, load_addr, 1);
+}
+
+/*
+ * Other supported value pairs, if any, would need to be added here.
+ * Note: head count is always 15.
+ */
+static inline u8 virtio_eckd_sectors_for_block_size(int size)
+{
+    switch (size) {
+    case 512:
+        return 49;
+    case 1024:
+        return 33;
+    case 2048:
+        return 21;
+    case 4096:
+        return 12;
+    }
+    return 0;
+}
+
+VirtioGDN virtio_guessed_disk_nature(void)
+{
+    return virtio_get_device()->guessed_disk_nature;
+}
+
+void virtio_assume_scsi(void)
+{
+    VDev *vdev = virtio_get_device();
+
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        vdev->guessed_disk_nature = VIRTIO_GDN_SCSI;
+        vdev->config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE;
+        vdev->config.blk.physical_block_exp = 0;
+        vdev->blk_factor = 1;
+        break;
+    case VIRTIO_ID_SCSI:
+        vdev->scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE;
+        break;
+    }
+}
+
+void virtio_assume_iso9660(void)
+{
+    VDev *vdev = virtio_get_device();
+
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        vdev->guessed_disk_nature = VIRTIO_GDN_SCSI;
+        vdev->config.blk.blk_size = VIRTIO_ISO_BLOCK_SIZE;
+        vdev->config.blk.physical_block_exp = 0;
+        vdev->blk_factor = VIRTIO_ISO_BLOCK_SIZE / VIRTIO_SECTOR_SIZE;
+        break;
+    case VIRTIO_ID_SCSI:
+        vdev->scsi_block_size = VIRTIO_ISO_BLOCK_SIZE;
+        break;
+    }
+}
+
+void virtio_assume_eckd(void)
+{
+    VDev *vdev = virtio_get_device();
+
+    vdev->guessed_disk_nature = VIRTIO_GDN_DASD;
+    vdev->blk_factor = 1;
+    vdev->config.blk.physical_block_exp = 0;
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        vdev->config.blk.blk_size = 4096;
+        break;
+    case VIRTIO_ID_SCSI:
+        vdev->config.blk.blk_size = vdev->scsi_block_size;
+        break;
+    }
+    vdev->config.blk.geometry.heads = 15;
+    vdev->config.blk.geometry.sectors =
+        virtio_eckd_sectors_for_block_size(vdev->config.blk.blk_size);
+}
+
+bool virtio_disk_is_scsi(void)
+{
+    VDev *vdev = virtio_get_device();
+
+    if (vdev->guessed_disk_nature == VIRTIO_GDN_SCSI) {
+        return true;
+    }
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        return (vdev->config.blk.geometry.heads == 255)
+            && (vdev->config.blk.geometry.sectors == 63)
+            && (virtio_get_block_size()  == VIRTIO_SCSI_BLOCK_SIZE);
+    case VIRTIO_ID_SCSI:
+        return true;
+    }
+    return false;
+}
+
+bool virtio_disk_is_eckd(void)
+{
+    VDev *vdev = virtio_get_device();
+    const int block_size = virtio_get_block_size();
+
+    if (vdev->guessed_disk_nature == VIRTIO_GDN_DASD) {
+        return true;
+    }
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        return (vdev->config.blk.geometry.heads == 15)
+            && (vdev->config.blk.geometry.sectors ==
+                virtio_eckd_sectors_for_block_size(block_size));
+    case VIRTIO_ID_SCSI:
+        return false;
+    }
+    return false;
+}
+
+bool virtio_ipl_disk_is_valid(void)
+{
+    return virtio_disk_is_scsi() || virtio_disk_is_eckd();
+}
+
+int virtio_get_block_size(void)
+{
+    VDev *vdev = virtio_get_device();
+
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        return vdev->config.blk.blk_size << vdev->config.blk.physical_block_exp;
+    case VIRTIO_ID_SCSI:
+        return vdev->scsi_block_size;
+    }
+    return 0;
+}
+
+uint8_t virtio_get_heads(void)
+{
+    VDev *vdev = virtio_get_device();
+
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        return vdev->config.blk.geometry.heads;
+    case VIRTIO_ID_SCSI:
+        return vdev->guessed_disk_nature == VIRTIO_GDN_DASD
+               ? vdev->config.blk.geometry.heads : 255;
+    }
+    return 0;
+}
+
+uint8_t virtio_get_sectors(void)
+{
+    VDev *vdev = virtio_get_device();
+
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        return vdev->config.blk.geometry.sectors;
+    case VIRTIO_ID_SCSI:
+        return vdev->guessed_disk_nature == VIRTIO_GDN_DASD
+               ? vdev->config.blk.geometry.sectors : 63;
+    }
+    return 0;
+}
+
+uint64_t virtio_get_blocks(void)
+{
+    VDev *vdev = virtio_get_device();
+    const uint64_t factor = virtio_get_block_size() / VIRTIO_SECTOR_SIZE;
+
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        return vdev->config.blk.capacity / factor;
+    case VIRTIO_ID_SCSI:
+        return vdev->scsi_last_block / factor;
+    }
+    return 0;
+}
+
+void virtio_blk_setup_device(SubChannelId schid)
+{
+    VDev *vdev = virtio_get_device();
+
+    vdev->schid = schid;
+    virtio_setup_ccw(vdev);
+
+    switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_BLOCK:
+        sclp_print("Using virtio-blk.\n");
+        if (!virtio_ipl_disk_is_valid()) {
+            /* make sure all getters but blocksize return 0 for
+             * invalid IPL disk
+             */
+            memset(&vdev->config.blk, 0, sizeof(vdev->config.blk));
+            virtio_assume_scsi();
+        }
+        break;
+    case VIRTIO_ID_SCSI:
+        IPL_assert(vdev->config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE,
+            "Config: sense size mismatch");
+        IPL_assert(vdev->config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE,
+            "Config: CDB size mismatch");
+
+        sclp_print("Using virtio-scsi.\n");
+        virtio_scsi_setup(vdev);
+        break;
+    default:
+        panic("\n! No IPL device available !\n");
+    }
+}
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 8768331..09ab291 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -70,7 +70,7 @@  static long virtio_notify(SubChannelId schid, int vq_idx, long cookie)
  *             Virtio functions                *
  ***********************************************/
 
-static int drain_irqs(SubChannelId schid)
+int drain_irqs(SubChannelId schid)
 {
     Irb irb = {};
     int r = 0;
@@ -155,7 +155,7 @@  static bool vring_notify(VRing *vr)
     return vr->cookie >= 0;
 }
 
-static void vring_send_buf(VRing *vr, void *p, int len, int flags)
+void vring_send_buf(VRing *vr, void *p, int len, int flags)
 {
     /* For follow-up chains we need to keep the first entry point */
     if (!(flags & VRING_HIDDEN_IS_CHAIN)) {
@@ -210,7 +210,7 @@  static int vr_poll(VRing *vr)
  *
  * Returns 0 on success, 1 on timeout.
  */
-static int vring_wait_reply(void)
+int vring_wait_reply(void)
 {
     ulong target_second = get_second() + vdev.wait_reply_timeout;
 
@@ -247,242 +247,7 @@  int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd)
     return 0;
 }
 
-/***********************************************
- *               Virtio block                  *
- ***********************************************/
-
-static int virtio_blk_read_many(VDev *vdev,
-                                ulong sector, void *load_addr, int sec_num)
-{
-    VirtioBlkOuthdr out_hdr;
-    u8 status;
-    VRing *vr = &vdev->vrings[vdev->cmd_vr_idx];
-
-    /* Tell the host we want to read */
-    out_hdr.type = VIRTIO_BLK_T_IN;
-    out_hdr.ioprio = 99;
-    out_hdr.sector = virtio_sector_adjust(sector);
-
-    vring_send_buf(vr, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
-
-    /* This is where we want to receive data */
-    vring_send_buf(vr, load_addr, virtio_get_block_size() * sec_num,
-                   VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
-                   VRING_DESC_F_NEXT);
-
-    /* status field */
-    vring_send_buf(vr, &status, sizeof(u8),
-                   VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN);
-
-    /* Now we can tell the host to read */
-    vring_wait_reply();
-
-    if (drain_irqs(vr->schid)) {
-        /* Well, whatever status is supposed to contain... */
-        status = 1;
-    }
-    return status;
-}
-
-int virtio_read_many(ulong sector, void *load_addr, int sec_num)
-{
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        return virtio_blk_read_many(&vdev, sector, load_addr, sec_num);
-    case VIRTIO_ID_SCSI:
-        return virtio_scsi_read_many(&vdev, sector, load_addr, sec_num);
-    }
-    panic("\n! No readable IPL device !\n");
-    return -1;
-}
-
-unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
-                                 ulong subchan_id, void *load_addr)
-{
-    u8 status;
-    int sec = rec_list1;
-    int sec_num = ((rec_list2 >> 32) & 0xffff) + 1;
-    int sec_len = rec_list2 >> 48;
-    ulong addr = (ulong)load_addr;
-
-    if (sec_len != virtio_get_block_size()) {
-        return -1;
-    }
-
-    sclp_print(".");
-    status = virtio_read_many(sec, (void *)addr, sec_num);
-    if (status) {
-        panic("I/O Error");
-    }
-    addr += sec_num * virtio_get_block_size();
-
-    return addr;
-}
-
-int virtio_read(ulong sector, void *load_addr)
-{
-    return virtio_read_many(sector, load_addr, 1);
-}
-
-/*
- * Other supported value pairs, if any, would need to be added here.
- * Note: head count is always 15.
- */
-static inline u8 virtio_eckd_sectors_for_block_size(int size)
-{
-    switch (size) {
-    case 512:
-        return 49;
-    case 1024:
-        return 33;
-    case 2048:
-        return 21;
-    case 4096:
-        return 12;
-    }
-    return 0;
-}
-
-VirtioGDN virtio_guessed_disk_nature(void)
-{
-    return vdev.guessed_disk_nature;
-}
-
-void virtio_assume_scsi(void)
-{
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        vdev.guessed_disk_nature = VIRTIO_GDN_SCSI;
-        vdev.config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE;
-        vdev.config.blk.physical_block_exp = 0;
-        vdev.blk_factor = 1;
-        break;
-    case VIRTIO_ID_SCSI:
-        vdev.scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE;
-        break;
-    }
-}
-
-void virtio_assume_iso9660(void)
-{
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        vdev.guessed_disk_nature = VIRTIO_GDN_SCSI;
-        vdev.config.blk.blk_size = VIRTIO_ISO_BLOCK_SIZE;
-        vdev.config.blk.physical_block_exp = 0;
-        vdev.blk_factor = VIRTIO_ISO_BLOCK_SIZE / VIRTIO_SECTOR_SIZE;
-        break;
-    case VIRTIO_ID_SCSI:
-        vdev.scsi_block_size = VIRTIO_ISO_BLOCK_SIZE;
-        break;
-    }
-}
-
-void virtio_assume_eckd(void)
-{
-    vdev.guessed_disk_nature = VIRTIO_GDN_DASD;
-    vdev.blk_factor = 1;
-    vdev.config.blk.physical_block_exp = 0;
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        vdev.config.blk.blk_size = 4096;
-        break;
-    case VIRTIO_ID_SCSI:
-        vdev.config.blk.blk_size = vdev.scsi_block_size;
-        break;
-    }
-    vdev.config.blk.geometry.heads = 15;
-    vdev.config.blk.geometry.sectors =
-        virtio_eckd_sectors_for_block_size(vdev.config.blk.blk_size);
-}
-
-bool virtio_disk_is_scsi(void)
-{
-    if (vdev.guessed_disk_nature == VIRTIO_GDN_SCSI) {
-        return true;
-    }
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        return (vdev.config.blk.geometry.heads == 255)
-            && (vdev.config.blk.geometry.sectors == 63)
-            && (virtio_get_block_size()  == VIRTIO_SCSI_BLOCK_SIZE);
-    case VIRTIO_ID_SCSI:
-        return true;
-    }
-    return false;
-}
-
-bool virtio_disk_is_eckd(void)
-{
-    const int block_size = virtio_get_block_size();
-
-    if (vdev.guessed_disk_nature == VIRTIO_GDN_DASD) {
-        return true;
-    }
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        return (vdev.config.blk.geometry.heads == 15)
-            && (vdev.config.blk.geometry.sectors ==
-                virtio_eckd_sectors_for_block_size(block_size));
-    case VIRTIO_ID_SCSI:
-        return false;
-    }
-    return false;
-}
-
-bool virtio_ipl_disk_is_valid(void)
-{
-    return virtio_disk_is_scsi() || virtio_disk_is_eckd();
-}
-
-int virtio_get_block_size(void)
-{
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        return vdev.config.blk.blk_size << vdev.config.blk.physical_block_exp;
-    case VIRTIO_ID_SCSI:
-        return vdev.scsi_block_size;
-    }
-    return 0;
-}
-
-uint8_t virtio_get_heads(void)
-{
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        return vdev.config.blk.geometry.heads;
-    case VIRTIO_ID_SCSI:
-        return vdev.guessed_disk_nature == VIRTIO_GDN_DASD
-               ? vdev.config.blk.geometry.heads : 255;
-    }
-    return 0;
-}
-
-uint8_t virtio_get_sectors(void)
-{
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        return vdev.config.blk.geometry.sectors;
-    case VIRTIO_ID_SCSI:
-        return vdev.guessed_disk_nature == VIRTIO_GDN_DASD
-               ? vdev.config.blk.geometry.sectors : 63;
-    }
-    return 0;
-}
-
-uint64_t virtio_get_blocks(void)
-{
-    const uint64_t factor = virtio_get_block_size() / VIRTIO_SECTOR_SIZE;
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        return vdev.config.blk.capacity / factor;
-    case VIRTIO_ID_SCSI:
-        return vdev.scsi_last_block / factor;
-    }
-    return 0;
-}
-
-static void virtio_setup_ccw(VDev *vdev)
+void virtio_setup_ccw(VDev *vdev)
 {
     int i, cfg_size = 0;
     unsigned char status = VIRTIO_CONFIG_S_DRIVER_OK;
@@ -544,36 +309,6 @@  static void virtio_setup_ccw(VDev *vdev)
         "Could not write status to host");
 }
 
-void virtio_setup_device(SubChannelId schid)
-{
-    vdev.schid = schid;
-    virtio_setup_ccw(&vdev);
-
-    switch (vdev.senseid.cu_model) {
-    case VIRTIO_ID_BLOCK:
-        sclp_print("Using virtio-blk.\n");
-        if (!virtio_ipl_disk_is_valid()) {
-            /* make sure all getters but blocksize return 0 for
-             * invalid IPL disk
-             */
-            memset(&vdev.config.blk, 0, sizeof(vdev.config.blk));
-            virtio_assume_scsi();
-        }
-        break;
-    case VIRTIO_ID_SCSI:
-        IPL_assert(vdev.config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE,
-            "Config: sense size mismatch");
-        IPL_assert(vdev.config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE,
-            "Config: CDB size mismatch");
-
-        sclp_print("Using virtio-scsi.\n");
-        virtio_scsi_setup(&vdev);
-        break;
-    default:
-        panic("\n! No IPL device available !\n");
-    }
-}
-
 bool virtio_is_supported(SubChannelId schid)
 {
     vdev.schid = schid;
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
index 1eaf865..d743919 100644
--- a/pc-bios/s390-ccw/virtio.h
+++ b/pc-bios/s390-ccw/virtio.h
@@ -291,6 +291,10 @@  struct VirtioCmd {
 };
 typedef struct VirtioCmd VirtioCmd;
 
+int drain_irqs(SubChannelId schid);
+void vring_send_buf(VRing *vr, void *p, int len, int flags);
+int vring_wait_reply(void);
 int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd);
+void virtio_setup_ccw(VDev *vdev);
 
 #endif /* VIRTIO_H */