@@ -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;
+ }
+ 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));
@@ -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 {