mirror of https://gitee.com/openkylin/qemu.git
pc-bios/s390-ccw: make provisions for different backends
Add dispatching code to make room for non virtio-blk boot devices. Signed-off-by: Eugene (jno) Dvurechenski <jno@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
parent
69429682c6
commit
a1102cebbf
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
return (vdev.config.blk.geometry.heads == 255)
|
||||
&& (vdev.config.blk.geometry.sectors == 63)
|
||||
&& (virtio_get_block_size() == 512);
|
||||
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 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));
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue