/** @file

  Virtio Block Device specific type and macro definitions corresponding to the
  virtio-0.9.5 specification.

  Copyright (C) 2012, Red Hat, Inc.

  This program and the accompanying materials are licensed and made available
  under the terms and conditions of the BSD License which accompanies this
  distribution. The full text of the license may be found at
  http://opensource.org/licenses/bsd-license.php

  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

#ifndef _VIRTIO_BLK_H_
#define _VIRTIO_BLK_H_

#include <IndustryStandard/Virtio.h>


//
// virtio-0.9.5, Appendix D: Block Device
//
#pragma pack(1)
typedef struct {
  UINT8  PhysicalBlockExp; // # of logical blocks per physical block (log2)
  UINT8  AlignmentOffset;  // offset of first aligned logical block
  UINT16 MinIoSize;        // suggested minimum I/O size in blocks
  UINT32 OptIoSize;        // optimal (suggested maximum) I/O size in blocks
} VIRTIO_BLK_TOPOLOGY;

typedef struct {
  UINT64              Capacity;
  UINT32              SizeMax;
  UINT32              SegMax;
  UINT16              Cylinders;
  UINT8               Heads;
  UINT8               Sectors;
  UINT32              BlkSize;
  VIRTIO_BLK_TOPOLOGY Topology;
} VIRTIO_BLK_CONFIG;
#pragma pack()

#define OFFSET_OF_VBLK(Field) OFFSET_OF (VIRTIO_BLK_CONFIG, Field)
#define SIZE_OF_VBLK(Field)   (sizeof ((VIRTIO_BLK_CONFIG *) 0)->Field)

#define VIRTIO_BLK_F_BARRIER  BIT0
#define VIRTIO_BLK_F_SIZE_MAX BIT1
#define VIRTIO_BLK_F_SEG_MAX  BIT2
#define VIRTIO_BLK_F_GEOMETRY BIT4
#define VIRTIO_BLK_F_RO       BIT5
#define VIRTIO_BLK_F_BLK_SIZE BIT6  // treated as "logical block size" in
                                    // practice; actual host side
                                    // implementation negotiates "optimal"
                                    // block size separately, via
                                    // VIRTIO_BLK_F_TOPOLOGY
#define VIRTIO_BLK_F_SCSI     BIT7
#define VIRTIO_BLK_F_FLUSH    BIT9  // identical to "write cache enabled"
#define VIRTIO_BLK_F_TOPOLOGY BIT10 // information on optimal I/O alignment

//
// We keep the status byte separate from the rest of the virtio-blk request
// header. See description of historical scattering at the end of Appendix D:
// we're going to put the status byte in a separate VRING_DESC.
//
#pragma pack(1)
typedef struct {
  UINT32 Type;
  UINT32 IoPrio;
  UINT64 Sector;
} VIRTIO_BLK_REQ;
#pragma pack()

#define VIRTIO_BLK_T_IN           0x00000000
#define VIRTIO_BLK_T_OUT          0x00000001
#define VIRTIO_BLK_T_SCSI_CMD     0x00000002
#define VIRTIO_BLK_T_SCSI_CMD_OUT 0x00000003
#define VIRTIO_BLK_T_FLUSH        0x00000004
#define VIRTIO_BLK_T_FLUSH_OUT    0x00000005
#define VIRTIO_BLK_T_BARRIER      BIT31

#define VIRTIO_BLK_S_OK           0x00
#define VIRTIO_BLK_S_IOERR        0x01
#define VIRTIO_BLK_S_UNSUPP       0x02

#endif // _VIRTIO_BLK_H_