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

/***************************************************************************
 *    copyright            : (C) 2002 by Frank Mori Hess
 ***************************************************************************/

#ifndef _GPIB_TYPES_H
#define _GPIB_TYPES_H

#ifdef __KERNEL__
#include <linux/gpib.h>
#include <linux/atomic.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>

struct gpib_board;

/* config parameters that are only used by driver attach functions */
struct gpib_board_config {
        /* firmware blob */
        void *init_data;
        int init_data_length;
        /* IO base address to use for non-pnp cards (set by core, driver should make local copy) */
        u32 ibbase;
        void __iomem *mmibbase;
        /* IRQ to use for non-pnp cards (set by core, driver should make local copy) */
        unsigned int ibirq;
        /* dma channel to use for non-pnp cards (set by core, driver should make local copy) */
        unsigned int ibdma;
        /*
         * pci bus of card, useful for distinguishing multiple identical pci cards
         * (negative means don't care)
         */
        int pci_bus;
        /*
         * pci slot of card, useful for distinguishing multiple identical pci cards
         * (negative means don't care)
         */
        int pci_slot;
        /* sysfs device path of hardware to attach */
        char *device_path;
        /* serial number of hardware to attach */
        char *serial_number;
};

/*
 * struct gpib_interface defines the interface
 * between the board-specific details dealt with in the drivers
 * and generic interface provided by gpib-common.
 * This really should be in a different header file.
 */
struct gpib_interface {
        /* name of board */
        char *name;
        /* attach() initializes board and allocates resources */
        int (*attach)(struct gpib_board *board, const struct gpib_board_config *config);
        /* detach() shuts down board and frees resources */
        void (*detach)(struct gpib_board *board);
        /*
         * read() should read at most 'length' bytes from the bus into
         * 'buffer'.  It should return when it fills the buffer or
         * encounters an END (EOI and or EOS if appropriate).  It should set 'end'
         * to be nonzero if the read was terminated by an END, otherwise 'end'
         * should be zero.
         * Ultimately, this will be changed into or replaced by an asynchronous
         * read.  Zero return value for success, negative
         * return indicates error.
         * nbytes returns number of bytes read
         */
        int (*read)(struct gpib_board *board, u8 *buffer, size_t length, int *end,
                    size_t *bytes_read);
        /*
         * write() should write 'length' bytes from buffer to the bus.
         * If the boolean value send_eoi is nonzero, then EOI should
         * be sent along with the last byte.  Returns number of bytes
         * written or negative value on error.
         */
        int (*write)(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi,
                     size_t *bytes_written);
        /*
         * command() writes the command bytes in 'buffer' to the bus
         * Returns zero on success or negative value on error.
         */
        int (*command)(struct gpib_board *board, u8 *buffer, size_t length,
                       size_t *bytes_written);
        /*
         * Take control (assert ATN).  If 'asyncronous' is nonzero, take
         * control asyncronously (assert ATN immediately without waiting
         * for other processes to complete first).  Should not return
         * until board becomes controller in charge.  Returns zero no success,
         * nonzero on error.
         */
        int (*take_control)(struct gpib_board *board, int asyncronous);
        /*
         * De-assert ATN.  Returns zero on success, nonzer on error.
         */
        int (*go_to_standby)(struct gpib_board *board);
        /* request/release control of the IFC and REN lines (system controller) */
        int (*request_system_control)(struct gpib_board *board, int request_control);
        /*
         * Asserts or de-asserts 'interface clear' (IFC) depending on
         * boolean value of 'assert'
         */
        void (*interface_clear)(struct gpib_board *board, int assert);
        /*
         * Sends remote enable command if 'enable' is nonzero, disables remote mode
         * if 'enable' is zero
         */
        void (*remote_enable)(struct gpib_board *board, int enable);
        /*
         * enable END for reads, when byte 'eos' is received.  If
         * 'compare_8_bits' is nonzero, then all 8 bits are compared
         * with the eos bytes.  Otherwise only the 7 least significant
         * bits are compared.
         */
        int (*enable_eos)(struct gpib_board *board, u8 eos, int compare_8_bits);
        /* disable END on eos byte (END on EOI only)*/
        void (*disable_eos)(struct gpib_board *board);
        /* configure parallel poll */
        void (*parallel_poll_configure)(struct gpib_board *board, u8 configuration);
        /* conduct parallel poll */
        int (*parallel_poll)(struct gpib_board *board, u8 *result);
        /* set/clear ist (individual status bit) */
        void (*parallel_poll_response)(struct gpib_board *board, int ist);
        /* select local parallel poll configuration mode PP2 versus remote PP1 */
        void (*local_parallel_poll_mode)(struct gpib_board *board, int local);
        /*
         * Returns current status of the bus lines.  Should be set to
         * NULL if your board does not have the ability to query the
         * state of the bus lines.
         */
        int (*line_status)(const struct gpib_board *board);
        /*
         * updates and returns the board's current status.
         * The meaning of the bits are specified in gpib_user.h
         * in the IBSTA section.  The driver does not need to
         * worry about setting the CMPL, END, TIMO, or ERR bits.
         */
        unsigned int (*update_status)(struct gpib_board *board, unsigned int clear_mask);
        /*
         * Sets primary address 0-30 for gpib interface card.
         */
        int (*primary_address)(struct gpib_board *board, unsigned int address);
        /*
         * Sets and enables, or disables secondary address 0-30
         * for gpib interface card.
         */
        int (*secondary_address)(struct gpib_board *board, unsigned int address,
                                 int enable);
        /*
         * Sets the byte the board should send in response to a serial poll.
         * This function should also start or stop requests for service via
         * IEEE 488.2 reqt/reqf, based on MSS (bit 6 of the status_byte).
         * If the more flexible serial_poll_response2 is implemented by the
         * driver, then this method should be left NULL since it will not
         * be used.  This method can generate spurious service requests
         * which are allowed by IEEE 488.2, but not ideal.
         *
         * This method should implement the serial poll response method described
         * by IEEE 488.2 section 11.3.3.4.3 "Allowed Coupled Control of
         * STB, reqt, and reqf".
         */
        void (*serial_poll_response)(struct gpib_board *board, u8 status_byte);
        /*
         * Sets the byte the board should send in response to a serial poll.
         * This function should also request service via IEEE 488.2 reqt/reqf
         * based on MSS (bit 6 of the status_byte) and new_reason_for_service.
         * reqt should be set true if new_reason_for_service is true,
         * and reqf should be set true if MSS is false.  This function
         * will never be called with MSS false and new_reason_for_service
         * true simultaneously, so don't worry about that case.
         *
         * This method implements the serial poll response method described
         * by IEEE 488.2 section 11.3.3.4.1 "Preferred Implementation".
         *
         * If this method is left NULL by the driver, then the user library
         * function ibrsv2 will not work.
         */
        void (*serial_poll_response2)(struct gpib_board *board, u8 status_byte,
                                      int new_reason_for_service);
        /*
         * returns the byte the board will send in response to a serial poll.
         */
        u8 (*serial_poll_status)(struct gpib_board *board);
        /* adjust T1 delay */
        int (*t1_delay)(struct gpib_board *board, unsigned int nano_sec);
        /* go to local mode */
        void (*return_to_local)(struct gpib_board *board);
        /* board does not support 7 bit eos comparisons */
        unsigned no_7_bit_eos : 1;
        /* skip check for listeners before trying to send command bytes */
        unsigned skip_check_for_command_acceptors : 1;
};

