mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 17:23:56 -06:00
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
4 changed files with 106 additions and 44 deletions
|
@ -50,7 +50,7 @@ static bool find_dev(Schib *schib, int dev_no)
|
||||||
if (!schib->pmcw.dnv) {
|
if (!schib->pmcw.dnv) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!virtio_is_blk(blk_schid)) {
|
if (!virtio_is_supported(blk_schid)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) {
|
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");
|
panic("No virtio-blk device found!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtio_setup_block(blk_schid);
|
virtio_setup_device(blk_schid);
|
||||||
|
|
||||||
if (!virtio_ipl_disk_is_valid()) {
|
if (!virtio_ipl_disk_is_valid()) {
|
||||||
panic("No valid hard disk detected.\n");
|
panic("No valid hard disk detected.\n");
|
||||||
|
|
|
@ -70,8 +70,8 @@ void sclp_setup(void);
|
||||||
/* virtio.c */
|
/* virtio.c */
|
||||||
unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
|
unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
|
||||||
ulong subchan_id, void *load_addr);
|
ulong subchan_id, void *load_addr);
|
||||||
bool virtio_is_blk(SubChannelId schid);
|
bool virtio_is_supported(SubChannelId schid);
|
||||||
void virtio_setup_block(SubChannelId schid);
|
void virtio_setup_device(SubChannelId schid);
|
||||||
int virtio_read(ulong sector, void *load_addr);
|
int virtio_read(ulong sector, void *load_addr);
|
||||||
int enable_mss_facility(void);
|
int enable_mss_facility(void);
|
||||||
ulong get_second(void);
|
ulong get_second(void);
|
||||||
|
|
|
@ -25,7 +25,6 @@ static VDev vdev = {
|
||||||
.cmd_vr_idx = 0,
|
.cmd_vr_idx = 0,
|
||||||
.ring_area = ring_area,
|
.ring_area = ring_area,
|
||||||
.wait_reply_timeout = VRING_WAIT_REPLY_TIMEOUT,
|
.wait_reply_timeout = VRING_WAIT_REPLY_TIMEOUT,
|
||||||
.guessed_disk_nature = false,
|
|
||||||
.schid = { .one = 1 },
|
.schid = { .one = 1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,11 +229,12 @@ static int vring_wait_reply(void)
|
||||||
* Virtio block *
|
* 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;
|
VirtioBlkOuthdr out_hdr;
|
||||||
u8 status;
|
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 */
|
/* Tell the host we want to read */
|
||||||
out_hdr.type = VIRTIO_BLK_T_IN;
|
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;
|
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,
|
unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
|
||||||
ulong subchan_id, void *load_addr)
|
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);
|
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;
|
return vdev.guessed_disk_nature;
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtio_assume_scsi(void)
|
void virtio_assume_scsi(void)
|
||||||
{
|
{
|
||||||
vdev.guessed_disk_nature = true;
|
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.blk_size = 512;
|
||||||
vdev.config.blk.physical_block_exp = 0;
|
vdev.config.blk.physical_block_exp = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtio_assume_iso9660(void)
|
void virtio_assume_iso9660(void)
|
||||||
{
|
{
|
||||||
vdev.guessed_disk_nature = true;
|
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.blk_size = 2048;
|
||||||
vdev.config.blk.physical_block_exp = 0;
|
vdev.config.blk.physical_block_exp = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtio_assume_eckd(void)
|
void virtio_assume_eckd(void)
|
||||||
{
|
{
|
||||||
vdev.guessed_disk_nature = true;
|
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.blk_size = 4096;
|
||||||
vdev.config.blk.physical_block_exp = 0;
|
vdev.config.blk.physical_block_exp = 0;
|
||||||
|
|
||||||
/* this must be here to calculate code segment position */
|
/* this must be here to calculate code segment position */
|
||||||
vdev.config.blk.geometry.heads = 15;
|
vdev.config.blk.geometry.heads = 15;
|
||||||
vdev.config.blk.geometry.sectors = 12;
|
vdev.config.blk.geometry.sectors = 12;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool virtio_disk_is_scsi(void)
|
bool virtio_disk_is_scsi(void)
|
||||||
{
|
{
|
||||||
if (vdev.guessed_disk_nature) {
|
if (vdev.guessed_disk_nature == VIRTIO_GDN_SCSI) {
|
||||||
return (virtio_get_block_size() == 512);
|
return true;
|
||||||
}
|
}
|
||||||
|
switch (vdev.senseid.cu_model) {
|
||||||
|
case VIRTIO_ID_BLOCK:
|
||||||
return (vdev.config.blk.geometry.heads == 255)
|
return (vdev.config.blk.geometry.heads == 255)
|
||||||
&& (vdev.config.blk.geometry.sectors == 63)
|
&& (vdev.config.blk.geometry.sectors == 63)
|
||||||
&& (virtio_get_block_size() == 512);
|
&& (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();
|
const int block_size = virtio_get_block_size();
|
||||||
|
|
||||||
if (vdev.guessed_disk_nature) {
|
if (vdev.guessed_disk_nature == VIRTIO_GDN_DASD) {
|
||||||
return (block_size == 4096);
|
return true;
|
||||||
}
|
}
|
||||||
|
switch (vdev.senseid.cu_model) {
|
||||||
|
case VIRTIO_ID_BLOCK:
|
||||||
return (vdev.config.blk.geometry.heads == 15)
|
return (vdev.config.blk.geometry.heads == 15)
|
||||||
&& (vdev.config.blk.geometry.sectors ==
|
&& (vdev.config.blk.geometry.sectors ==
|
||||||
virtio_eckd_sectors_for_block_size(block_size));
|
virtio_eckd_sectors_for_block_size(block_size));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool virtio_ipl_disk_is_valid(void)
|
bool virtio_ipl_disk_is_valid(void)
|
||||||
|
@ -368,23 +398,39 @@ bool virtio_ipl_disk_is_valid(void)
|
||||||
|
|
||||||
int virtio_get_block_size(void)
|
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;
|
return vdev.config.blk.blk_size << vdev.config.blk.physical_block_exp;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t virtio_get_heads(void)
|
uint8_t virtio_get_heads(void)
|
||||||
{
|
{
|
||||||
|
switch (vdev.senseid.cu_model) {
|
||||||
|
case VIRTIO_ID_BLOCK:
|
||||||
return vdev.config.blk.geometry.heads;
|
return vdev.config.blk.geometry.heads;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t virtio_get_sectors(void)
|
uint8_t virtio_get_sectors(void)
|
||||||
{
|
{
|
||||||
|
switch (vdev.senseid.cu_model) {
|
||||||
|
case VIRTIO_ID_BLOCK:
|
||||||
return vdev.config.blk.geometry.sectors;
|
return vdev.config.blk.geometry.sectors;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t virtio_get_blocks(void)
|
uint64_t virtio_get_blocks(void)
|
||||||
{
|
{
|
||||||
|
switch (vdev.senseid.cu_model) {
|
||||||
|
case VIRTIO_ID_BLOCK:
|
||||||
return vdev.config.blk.capacity /
|
return vdev.config.blk.capacity /
|
||||||
(virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
|
(virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_setup_ccw(VDev *vdev)
|
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;
|
unsigned char status = VIRTIO_CONFIG_S_DRIVER_OK;
|
||||||
|
|
||||||
vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */
|
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);
|
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");
|
"Could not write status to host");
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtio_setup_block(SubChannelId schid)
|
void virtio_setup_device(SubChannelId schid)
|
||||||
{
|
{
|
||||||
vdev.schid = schid;
|
vdev.schid = schid;
|
||||||
virtio_setup_ccw(&vdev);
|
virtio_setup_ccw(&vdev);
|
||||||
|
|
||||||
|
switch (vdev.senseid.cu_model) {
|
||||||
|
case VIRTIO_ID_BLOCK:
|
||||||
if (!virtio_ipl_disk_is_valid()) {
|
if (!virtio_ipl_disk_is_valid()) {
|
||||||
/* make sure all getters but blocksize return 0 for invalid IPL disk */
|
/* make sure all getters but blocksize return 0 for
|
||||||
|
* invalid IPL disk
|
||||||
|
*/
|
||||||
memset(&vdev.config.blk, 0, sizeof(vdev.config.blk));
|
memset(&vdev.config.blk, 0, sizeof(vdev.config.blk));
|
||||||
virtio_assume_scsi();
|
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;
|
vdev.schid = schid;
|
||||||
memset(&vdev.senseid, 0, sizeof(vdev.senseid));
|
memset(&vdev.senseid, 0, sizeof(vdev.senseid));
|
||||||
|
|
|
@ -201,7 +201,15 @@ struct VirtioBlkConfig {
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
typedef struct VirtioBlkConfig VirtioBlkConfig;
|
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_scsi(void);
|
||||||
void virtio_assume_eckd(void);
|
void virtio_assume_eckd(void);
|
||||||
void virtio_assume_iso9660(void);
|
void virtio_assume_iso9660(void);
|
||||||
|
@ -228,7 +236,7 @@ struct VDev {
|
||||||
int cmd_vr_idx;
|
int cmd_vr_idx;
|
||||||
void *ring_area;
|
void *ring_area;
|
||||||
long wait_reply_timeout;
|
long wait_reply_timeout;
|
||||||
bool guessed_disk_nature;
|
VirtioGDN guessed_disk_nature;
|
||||||
SubChannelId schid;
|
SubChannelId schid;
|
||||||
SenseId senseid;
|
SenseId senseid;
|
||||||
union {
|
union {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue