diff options
-rw-r--r-- | pc-bios/s390-ccw/main.c | 4 | ||||
-rw-r--r-- | pc-bios/s390-ccw/s390-ccw.h | 4 | ||||
-rw-r--r-- | pc-bios/s390-ccw/virtio.c | 130 | ||||
-rw-r--r-- | pc-bios/s390-ccw/virtio.h | 12 |
4 files changed, 106 insertions, 44 deletions
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index 6bf44a7fa0..69a02feb87 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -50,7 +50,7 @@ static bool find_dev(Schib *schib, int dev_no) if (!schib->pmcw.dnv) { continue; } - if (!virtio_is_blk(blk_schid)) { + if (!virtio_is_supported(blk_schid)) { continue; } if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) { @@ -95,7 +95,7 @@ static void virtio_setup(uint64_t dev_info) panic("No virtio-blk device found!\n"); } - virtio_setup_block(blk_schid); + virtio_setup_device(blk_schid); if (!virtio_ipl_disk_is_valid()) { panic("No valid hard disk detected.\n"); diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h index 3e00d42eb8..616d96738d 100644 --- a/pc-bios/s390-ccw/s390-ccw.h +++ b/pc-bios/s390-ccw/s390-ccw.h @@ -70,8 +70,8 @@ void sclp_setup(void); /* virtio.c */ unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, ulong subchan_id, void *load_addr); -bool virtio_is_blk(SubChannelId schid); -void virtio_setup_block(SubChannelId schid); +bool virtio_is_supported(SubChannelId schid); +void virtio_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.c b/pc-bios/s390-ccw/virtio.c index 6bf0c38d87..56734aff44 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -25,7 +25,6 @@ static VDev vdev = { .cmd_vr_idx = 0, .ring_area = ring_area, .wait_reply_timeout = VRING_WAIT_REPLY_TIMEOUT, - .guessed_disk_nature = false, .schid = { .one = 1 }, }; @@ -230,11 +229,12 @@ static int vring_wait_reply(void) * Virtio block * ***********************************************/ -int virtio_read_many(ulong sector, void *load_addr, int sec_num) +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]; + VRing *vr = &vdev->vrings[vdev->cmd_vr_idx]; /* Tell the host we want to read */ out_hdr.type = VIRTIO_BLK_T_IN; @@ -262,6 +262,16 @@ int virtio_read_many(ulong sector, void *load_addr, int sec_num) 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); + } + 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) { @@ -290,44 +300,60 @@ int virtio_read(ulong sector, void *load_addr) return virtio_read_many(sector, load_addr, 1); } -bool virtio_guessed_disk_nature(void) +VirtioGDN virtio_guessed_disk_nature(void) { return vdev.guessed_disk_nature; } void virtio_assume_scsi(void) { - vdev.guessed_disk_nature = true; - vdev.config.blk.blk_size = 512; - vdev.config.blk.physical_block_exp = 0; + vdev.guessed_disk_nature = VIRTIO_GDN_SCSI; + switch (vdev.senseid.cu_model) { + case VIRTIO_ID_BLOCK: + vdev.config.blk.blk_size = 512; + vdev.config.blk.physical_block_exp = 0; + break; + } } void virtio_assume_iso9660(void) { - vdev.guessed_disk_nature = true; - vdev.config.blk.blk_size = 2048; - vdev.config.blk.physical_block_exp = 0; + vdev.guessed_disk_nature = VIRTIO_GDN_CDROM; + switch (vdev.senseid.cu_model) { + case VIRTIO_ID_BLOCK: + vdev.config.blk.blk_size = 2048; + vdev.config.blk.physical_block_exp = 0; + break; + } } void virtio_assume_eckd(void) { - vdev.guessed_disk_nature = true; - vdev.config.blk.blk_size = 4096; - vdev.config.blk.physical_block_exp = 0; + vdev.guessed_disk_nature = VIRTIO_GDN_DASD; + switch (vdev.senseid.cu_model) { + case VIRTIO_ID_BLOCK: + vdev.config.blk.blk_size = 4096; + vdev.config.blk.physical_block_exp = 0; - /* this must be here to calculate code segment position */ - vdev.config.blk.geometry.heads = 15; - vdev.config.blk.geometry.sectors = 12; + /* this must be here to calculate code segment position */ + vdev.config.blk.geometry.heads = 15; + vdev.config.blk.geometry.sectors = 12; + break; + } } bool virtio_disk_is_scsi(void) { - if (vdev.guessed_disk_nature) { - return (virtio_get_block_size() == 512); + 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() == 512); } - return (vdev.config.blk.geometry.heads == 255) - && (vdev.config.blk.geometry.sectors == 63) - && (virtio_get_block_size() == 512); + return false; } /* @@ -353,12 +379,16 @@ bool virtio_disk_is_eckd(void) { const int block_size = virtio_get_block_size(); - if (vdev.guessed_disk_nature) { - return (block_size == 4096); + if (vdev.guessed_disk_nature == VIRTIO_GDN_DASD) { + return true; } - return (vdev.config.blk.geometry.heads == 15) - && (vdev.config.blk.geometry.sectors == - virtio_eckd_sectors_for_block_size(block_size)); + 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)); + } + return false; } bool virtio_ipl_disk_is_valid(void) @@ -368,23 +398,39 @@ bool virtio_ipl_disk_is_valid(void) int virtio_get_block_size(void) { - return vdev.config.blk.blk_size << vdev.config.blk.physical_block_exp; + switch (vdev.senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return vdev.config.blk.blk_size << vdev.config.blk.physical_block_exp; + } + return 0; } uint8_t virtio_get_heads(void) { - return vdev.config.blk.geometry.heads; + switch (vdev.senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return vdev.config.blk.geometry.heads; + } + return 0; } uint8_t virtio_get_sectors(void) { - return vdev.config.blk.geometry.sectors; + switch (vdev.senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return vdev.config.blk.geometry.sectors; + } + return 0; } uint64_t virtio_get_blocks(void) { - return vdev.config.blk.capacity / - (virtio_get_block_size() / VIRTIO_SECTOR_SIZE); + switch (vdev.senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return vdev.config.blk.capacity / + (virtio_get_block_size() / VIRTIO_SECTOR_SIZE); + } + return 0; } static void virtio_setup_ccw(VDev *vdev) @@ -393,7 +439,7 @@ static void virtio_setup_ccw(VDev *vdev) unsigned char status = VIRTIO_CONFIG_S_DRIVER_OK; vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */ - vdev->guessed_disk_nature = false; + vdev->guessed_disk_nature = VIRTIO_GDN_NONE; run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0); @@ -441,19 +487,27 @@ static void virtio_setup_ccw(VDev *vdev) "Could not write status to host"); } -void virtio_setup_block(SubChannelId schid) +void virtio_setup_device(SubChannelId schid) { vdev.schid = schid; virtio_setup_ccw(&vdev); - 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(); + switch (vdev.senseid.cu_model) { + case VIRTIO_ID_BLOCK: + 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; + default: + panic("\n! No IPL device available !\n"); } } -bool virtio_is_blk(SubChannelId schid) +bool virtio_is_supported(SubChannelId schid) { vdev.schid = schid; memset(&vdev.senseid, 0, sizeof(vdev.senseid)); diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index b0034aa07f..7b227db7b8 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -201,7 +201,15 @@ struct VirtioBlkConfig { } __attribute__((packed)); typedef struct VirtioBlkConfig VirtioBlkConfig; -bool virtio_guessed_disk_nature(void); +enum guessed_disk_nature_type { + VIRTIO_GDN_NONE = 0, + VIRTIO_GDN_DASD = 1, + VIRTIO_GDN_CDROM = 2, + VIRTIO_GDN_SCSI = 3, +}; +typedef enum guessed_disk_nature_type VirtioGDN; + +VirtioGDN virtio_guessed_disk_nature(void); void virtio_assume_scsi(void); void virtio_assume_eckd(void); void virtio_assume_iso9660(void); @@ -228,7 +236,7 @@ struct VDev { int cmd_vr_idx; void *ring_area; long wait_reply_timeout; - bool guessed_disk_nature; + VirtioGDN guessed_disk_nature; SubChannelId schid; SenseId senseid; union { |