root/drivers/gpib/fmh_gpib/fmh_gpib.h
/* SPDX-License-Identifier: GPL-2.0 */

/***************************************************************************
 *    Author: Frank Mori Hess <fmh6jj@gmail.com>
 *   Copyright: (C) 2006, 2010, 2015 Fluke Corporation
 *      (C) 2017 Frank Mori Hess
 ***************************************************************************/

#include <linux/dmaengine.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/io.h>
#include "nec7210.h"

static const int fifo_reg_offset = 2;

static const int gpib_control_status_pci_resource_index;
static const int gpib_fifo_pci_resource_index = 1;

/* We don't have a real pci vendor/device id, the following will need to be
 * patched to match prototype hardware.
 */
#define BOGUS_PCI_VENDOR_ID_FLUKE 0xffff
#define BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER 0x0

struct fmh_priv {
        struct nec7210_priv nec7210_priv;
        struct resource *gpib_iomem_res;
        struct resource *write_transfer_counter_res;
        struct resource *dma_port_res;
        int irq;
        struct dma_chan *dma_channel;
        u8 *dma_buffer;
        int dma_buffer_size;
        int dma_burst_length;
        void __iomem *fifo_base;
        unsigned supports_fifo_interrupts : 1;
};

static inline int fmh_gpib_half_fifo_size(struct fmh_priv *priv)
{
        return priv->dma_burst_length;
}

// registers beyond the nec7210 register set
enum fmh_gpib_regs {
        EXT_STATUS_1_REG = 0x9,
        STATE1_REG = 0xc,
        ISR0_IMR0_REG = 0xe,
        BUS_STATUS_REG = 0xf
};

/* IMR0 -- Interrupt Mode Register 0 */
enum imr0_bits {
        ATN_INTERRUPT_ENABLE_BIT = 0x4,
        IFC_INTERRUPT_ENABLE_BIT = 0x8
};

/* ISR0 -- Interrupt Status Register 0 */
enum isr0_bits {
        ATN_INTERRUPT_BIT = 0x4,
        IFC_INTERRUPT_BIT = 0x8
};

enum state1_bits {
        SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */
        SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */
        SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */
        SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */
        SOURCE_HANDSHAKE_MASK = 0x7
};

enum fmh_gpib_auxmr_bits {
        AUX_I_REG = 0xe0,
};

enum aux_reg_i_bits {
        LOCAL_PPOLL_MODE_BIT = 0x4
};

enum ext_status_1_bits {
        DATA_IN_STATUS_BIT = 0x01,
        DATA_OUT_STATUS_BIT = 0x02,
        COMMAND_OUT_STATUS_BIT = 0x04,
        RFD_HOLDOFF_STATUS_BIT = 0x08,
        END_STATUS_BIT = 0x10
};

/* dma fifo reg and bits */
enum dma_fifo_regs {
        FIFO_DATA_REG = 0x0,
        FIFO_CONTROL_STATUS_REG = 0x1,
        FIFO_XFER_COUNTER_REG = 0x2,
        FIFO_MAX_BURST_LENGTH_REG = 0x3
};

enum fifo_data_bits {
        FIFO_DATA_EOI_FLAG = 0x100
};

enum fifo_control_bits {
        TX_FIFO_DMA_REQUEST_ENABLE = 0x0001,
        TX_FIFO_CLEAR = 0x0002,
        TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE = 0x0008,
        RX_FIFO_DMA_REQUEST_ENABLE = 0x0100,
        RX_FIFO_CLEAR = 0x0200,
        RX_FIFO_HALF_FULL_INTERRUPT_ENABLE = 0x0800
};

enum fifo_status_bits {
        TX_FIFO_EMPTY = 0x0001,
        TX_FIFO_FULL = 0x0002,
        TX_FIFO_HALF_EMPTY = 0x0004,
        TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED = 0x0008,
        TX_FIFO_DMA_REQUEST_IS_ENABLED = 0x0010,
        RX_FIFO_EMPTY = 0x0100,
        RX_FIFO_FULL = 0x0200,
        RX_FIFO_HALF_FULL = 0x0400,
        RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED = 0x0800,
        RX_FIFO_DMA_REQUEST_IS_ENABLED = 0x1000
};

static const unsigned int fifo_data_mask = 0x00ff;
static const unsigned int fifo_xfer_counter_mask = 0x0fff;
static const unsigned int fifo_max_burst_length_mask = 0x00ff;

static inline u8 gpib_cs_read_byte(struct nec7210_priv *nec_priv,
                                   unsigned int register_num)
{
        return readb(nec_priv->mmiobase + register_num * nec_priv->offset);
}

static inline void gpib_cs_write_byte(struct nec7210_priv *nec_priv, u8 data,
                                      unsigned int register_num)
{
        writeb(data, nec_priv->mmiobase + register_num * nec_priv->offset);
}

static inline uint16_t fifos_read(struct fmh_priv *fmh_priv, int register_num)
{
        if (!fmh_priv->fifo_base)
                return 0;
        return readw(fmh_priv->fifo_base + register_num * fifo_reg_offset);
}

static inline void fifos_write(struct fmh_priv *fmh_priv, uint16_t data, int register_num)
{
        if (!fmh_priv->fifo_base)
                return;
        writew(data, fmh_priv->fifo_base + register_num * fifo_reg_offset);
}

enum bus_status_bits {
        BSR_ATN_BIT = 0x01,
        BSR_EOI_BIT = 0x02,
        BSR_SRQ_BIT = 0x04,
        BSR_IFC_BIT = 0x08,
        BSR_REN_BIT = 0x10,
        BSR_DAV_BIT = 0x20,
        BSR_NRFD_BIT = 0x40,
        BSR_NDAC_BIT = 0x80,
};

enum fmh_gpib_aux_cmds {
        /* AUX_RTL2 is an auxiliary command which causes the cb7210 to assert
         * (and keep asserted) the local rtl message.  This is used in conjunction
         * with the normal nec7210 AUX_RTL command, which
         * pulses the rtl message, having the effect of clearing rtl if it was left
         * asserted by AUX_RTL2.
         */
        AUX_RTL2 = 0x0d,
        AUX_RFD_HOLDOFF_ASAP = 0x15,
        AUX_REQT = 0x18,
        AUX_REQF = 0x19,
        AUX_LO_SPEED = 0x40,
        AUX_HI_SPEED = 0x41
};