struct gpib_event_queue {
        struct list_head event_head;
        spinlock_t lock; // for access to event list
        unsigned int num_events;
        unsigned dropped_event : 1;
};

static inline void init_event_queue(struct gpib_event_queue *queue)
{
        INIT_LIST_HEAD(&queue->event_head);
        queue->num_events = 0;
        queue->dropped_event = 0;
        spin_lock_init(&queue->lock);
}

/* struct for supporting polling operation when irq is not available */
struct gpib_pseudo_irq {
        struct timer_list timer;
        irqreturn_t (*handler)(int irq, void *arg);
        struct gpib_board *board;
        atomic_t active;
};

static inline void init_gpib_pseudo_irq(struct gpib_pseudo_irq *pseudo_irq)
{
        pseudo_irq->handler = NULL;
        timer_setup(&pseudo_irq->timer, NULL, 0);
        atomic_set(&pseudo_irq->active, 0);
}

/* list so we can make a linked list of drivers */
struct gpib_interface_list {
        struct list_head list;
        struct gpib_interface *interface;
        struct module *module;
};

/*
 * One struct gpib_board is allocated for each physical board in the computer.
 * It provides storage for variables local to each board, and interface
 * functions for performing operations on the board
 */
struct gpib_board {
        /* functions used by this board */
        struct gpib_interface *interface;
        /*
         * Pointer to module whose use count we should increment when
         * interface is in use
         */
        struct module *provider_module;
        /* buffer used to store read/write data for this board */
        u8 *buffer;
        /* length of buffer */
        unsigned int buffer_length;
        /*
         * Used to hold the board's current status (see update_status() above)
         */
        unsigned long status;
        /*
         * Driver should only sleep on this wait queue.  It is special in that the
         * core will wake this queue and set the TIMO bit in 'status' when the
         * watchdog timer times out.
         */
        wait_queue_head_t wait;
        /*
         * Lock that only allows one process to access this board at a time.
         * Has to be first in any locking order, since it can be locked over
         * multiple ioctls.
         */
        struct mutex user_mutex;
        /*
         * Mutex which compensates for removal of "big kernel lock" from kernel.
         * Should not be held for extended waits.
         */
        struct mutex big_gpib_mutex;
        /* pid of last process to lock the board mutex */
        pid_t locking_pid;
        /* lock for setting locking pid */
        spinlock_t locking_pid_spinlock;
        /* Spin lock for dealing with races with the interrupt handler */
        spinlock_t spinlock;
        /* Watchdog timer to enable timeouts */
        struct timer_list timer;
        /* device of attached driver if any */
        struct device *dev;
        /* gpib_common device gpibN */
        struct device *gpib_dev;
        /*
         * 'private_data' can be used as seen fit by the driver to
         * store additional variables for this board
         */
        void *private_data;
        /* Number of open file descriptors using this board */
        unsigned int use_count;
        /* list of open devices connected to this board */
        struct list_head device_list;
        /* primary address */
        unsigned int pad;
        /* secondary address */
        int sad;
        /* timeout for io operations, in microseconds */
        unsigned int usec_timeout;
        /* board's parallel poll configuration byte */
        u8 parallel_poll_configuration;
        /* t1 delay we are using */
        unsigned int t1_nano_sec;
        /* Count that keeps track of whether board is up and running or not */
        unsigned int online;
        /* number of processes trying to autopoll */
        int autospollers;
        /* autospoll kernel thread */
        struct task_struct *autospoll_task;
        /* queue for recording received trigger/clear/ifc events */
        struct gpib_event_queue event_queue;
        /* minor number for this board's device file */
        int minor;
        /* struct to deal with polling mode*/
        struct gpib_pseudo_irq pseudo_irq;
        /* error dong autopoll */
        atomic_t stuck_srq;
        struct gpib_board_config config;
        /* Flag that indicates whether board is system controller of the bus */
        unsigned master : 1;
        /* individual status bit */
        unsigned ist : 1;
        /*
         * one means local parallel poll mode ieee 488.1 PP2 (or no parallel poll PP0),
         * zero means remote parallel poll configuration mode ieee 488.1 PP1
         */
        unsigned local_ppoll_mode : 1;
};

