#include <glib.h>
#include <blockdev/utils.h>


#ifndef BD_S390_API
#define BD_S390_API

GQuark  bd_s390_error_quark (void);


#define BD_S390_ERROR bd_s390_error_quark ()
typedef enum {
    BD_S390_ERROR_TECH_UNAVAIL,
    BD_S390_ERROR_DEVICE,
    BD_S390_ERROR_FORMAT_FAILED,
    BD_S390_ERROR_DASDFMT,
    BD_S390_ERROR_IO,
} BDS390Error;

typedef enum {
    BD_S390_TECH_DASD = 0,
    BD_S390_TECH_ZFCP,
} BDS390Tech;

typedef enum {
    BD_S390_TECH_MODE_MODIFY  = 1 << 0,
    BD_S390_TECH_MODE_QUERY   = 1 << 1,
} BDS390TechMode;

/**
 * bd_s390_is_tech_avail:
 * @tech: the queried tech
 * @mode: a bit mask of queried modes of operation (#BDS390TechMode) for @tech
 * @error: (out) (optional): place to store error (details about why the @tech-@mode combination is not available)
 *
 * Returns: whether the @tech-@mode combination is available -- supported by the
 *          plugin implementation and having all the runtime dependencies available
 */
gboolean  bd_s390_is_tech_avail (BDS390Tech tech, guint64 mode, GError **error);


/**
 * bd_s390_dasd_format:
 * @dasd: dasd to format
 * @extra: (nullable) (array zero-terminated=1): extra options for the formatting (right now
 *                                                 passed to the 'dasdfmt' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether dasdfmt was successful or not
 *
 * Tech category: %BD_S390_TECH_DASD-%BD_S390_TECH_MODE_MODIFY
 */
gboolean  bd_s390_dasd_format (const gchar *dasd, const BDExtraArg **extra, GError **error);


/**
 * bd_s390_dasd_needs_format:
 * @dasd: dasd to check, given as device number
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether a dasd needs dasdfmt run against it
 *
 * Tech category: %BD_S390_TECH_DASD-%BD_S390_TECH_MODE_QUERY
 */
gboolean  bd_s390_dasd_needs_format (const gchar *dasd, GError **error);


/**
 * bd_s390_dasd_online:
 * @dasd: dasd to switch online, given as device number
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether a dasd was successfully switched online
 *
 * Tech category: %BD_S390_TECH_DASD-%BD_S390_TECH_MODE_MODIFY
 */
gboolean  bd_s390_dasd_online (const gchar *dasd, GError **error);


/**
 * bd_s390_dasd_is_Ldl:
 * @dasd: dasd to check, whether it is LDL formatted
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether a dasd is LDL formatted
 *
 * Tech category: %BD_S390_TECH_DASD-%BD_S390_TECH_MODE_QUERY
 */
gboolean  bd_s390_dasd_is_ldl (const gchar *dasd, GError **error);


/**
 * bd_s390_dasd_is_fba:
 * @dasd: dasd to check, whether it is FBA
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether a dasd is FBA
 *
 * Tech category: %BD_S390_TECH_DASD-%BD_S390_TECH_MODE_QUERY
 */
gboolean  bd_s390_dasd_is_fba (const gchar *dasd, GError **error);


/**
 * bd_s390_sanitize_dev_input:
 * @dev: a DASD or zFCP device number
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: (transfer full): a synthesized dasd or zfcp device number
 *
 * Tech category: always available
 */
gchar* bd_s390_sanitize_dev_input (const gchar *dev, GError **error);


/**
 * bd_s390_zfcp_sanitize_wwpn_input:
 * @wwpn: a zFCP WWPN identifier
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: (transfer full): a synthesized zFCP WWPN
 *
 * Tech category: always available
 */
gchar* bd_s390_zfcp_sanitize_wwpn_input (const gchar *wwpn, GError **error);


/**
 * bd_s390_zfcp_sanitize_lun_input:
 * @lun: a zFCP LUN identifier
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: (transfer full): a synthesized zFCP LUN
 *
 * Tech category: always available
 */
gchar* bd_s390_zfcp_sanitize_lun_input (const gchar *lun, GError **error);


/**
 * bd_s390_zfcp_online:
 * @devno: zfcp device number
 * @wwpn: zfcp WWPN (World Wide Port Number)
 * @lun: zfcp LUN (Logical Unit Number)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether a zFCP device was successfully switched online
 *
 * Tech category: %BD_S390_TECH_ZFCP-%BD_S390_TECH_MODE_MODIFY
 */
gboolean  bd_s390_zfcp_online (const gchar *devno, const gchar *wwpn, const gchar *lun, GError **error);


/**
 * bd_s390_zfcp_scsi_offline:
 * @devno: zfcp device number
 * @wwpn: zfcp WWPN (World Wide Port Number)
 * @lun: zfcp LUN (Logical Unit Number)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether a LUN was successfully removed from its associated WWPN
 *
 * This function looks through /proc/scsi/scsi and manually removes LUNs from
 * associated WWPNs. zFCP devices are SCSI devices accessible over FCP protocol.
 * In z/OS the IODF (I/O definition file) contains basic information about the
 * I/O config, but WWPN and LUN configuration is done at the OS level, hence
 * this function becomes necessary when switching the device offline. This
 * particular sequence of actions is for some reason unnecessary when switching
 * the device online. Chalk it up to s390x being s390x.
 *
 * Tech category: %BD_S390_TECH_ZFCP-%BD_S390_TECH_MODE_MODIFY
 */
gboolean  bd_s390_zfcp_scsi_offline (const gchar *devno, const gchar *wwpn, const gchar *lun, GError **error);


/**
 * bd_s390_zfcp_offline:
 * @devno: zfcp device number
 * @wwpn: zfcp WWPN (World Wide Port Number)
 * @lun: zfcp LUN (Logical Unit Number)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether a zfcp device was successfully switched offline
 *
 * Tech category: %BD_S390_TECH_ZFCP-%BD_S390_TECH_MODE_MODIFY
 */
gboolean  bd_s390_zfcp_offline (const gchar *devno, const gchar *wwpn, const gchar *lun, GError **error);


#endif  /* BD_S390_API */
