/*
 * 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 <stdio.h>
#include "s390-ccw.h"
#include "virtio.h"
#include "virtio-scsi.h"

#define VIRTIO_BLK_F_GEOMETRY   (1 << 4)
#define VIRTIO_BLK_F_BLK_SIZE   (1 << 6)

static int virtio_blk_read_many(VDev *vdev, unsigned long 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(unsigned long 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);
    }

    return -1;
}

unsigned long virtio_load_direct(unsigned long rec_list1, unsigned long rec_list2,
                                 unsigned long 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;
    unsigned long addr = (unsigned long)load_addr;

    if (sec_len != virtio_get_block_size()) {
        return 0;
    }

    printf(".");
    status = virtio_read_many(sec, (void *)addr, sec_num);
    if (status) {
        return 0;
    }
    addr += sec_num * virtio_get_block_size();

    return addr;
}

int virtio_read(unsigned long 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_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 = VIRTIO_DASD_DEFAULT_BLOCK_SIZE;
        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_ipl_disk_is_valid(void)
{
    int blksize = virtio_get_block_size();
    VDev *vdev = virtio_get_device();

    if (vdev->guessed_disk_nature == VIRTIO_GDN_SCSI ||
        vdev->guessed_disk_nature == VIRTIO_GDN_DASD) {
        return true;
    }

    return (vdev->senseid.cu_model == VIRTIO_ID_BLOCK ||
            vdev->senseid.cu_model == VIRTIO_ID_SCSI) &&
           blksize >= 512 && blksize <= 4096;
}

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;
    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;
}

int virtio_blk_setup_device(SubChannelId schid)
{
    VDev *vdev = virtio_get_device();

    vdev->guest_features[0] = VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_BLK_SIZE;
    vdev->schid = schid;
    virtio_setup_ccw(vdev);

    puts("Using virtio-blk.");

    return 0;
}
