/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/*
 * Copyright (c) 2018-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 */

#ifndef _MST_KERNEL_H_
#define _MST_KERNEL_H_

/****************************************************/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/byteorder/generic.h>
#include <linux/cdev.h>

#include "mst.h"

/****************************************************/
#define DRV_VERSION "2.0.0"
#define DRV_RELDATE "Nov-27-2012"

/****************************************************/
/* defines */
#define MST_NAME_SIZE 30
#define MST_PREFIX "  MST::  "

#define MST_DEVICE_PREFIX "mt"
#define MST_PCICONF_DEVICE_NAME "_mstconf"
#define MST_PCIMEM_DEVICE_NAME "_mstcr"

#define MST_MELLANOX_PCI_VENDOR 0x15b3

#define MST_CONF_ADDR_REG 88
#define MST_CONF_DATA_REG 92

#define MST_VPD_DEFAULT_TOUT 2000 /* milli seconds */

#define mst_err(format, arg...) pr_err("%s: %s %d: " format, MST_PREFIX, __func__, __LINE__, ##arg)
#define mst_info(format, arg...) pr_info("%s: %s %d: " format, MST_PREFIX, __func__, __LINE__, ##arg)

#define capability_support_info_message(dev, capability)                                                 \
    mst_info("Device 0x%x (%x:%x:%x.%x) doesn't support %s capability.\n", dev->pci_dev->device,         \
             pci_domain_nr(dev->pci_dev->bus), dev->pci_dev->bus->number, PCI_SLOT(dev->pci_dev->devfn), \
             PCI_FUNC(dev->pci_dev->devfn), #capability);

/****************************************************/
/* new types */
enum dev_type
{
    PCICONF,
    PCIMEM
};

struct dma_page
{
    struct page** page_list;
    dma_addr_t dma_addr[PCICONF_MAX_PAGES_SIZE];
};

struct mst_dev_data
{
    int addr_reg; /* PCICONF address register */
    int data_reg; /* PCICONF data register */
    int wo_addr;
    unsigned int bar;         /* PCIMEM bar */
    void* hw_addr;            /* PCIMEM memory start */
    char name[MST_NAME_SIZE]; /* name of character device */
    enum dev_type type;       /* type of device */
    struct pci_dev* pci_dev;  /* device pci struct in kernel */
    struct list_head list;    /* list of mst_devices */
    struct mutex lock;        /* device lock */
    int vpd_cap_addr;         /* addr VPD capability */
    int major;                /* device major number */
    int initialized;          /* indicate if init done */

    dev_t my_dev;
    struct cdev mcdev;
    struct class* cl;

    unsigned char connectx_wa_slots; /* wa for pci bug */
                                     /* Vendor specific capability address */
    int vendor_specific_cap;
    /* status on VSEC supported spaces*/
    int spaces_support_status;

    // Allocated pages for the user space.
    struct dma_page dma_page;
};

/****************************************************/
int pci_read4_vpd(struct mst_dev_data* dev, unsigned int timeout, unsigned int offset, u32* buf);

int pci_write4_vpd(struct mst_dev_data* dev, unsigned int timeout, unsigned int offset, u32 buf);

#endif /* _MST_KERNEL_H_ */