/* element of event queue */
struct gpib_event {
        struct list_head list;
        short event_type;
};

/*
 * Each board has a list of gpib_status_queue to keep track of all open devices
 * on the bus, so we know what address to poll when we get a service request
 */
struct gpib_status_queue {
        /* list_head so we can make a linked list of devices */
        struct list_head list;
        unsigned int pad;       /* primary gpib address */
        int sad;        /* secondary gpib address (negative means disabled) */
        /* stores serial poll bytes for this device */
        struct list_head status_bytes;
        unsigned int num_status_bytes;
        /* number of times this address is opened */
        unsigned int reference_count;
        /* flags loss of status byte error due to limit on size of queue */
        unsigned dropped_byte : 1;
};

struct gpib_status_byte {
        struct list_head list;
        u8 poll_byte;
};

void init_gpib_status_queue(struct gpib_status_queue *device);

/* Used to store device-descriptor-specific information */
struct gpib_descriptor {
        unsigned int pad;       /* primary gpib address */
        int sad;        /* secondary gpib address (negative means disabled) */
        atomic_t io_in_progress;
        /*
         * Kernel-only reference count to prevent descriptor from being
         * freed while IO handlers hold a pointer to it.  Incremented
         * before each IO operation, decremented when done.  Unlike
         * io_in_progress, this cannot be modified from userspace via
         * general_ibstatus().
         */
        atomic_t descriptor_busy;
        unsigned is_board : 1;
        unsigned autopoll_enabled : 1;
};

struct gpib_file_private {
        atomic_t holding_mutex;
        struct gpib_descriptor *descriptors[GPIB_MAX_NUM_DESCRIPTORS];
        /* locked while descriptors are being allocated/deallocated */
        struct mutex descriptors_mutex;
        unsigned got_module : 1;
};

#endif  /* __KERNEL__ */

#endif  /* _GPIB_TYPES_H */