--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Header for amcc5920 pci chip
+ *
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+// plx pci chip registers and bits
+enum amcc_registers {
+ AMCC_INTCS_REG = 0x38,
+ AMCC_PASS_THRU_REG = 0x60,
+};
+
+enum amcc_incsr_bits {
+ AMCC_ADDON_INTR_ENABLE_BIT = 0x2000,
+ AMCC_ADDON_INTR_ACTIVE_BIT = 0x400000,
+ AMCC_INTR_ACTIVE_BIT = 0x800000,
+};
+
+static const int bits_per_region = 8;
+
+static inline uint32_t amcc_wait_state_bits(unsigned int region, unsigned int num_wait_states)
+{
+ return (num_wait_states & 0x7) << (-region * bits_per_region);
+};
+
+enum amcc_prefetch_bits {
+ PREFETCH_DISABLED = 0x0,
+ PREFETCH_SMALL = 0x8,
+ PREFETCH_MEDIUM = 0x10,
+ PREFETCH_LARGE = 0x18,
+};
+
+static inline uint32_t amcc_prefetch_bits(unsigned int region, enum amcc_prefetch_bits prefetch)
+{
+ return prefetch << (--region * bits_per_region);
+};
+
+static inline uint32_t amcc_PTADR_mode_bit(unsigned int region)
+{
+ return 0x80 << (--region * bits_per_region);
+};
+
+static inline uint32_t amcc_disable_write_fifo_bit(unsigned int region)
+{
+ return 0x20 << (--region * bits_per_region);
+};
+
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Registers and bits for amccs5933 pci chip
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+// register offsets
+enum {
+ MBEF_REG = 0x34, // mailbux empty/full
+ INTCSR_REG = 0x38, // interrupt control and status
+ BMCSR_REG = 0x3c, // bus master control and status
+};
+
+// incoming mailbox 0-3 register offsets
+extern inline int INCOMING_MAILBOX_REG(unsigned int mailbox)
+{
+ return (0x10 + 4 * mailbox);
+};
+
+// bit definitions
+
+// INTCSR bits
+enum {
+ OUTBOX_EMPTY_INTR_BIT = 0x10, // enable outbox empty interrupt
+ INBOX_FULL_INTR_BIT = 0x1000, // enable inbox full interrupt
+ INBOX_INTR_CS_BIT = 0x20000, // read, or write clear inbox full interrupt
+ INTR_ASSERTED_BIT = 0x800000, // read only, interrupt asserted
+};
+
+// select byte 0 to 3 of incoming mailbox
+extern inline int INBOX_BYTE_BITS(unsigned int byte)
+{
+ return (byte & 0x3) << 8;
+};
+
+// select incoming mailbox 0 to 3
+extern inline int INBOX_SELECT_BITS(unsigned int mailbox)
+{
+ return (mailbox & 0x3) << 10;
+};
+
+// select byte 0 to 3 of outgoing mailbox
+extern inline int OUTBOX_BYTE_BITS(unsigned int byte)
+{
+ return (byte & 0x3);
+};
+
+// select outgoing mailbox 0 to 3
+extern inline int OUTBOX_SELECT_BITS(unsigned int mailbox)
+{
+ return (mailbox & 0x3) << 2;
+};
+
+//BMCSR bits
+enum {
+ MBOX_FLAGS_RESET_BIT = 0x08000000, // resets mailbox empty/full flags
+};
+
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002,2003 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_P_H
+#define _GPIB_P_H
+
+#include <linux/types.h>
+
+#include "gpib_types.h"
+#include "gpib_proto.h"
+#include "gpib_user.h"
+#include "gpib_ioctl.h"
+
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+
+void gpib_register_driver(gpib_interface_t *interface, struct module *mod);
+void gpib_unregister_driver(gpib_interface_t *interface);
+struct pci_dev *gpib_pci_get_device(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, struct pci_dev *from);
+struct pci_dev *gpib_pci_get_subsys(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, unsigned int ss_vendor,
+ unsigned int ss_device, struct pci_dev *from);
+unsigned int num_gpib_events(const gpib_event_queue_t *queue);
+int push_gpib_event(gpib_board_t *board, short event_type);
+int pop_gpib_event(gpib_event_queue_t *queue, short *event_type);
+int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, void *));
+void gpib_free_pseudo_irq(gpib_board_t *board);
+int gpib_match_device_path(struct device *dev, const char *device_path_in);
+
+extern gpib_board_t board_array[GPIB_MAX_NUM_BOARDS];
+
+extern struct list_head registered_drivers;
+
+#ifdef GPIB_DEBUG
+#define GPIB_DPRINTK(format, args...) pr_info("gpib debug: " format, ## args)
+#else
+#define GPIB_DPRINTK(arg...)
+#endif
+
+#include <linux/io.h>
+
+void writeb_wrapper(unsigned int value, void *address);
+unsigned int readb_wrapper(void *address);
+void outb_wrapper(unsigned int value, void *address);
+unsigned int inb_wrapper(void *address);
+void writew_wrapper(unsigned int value, void *address);
+unsigned int readw_wrapper(void *address);
+void outw_wrapper(unsigned int value, void *address);
+unsigned int inw_wrapper(void *address);
+
+#endif // _GPIB_P_H
+
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __GPIB_PCI_IDS_H
+#define __GPIB_LINUX_PCI_IDS_H
+
+#ifndef PCI_VENDOR_ID_AMCC
+#define PCI_VENDOR_ID_AMCC 0x10e8
+#endif
+
+#ifndef PCI_VENDOR_ID_CBOARDS
+#define PCI_VENDOR_ID_CBOARDS 0x1307
+#endif
+
+#ifndef PCI_VENDOR_ID_QUANCOM
+#define PCI_VENDOR_ID_QUANCOM 0x8008
+#endif
+
+#ifndef PCI_DEVICE_ID_QUANCOM_GPIB
+#define PCI_DEVICE_ID_QUANCOM_GPIB 0x3302
+#endif
+
+#endif // __GPIB_PCI_IDS_H
+
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef GPIB_PROTO_INCLUDED
+#define GPIB_PROTO_INCLUDED
+
+#include <linux/fs.h>
+
+int ibopen(struct inode *inode, struct file *filep);
+int ibclose(struct inode *inode, struct file *file);
+long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg);
+int osInit(void);
+void osReset(void);
+void os_start_timer(gpib_board_t *board, unsigned int usec_timeout);
+void os_remove_timer(gpib_board_t *board);
+void osSendEOI(void);
+void osSendEOI(void);
+void init_gpib_board(gpib_board_t *board);
+static inline unsigned long usec_to_jiffies(unsigned int usec)
+{
+ unsigned long usec_per_jiffy = 1000000 / HZ;
+
+ return 1 + (usec + usec_per_jiffy - 1) / usec_per_jiffy;
+};
+
+int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout);
+void init_gpib_descriptor(gpib_descriptor_t *desc);
+int dvrsp(gpib_board_t *board, unsigned int pad, int sad,
+ unsigned int usec_timeout, uint8_t *result);
+int ibAPWait(gpib_board_t *board, int pad);
+int ibAPrsp(gpib_board_t *board, int padsad, char *spb);
+void ibAPE(gpib_board_t *board, int pad, int v);
+int ibcac(gpib_board_t *board, int sync, int fallback_to_async);
+int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_written);
+int ibgts(gpib_board_t *board);
+int ibonline(gpib_board_t *board);
+int iboffline(gpib_board_t *board);
+int iblines(const gpib_board_t *board, short *lines);
+int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *bytes_read);
+int ibrpp(gpib_board_t *board, uint8_t *buf);
+int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service);
+void ibrsc(gpib_board_t *board, int request_control);
+int ibsic(gpib_board_t *board, unsigned int usec_duration);
+int ibsre(gpib_board_t *board, int enable);
+int ibpad(gpib_board_t *board, unsigned int addr);
+int ibsad(gpib_board_t *board, int addr);
+int ibeos(gpib_board_t *board, int eos, int eosflags);
+int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask,
+ int *status, unsigned long usec_timeout, gpib_descriptor_t *desc);
+int ibwrt(gpib_board_t *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written);
+int ibstatus(gpib_board_t *board);
+int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device,
+ int clear_mask, int set_mask, gpib_descriptor_t *desc);
+int io_timed_out(gpib_board_t *board);
+int ibppc(gpib_board_t *board, uint8_t configuration);
+
+#endif /* GPIB_PROTO_INCLUDED */
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2006 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_STATE_MACHINES_H
+#define _GPIB_STATE_MACHINES_H
+
+enum talker_function_state {
+ talker_idle,
+ talker_addressed,
+ talker_active,
+ serial_poll_active
+};
+
+enum listener_function_state {
+ listener_idle,
+ listener_addressed,
+ listener_active
+};
+
+#endif // _GPIB_STATE_MACHINES_H
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_TYPES_H
+#define _GPIB_TYPES_H
+
+#ifdef __KERNEL__
+/* gpib_interface_t 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.
+ */
+#include "gpib_user.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>
+
+typedef struct gpib_interface_struct gpib_interface_t;
+typedef struct gpib_board_struct gpib_board_t;
+
+/* config parameters that are only used by driver attach functions */
+typedef struct {
+ /* 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) */
+ void *ibbase;
+ /* 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;
+} gpib_board_config_t;
+
+struct gpib_interface_struct {
+ /* name of board */
+ char *name;
+ /* attach() initializes board and allocates resources */
+ int (*attach)(gpib_board_t *board, const gpib_board_config_t *config);
+ /* detach() shuts down board and frees resources */
+ void (*detach)(gpib_board_t *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)(gpib_board_t *board, uint8_t *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)(gpib_board_t *board, uint8_t *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)(gpib_board_t *board, uint8_t *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)(gpib_board_t *board, int asyncronous);
+ /* De-assert ATN. Returns zero on success, nonzer on error.
+ */
+ int (*go_to_standby)(gpib_board_t *board);
+ /* request/release control of the IFC and REN lines (system controller) */
+ void (*request_system_control)(gpib_board_t *board, int request_control);
+ /* Asserts or de-asserts 'interface clear' (IFC) depending on
+ * boolean value of 'assert'
+ */
+ void (*interface_clear)(gpib_board_t *board, int assert);
+ /* Sends remote enable command if 'enable' is nonzero, disables remote mode
+ * if 'enable' is zero
+ */
+ void (*remote_enable)(gpib_board_t *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)(gpib_board_t *board, uint8_t eos, int compare_8_bits);
+ /* disable END on eos byte (END on EOI only)*/
+ void (*disable_eos)(gpib_board_t *board);
+ /* configure parallel poll */
+ void (*parallel_poll_configure)(gpib_board_t *board, uint8_t configuration);
+ /* conduct parallel poll */
+ int (*parallel_poll)(gpib_board_t *board, uint8_t *result);
+ /* set/clear ist (individual status bit) */
+ void (*parallel_poll_response)(gpib_board_t *board, int ist);
+ /* select local parallel poll configuration mode PP2 versus remote PP1 */
+ void (*local_parallel_poll_mode)(gpib_board_t *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 gpib_board_t *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)(gpib_board_t *board, unsigned int clear_mask);
+ /* Sets primary address 0-30 for gpib interface card.
+ */
+ int (*primary_address)(gpib_board_t *board, unsigned int address);
+ /* Sets and enables, or disables secondary address 0-30
+ * for gpib interface card.
+ */
+ int (*secondary_address)(gpib_board_t *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)(gpib_board_t *board, uint8_t 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)(gpib_board_t *board, uint8_t status_byte,
+ int new_reason_for_service);
+ /* returns the byte the board will send in response to a serial poll.
+ */
+ uint8_t (*serial_poll_status)(gpib_board_t *board);
+ /* adjust T1 delay */
+ unsigned int (*t1_delay)(gpib_board_t *board, unsigned int nano_sec);
+ /* go to local mode */
+ void (*return_to_local)(gpib_board_t *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;
+};
+
+typedef struct {
+ struct list_head event_head;
+ spinlock_t lock; // for access to event list
+ unsigned int num_events;
+ unsigned dropped_event : 1;
+} gpib_event_queue_t;
+
+static inline void init_event_queue(gpib_event_queue_t *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);
+ gpib_board_t *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 */
+typedef struct gpib_interface_list_struct {
+ struct list_head list;
+ gpib_interface_t *interface;
+ struct module *module;
+} gpib_interface_list_t;
+
+/* One gpib_board_t 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_struct {
+ /* functions used by this board */
+ gpib_interface_t *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;
+ spinlock_t locking_pid_spinlock; // lock for setting locking pid
+ /* 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 */
+ gpib_event_queue_t 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;
+ gpib_board_config_t 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 */
+typedef struct {
+ struct list_head list;
+ short event_type;
+} gpib_event_t;
+
+/* Each board has a list of gpib_status_queue_t to keep track of all open devices
+ * on the bus, so we know what address to poll when we get a service request
+ */
+typedef struct {
+ /* 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;
+} gpib_status_queue_t;
+
+typedef struct {
+ struct list_head list;
+ u8 poll_byte;
+} status_byte_t;
+
+void init_gpib_status_queue(gpib_status_queue_t *device);
+
+/* Used to store device-descriptor-specific information */
+typedef struct {
+ unsigned int pad; /* primary gpib address */
+ int sad; /* secondary gpib address (negative means disabled) */
+ atomic_t io_in_progress;
+ unsigned is_board : 1;
+ unsigned autopoll_enabled : 1;
+} gpib_descriptor_t;
+
+typedef struct {
+ atomic_t holding_mutex;
+ gpib_descriptor_t *descriptors[GPIB_MAX_NUM_DESCRIPTORS];
+ /* locked while descriptors are being allocated/deallocated */
+ struct mutex descriptors_mutex;
+ unsigned got_module : 1;
+} gpib_file_private_t;
+
+#endif /* __KERNEL__ */
+
+#endif /* _GPIB_TYPES_H */
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _NEC7210_H
+#define _NEC7210_H
+
+#include "gpib_state_machines.h"
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+
+#include "gpib_types.h"
+#include "nec7210_registers.h"
+
+/* struct used to provide variables local to a nec7210 chip */
+struct nec7210_priv {
+ void *iobase;
+ unsigned int offset; // offset between successive nec7210 io addresses
+ unsigned int dma_channel;
+ u8 *dma_buffer;
+ unsigned int dma_buffer_length; // length of dma buffer
+ dma_addr_t dma_buffer_addr; // bus address of board->buffer for use with dma
+ // software copy of bits written to registers
+ u8 reg_bits[8];
+ u8 auxa_bits; // bits written to auxiliary register A
+ u8 auxb_bits; // bits written to auxiliary register B
+ // used to keep track of board's state, bit definitions given below
+ unsigned long state;
+ /* lock for chips that extend the nec7210 registers by paging in alternate regs */
+ spinlock_t register_page_lock;
+ // wrappers for outb, inb, readb, or writeb
+ u8 (*read_byte)(struct nec7210_priv *priv, unsigned int register_number);
+ void (*write_byte)(struct nec7210_priv *priv, u8 byte, unsigned int register_number);
+ enum nec7210_chipset type;
+ enum talker_function_state talker_state;
+ enum listener_function_state listener_state;
+ void *private;
+ unsigned srq_pending : 1;
+};
+
+static inline void init_nec7210_private(struct nec7210_priv *priv)
+{
+ memset(priv, 0, sizeof(struct nec7210_priv));
+ spin_lock_init(&priv->register_page_lock);
+}
+
+// slightly shorter way to access read_byte and write_byte
+static inline u8 read_byte(struct nec7210_priv *priv, unsigned int register_number)
+{
+ return priv->read_byte(priv, register_number);
+}
+
+static inline void write_byte(struct nec7210_priv *priv, u8 byte, unsigned int register_number)
+{
+ priv->write_byte(priv, byte, register_number);
+}
+
+// struct nec7210_priv.state bit numbers
+enum {
+ PIO_IN_PROGRESS_BN, // pio transfer in progress
+ DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress
+ DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress
+ READ_READY_BN, // board has data byte available to read
+ WRITE_READY_BN, // board is ready to send a data byte
+ COMMAND_READY_BN, // board is ready to send a command byte
+ RECEIVED_END_BN, // received END
+ BUS_ERROR_BN, // output error has occurred
+ RFD_HOLDOFF_BN, // rfd holdoff in effect
+ DEV_CLEAR_BN, // device clear received
+ ADR_CHANGE_BN, // address state change occurred
+};
+
+// interface functions
+int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read);
+int nec7210_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written);
+int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written);
+int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syncronous);
+int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv);
+void nec7210_request_system_control(gpib_board_t *board,
+ struct nec7210_priv *priv, int request_control);
+void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int assert);
+void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int enable);
+int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t eos_bytes,
+ int compare_8_bits);
+void nec7210_disable_eos(gpib_board_t *board, struct nec7210_priv *priv);
+unsigned int nec7210_update_status(gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int clear_mask);
+unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_priv *priv);
+int nec7210_primary_address(const gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int address);
+int nec7210_secondary_address(const gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int address, int enable);
+int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *result);
+void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv, uint8_t status);
+void nec7210_parallel_poll_configure(gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int configuration);
+void nec7210_parallel_poll_response(gpib_board_t *board,
+ struct nec7210_priv *priv, int ist);
+uint8_t nec7210_serial_poll_status(gpib_board_t *board,
+ struct nec7210_priv *priv);
+unsigned int nec7210_t1_delay(gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int nano_sec);
+void nec7210_return_to_local(const gpib_board_t *board, struct nec7210_priv *priv);
+
+// utility functions
+void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board);
+void nec7210_board_online(struct nec7210_priv *priv, const gpib_board_t *board);
+unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg,
+ unsigned int mask, unsigned int bits);
+void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, int mode);
+void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv);
+uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int *end);
+
+// wrappers for io functions
+uint8_t nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_ioport_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num);
+uint8_t nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num);
+uint8_t nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num);
+uint8_t nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num);
+
+// interrupt service routine
+irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv);
+irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board,
+ struct nec7210_priv *priv, int status1, int status2);
+
+#endif //_NEC7210_H
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _NEC7210_REGISTERS_H
+#define _NEC7210_REGISTERS_H
+
+enum nec7210_chipset {
+ NEC7210, // The original
+ TNT4882, // NI
+ NAT4882, // NI
+ CB7210, // measurement computing
+ IOT7210, // iotech
+ IGPIB7210, // Ines
+ TNT5004, // NI (minor differences to TNT4882)
+};
+
+// nec7210 has 8 registers
+static const int nec7210_num_registers = 8;
+
+/* nec7210 register numbers (might need to be multiplied by
+ * a board-dependent offset to get actually io address offset)
+ */
+// write registers
+enum nec7210_write_regs {
+ CDOR, // command/data out
+ IMR1, // interrupt mask 1
+ IMR2, // interrupt mask 2
+ SPMR, // serial poll mode
+ ADMR, // address mode
+ AUXMR, // auxiliary mode
+ ADR, // address
+ EOSR, // end-of-string
+};
+
+// read registers
+enum nec7210_read_regs {
+ DIR, // data in
+ ISR1, // interrupt status 1
+ ISR2, // interrupt status 2
+ SPSR, // serial poll status
+ ADSR, // address status
+ CPTR, // command pass though
+ ADR0, // address 1
+ ADR1, // address 2
+};
+
+//bit definitions common to nec-7210 compatible registers
+
+// ISR1: interrupt status register 1
+enum isr1_bits {
+ HR_DI = (1 << 0),
+ HR_DO = (1 << 1),
+ HR_ERR = (1 << 2),
+ HR_DEC = (1 << 3),
+ HR_END = (1 << 4),
+ HR_DET = (1 << 5),
+ HR_APT = (1 << 6),
+ HR_CPT = (1 << 7),
+};
+
+// IMR1: interrupt mask register 1
+enum imr1_bits {
+ HR_DIIE = (1 << 0),
+ HR_DOIE = (1 << 1),
+ HR_ERRIE = (1 << 2),
+ HR_DECIE = (1 << 3),
+ HR_ENDIE = (1 << 4),
+ HR_DETIE = (1 << 5),
+ HR_APTIE = (1 << 6),
+ HR_CPTIE = (1 << 7),
+};
+
+// ISR2, interrupt status register 2
+enum isr2_bits {
+ HR_ADSC = (1 << 0),
+ HR_REMC = (1 << 1),
+ HR_LOKC = (1 << 2),
+ HR_CO = (1 << 3),
+ HR_REM = (1 << 4),
+ HR_LOK = (1 << 5),
+ HR_SRQI = (1 << 6),
+ HR_INT = (1 << 7),
+};
+
+// IMR2, interrupt mask register 2
+enum imr2_bits {
+ // all the bits in this register that enable interrupts
+ IMR2_ENABLE_INTR_MASK = 0x4f,
+ HR_ACIE = (1 << 0),
+ HR_REMIE = (1 << 1),
+ HR_LOKIE = (1 << 2),
+ HR_COIE = (1 << 3),
+ HR_DMAI = (1 << 4),
+ HR_DMAO = (1 << 5),
+ HR_SRQIE = (1 << 6),
+};
+
+// SPSR, serial poll status register
+enum spsr_bits {
+ HR_PEND = (1 << 6),
+};
+
+// SPMR, serial poll mode register
+enum spmr_bits {
+ HR_RSV = (1 << 6),
+};
+
+// ADSR, address status register
+enum adsr_bits {
+ HR_MJMN = (1 << 0),
+ HR_TA = (1 << 1),
+ HR_LA = (1 << 2),
+ HR_TPAS = (1 << 3),
+ HR_LPAS = (1 << 4),
+ HR_SPMS = (1 << 5),
+ HR_NATN = (1 << 6),
+ HR_CIC = (1 << 7),
+};
+
+// ADMR, address mode register
+enum admr_bits {
+ HR_ADM0 = (1 << 0),
+ HR_ADM1 = (1 << 1),
+ HR_TRM0 = (1 << 4),
+ HR_TRM1 = (1 << 5),
+ HR_TRM_EOIOE_TRIG = 0,
+ HR_TRM_CIC_TRIG = HR_TRM0,
+ HR_TRM_CIC_EOIOE = HR_TRM1,
+ HR_TRM_CIC_PE = HR_TRM0 | HR_TRM1,
+ HR_LON = (1 << 6),
+ HR_TON = (1 << 7),
+};
+
+// ADR, bits used in address0, address1 and address0/1 registers
+enum adr_bits {
+ ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits */
+ HR_DL = (1 << 5),
+ HR_DT = (1 << 6),
+ HR_ARS = (1 << 7),
+};
+
+// ADR1, address1 register
+enum adr1_bits {
+ HR_EOI = (1 << 7),
+};
+
+// AUXMR, auxiliary mode register
+enum auxmr_bits {
+ ICR = 0x20,
+ PPR = 0x60,
+ AUXRA = 0x80,
+ AUXRB = 0xa0,
+ AUXRE = 0xc0,
+};
+
+// auxra, auxiliary register A
+enum auxra_bits {
+ HR_HANDSHAKE_MASK = 0x3,
+ HR_HLDA = 0x1,
+ HR_HLDE = 0x2,
+ HR_LCM = 0x3, /* auxra listen continuous */
+ HR_REOS = 0x4,
+ HR_XEOS = 0x8,
+ HR_BIN = 0x10,
+};
+
+// auxrb, auxiliary register B
+enum auxrb_bits {
+ HR_CPTE = (1 << 0),
+ HR_SPEOI = (1 << 1),
+ HR_TRI = (1 << 2),
+ HR_INV = (1 << 3),
+ HR_ISS = (1 << 4),
+};
+
+enum auxre_bits {
+ HR_DAC_HLD_DCAS = 0x1, /* perform DAC holdoff on receiving clear */
+ HR_DAC_HLD_DTAS = 0x2, /* perform DAC holdoff on receiving trigger */
+};
+
+// parallel poll register
+enum ppr_bits {
+ HR_PPS = (1 << 3),
+ HR_PPU = (1 << 4),
+};
+
+/* 7210 Auxiliary Commands */
+enum aux_cmds {
+ AUX_PON = 0x0, /* Immediate Execute pon */
+ AUX_CPPF = 0x1, /* Clear Parallel Poll Flag */
+ AUX_CR = 0x2, /* Chip Reset */
+ AUX_FH = 0x3, /* Finish Handshake */
+ AUX_TRIG = 0x4, /* Trigger */
+ AUX_RTL = 0x5, /* Return to local */
+ AUX_SEOI = 0x6, /* Send EOI */
+ AUX_NVAL = 0x7, /* Non-Valid Secondary Command or Address */
+ AUX_SPPF = 0x9, /* Set Parallel Poll Flag */
+ AUX_VAL = 0xf, /* Valid Secondary Command or Address */
+ AUX_GTS = 0x10, /* Go To Standby */
+ AUX_TCA = 0x11, /* Take Control Asynchronously */
+ AUX_TCS = 0x12, /* Take Control Synchronously */
+ AUX_LTN = 0x13, /* Listen */
+ AUX_DSC = 0x14, /* Disable System Control */
+ AUX_CIFC = 0x16, /* Clear IFC */
+ AUX_CREN = 0x17, /* Clear REN */
+ AUX_TCSE = 0x1a, /* Take Control Synchronously on End */
+ AUX_LTNC = 0x1b, /* Listen in Continuous Mode */
+ AUX_LUN = 0x1c, /* Local Unlisten */
+ AUX_EPP = 0x1d, /* Execute Parallel Poll */
+ AUX_SIFC = 0x1e, /* Set IFC */
+ AUX_SREN = 0x1f, /* Set REN */
+};
+
+#endif //_NEC7210_REGISTERS_H
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Header for plx9050 pci chip
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _PLX9050_GPIB_H
+#define _PLX9050_GPIB_H
+
+// plx pci chip registers and bits
+enum {
+ PLX9050_INTCSR_REG = 0x4c,
+ PLX9050_CNTRL_REG = 0x50
+};
+
+enum plx9050_intcsr_bits {
+ PLX9050_LINTR1_EN_BIT = 0x1,
+ PLX9050_LINTR1_POLARITY_BIT = 0x2,
+ PLX9050_LINTR1_STATUS_BIT = 0x4,
+ PLX9050_LINTR2_EN_BIT = 0x8,
+ PLX9050_LINTR2_POLARITY_BIT = 0x10,
+ PLX9050_LINTR2_STATUS_BIT = 0x20,
+ PLX9050_PCI_INTR_EN_BIT = 0x40,
+ PLX9050_SOFT_INTR_BIT = 0x80,
+ PLX9050_LINTR1_SELECT_ENABLE_BIT = 0x100, //9052 extension
+ PLX9050_LINTR2_SELECT_ENABLE_BIT = 0x200, //9052 extension
+ PLX9050_LINTR1_EDGE_CLEAR_BIT = 0x400, //9052 extension
+ PLX9050_LINTR2_EDGE_CLEAR_BIT = 0x800, //9052 extension
+};
+
+enum plx9050_cntrl_bits {
+ PLX9050_WAITO_NOT_USER0_SELECT_BIT = 0x1,
+ PLX9050_USER0_OUTPUT_BIT = 0x2,
+ PLX9050_USER0_DATA_BIT = 0x4,
+ PLX9050_LLOCK_NOT_USER1_SELECT_BIT = 0x8,
+ PLX9050_USER1_OUTPUT_BIT = 0x10,
+ PLX9050_USER1_DATA_BIT = 0x20,
+ PLX9050_CS2_NOT_USER2_SELECT_BIT = 0x40,
+ PLX9050_USER2_OUTPUT_BIT = 0x80,
+ PLX9050_USER2_DATA_BIT = 0x100,
+ PLX9050_CS3_NOT_USER3_SELECT_BIT = 0x200,
+ PLX9050_USER3_OUTPUT_BIT = 0x400,
+ PLX9050_USER3_DATA_BIT = 0x800,
+ PLX9050_PCIBAR_ENABLE_MASK = 0x3000,
+ PLX9050_PCIBAR_MEMORY_AND_IO_ENABLE_BITS = 0x0,
+ PLX9050_PCIBAR_MEMORY_NO_IO_ENABLE_BITS = 0x1000,
+ PLX9050_PCIBAR_IO_NO_MEMORY_ENABLE_BITS = 0x2000,
+ PLX9050_PCIBAR_MEMORY_AND_IO_TOO_ENABLE_BITS = 0x3000,
+ PLX9050_PCI_READ_MODE_BIT = 0x4000,
+ PLX9050_PCI_READ_WITH_WRITE_FLUSH_MODE_BIT = 0x8000,
+ PLX9050_PCI_READ_NO_FLUSH_MODE_BIT = 0x10000,
+ PLX9050_PCI_READ_NO_WRITE_MODE_BIT = 0x20000,
+ PLX9050_PCI_WRITE_MODE_BIT = 0x40000,
+ PLX9050_PCI_RETRY_DELAY_MASK = 0x780000,
+ PLX9050_DIRECT_SLAVE_LOCK_ENABLE_BIT = 0x800000,
+ PLX9050_EEPROM_CLOCK_BIT = 0x1000000,
+ PLX9050_EEPROM_CHIP_SELECT_BIT = 0x2000000,
+ PLX9050_WRITE_TO_EEPROM_BIT = 0x4000000,
+ PLX9050_READ_EEPROM_DATA_BIT = 0x8000000,
+ PLX9050_EEPROM_VALID_BIT = 0x10000000,
+ PLX9050_RELOAD_CONFIG_REGISTERS_BIT = 0x20000000,
+ PLX9050_PCI_SOFTWARE_RESET_BIT = 0x40000000,
+ PLX9050_MASK_REVISION_BIT = 0x80000000
+};
+
+static inline unsigned int PLX9050_PCI_RETRY_DELAY_BITS(unsigned int clocks)
+{
+ return ((clocks / 8) << 19) & PLX9050_PCI_RETRY_DELAY_MASK;
+}
+
+#endif // _PLX9050_GPIB_H
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Quancom pci stuff
+ * copyright (C) 2005 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _QUANCOM_PCI_H
+#define _QUANCOM_PCI_H
+
+/* quancom registers */
+enum quancom_regs {
+ QUANCOM_IRQ_CONTROL_STATUS_REG = 0xfc,
+};
+
+enum quancom_irq_control_status_bits {
+ QUANCOM_IRQ_ASSERTED_BIT = 0x1, /* readable */
+ /* (any write to the register clears the interrupt)*/
+ QUANCOM_IRQ_ENABLE_BIT = 0x4, /* writeable */
+};
+
+#endif // _QUANCOM_PCI_H
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _TMS9914_H
+#define _TMS9914_H
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include "gpib_state_machines.h"
+#include "gpib_types.h"
+
+enum tms9914_holdoff_mode {
+ TMS9914_HOLDOFF_NONE,
+ TMS9914_HOLDOFF_EOI,
+ TMS9914_HOLDOFF_ALL,
+};
+
+/* struct used to provide variables local to a tms9914 chip */
+struct tms9914_priv {
+ void *iobase;
+ unsigned int offset; // offset between successive tms9914 io addresses
+ unsigned int dma_channel;
+ // software copy of bits written to interrupt mask registers
+ u8 imr0_bits, imr1_bits;
+ // bits written to address mode register
+ u8 admr_bits;
+ u8 auxa_bits; // bits written to auxiliary register A
+ // used to keep track of board's state, bit definitions given below
+ unsigned long state;
+ u8 eos; // eos character
+ short eos_flags;
+ u8 spoll_status;
+ enum tms9914_holdoff_mode holdoff_mode;
+ unsigned int ppoll_line;
+ enum talker_function_state talker_state;
+ enum listener_function_state listener_state;
+ unsigned ppoll_sense : 1;
+ unsigned ppoll_enable : 1;
+ unsigned ppoll_configure_state : 1;
+ unsigned primary_listen_addressed : 1;
+ unsigned primary_talk_addressed : 1;
+ unsigned holdoff_on_end : 1;
+ unsigned holdoff_on_all : 1;
+ unsigned holdoff_active : 1;
+ // wrappers for outb, inb, readb, or writeb
+ u8 (*read_byte)(struct tms9914_priv *priv, unsigned int register_number);
+ void (*write_byte)(struct tms9914_priv *priv, u8 byte, unsigned int
+ register_number);
+};
+
+// slightly shorter way to access read_byte and write_byte
+static inline u8 read_byte(struct tms9914_priv *priv, unsigned int register_number)
+{
+ return priv->read_byte(priv, register_number);
+}
+
+static inline void write_byte(struct tms9914_priv *priv, u8 byte, unsigned int register_number)
+{
+ priv->write_byte(priv, byte, register_number);
+}
+
+// struct tms9914_priv.state bit numbers
+enum {
+ PIO_IN_PROGRESS_BN, // pio transfer in progress
+ DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress
+ DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress
+ READ_READY_BN, // board has data byte available to read
+ WRITE_READY_BN, // board is ready to send a data byte
+ COMMAND_READY_BN, // board is ready to send a command byte
+ RECEIVED_END_BN, // received END
+ BUS_ERROR_BN, // bus error
+ DEV_CLEAR_BN, // device clear received
+};
+
+// interface functions
+int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read);
+int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written);
+int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written);
+int tms9914_take_control(gpib_board_t *board, struct tms9914_priv *priv, int syncronous);
+/* alternate version of tms9914_take_control which works around buggy tcs
+ * implementation.
+ */
+int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *priv,
+ int syncronous);
+int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv);
+void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *priv,
+ int request_control);
+void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int assert);
+void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int enable);
+int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t eos_bytes,
+ int compare_8_bits);
+void tms9914_disable_eos(gpib_board_t *board, struct tms9914_priv *priv);
+unsigned int tms9914_update_status(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int clear_mask);
+int tms9914_primary_address(gpib_board_t *board,
+ struct tms9914_priv *priv, unsigned int address);
+int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int address, int enable);
+int tms9914_parallel_poll(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *result);
+void tms9914_parallel_poll_configure(gpib_board_t *board,
+ struct tms9914_priv *priv, uint8_t config);
+void tms9914_parallel_poll_response(gpib_board_t *board,
+ struct tms9914_priv *priv, int ist);
+void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv, uint8_t status);
+uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *priv);
+int tms9914_line_status(const gpib_board_t *board, struct tms9914_priv *priv);
+unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int nano_sec);
+void tms9914_return_to_local(const gpib_board_t *board, struct tms9914_priv *priv);
+
+// utility functions
+void tms9914_board_reset(struct tms9914_priv *priv);
+void tms9914_online(gpib_board_t *board, struct tms9914_priv *priv);
+void tms9914_release_holdoff(struct tms9914_priv *priv);
+void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode);
+
+// wrappers for io functions
+uint8_t tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num);
+void tms9914_ioport_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num);
+uint8_t tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num);
+void tms9914_iomem_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num);
+
+// interrupt service routine
+irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv);
+irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_priv *priv,
+ int status1, int status2);
+
+// tms9914 has 8 registers
+static const int tms9914_num_registers = 8;
+
+/* tms9914 register numbers (might need to be multiplied by
+ * a board-dependent offset to get actually io address offset)
+ */
+// write registers
+enum {
+ IMR0 = 0, /* interrupt mask 0 */
+ IMR1 = 1, /* interrupt mask 1 */
+ AUXCR = 3, /* auxiliary command */
+ ADR = 4, // address register
+ SPMR = 5, // serial poll mode register
+ PPR = 6, /* parallel poll */
+ CDOR = 7, /* data out register */
+};
+
+// read registers
+enum {
+ ISR0 = 0, /* interrupt status 0 */
+ ISR1 = 1, /* interrupt status 1 */
+ ADSR = 2, /* address status */
+ BSR = 3, /* bus status */
+ CPTR = 6, /* command pass thru */
+ DIR = 7, /* data in register */
+};
+
+//bit definitions common to tms9914 compatible registers
+
+/* ISR0 - Register bits */
+enum isr0_bits {
+ HR_MAC = (1 << 0), /* My Address Change */
+ HR_RLC = (1 << 1), /* Remote/Local change */
+ HR_SPAS = (1 << 2), /* Serial Poll active State */
+ HR_END = (1 << 3), /* END (EOI or EOS) */
+ HR_BO = (1 << 4), /* Byte Out */
+ HR_BI = (1 << 5), /* Byte In */
+};
+
+/* IMR0 - Register bits */
+enum imr0_bits {
+ HR_MACIE = (1 << 0), /* */
+ HR_RLCIE = (1 << 1), /* */
+ HR_SPASIE = (1 << 2), /* */
+ HR_ENDIE = (1 << 3), /* */
+ HR_BOIE = (1 << 4), /* */
+ HR_BIIE = (1 << 5), /* */
+};
+
+/* ISR1 - Register bits */
+enum isr1_bits {
+ HR_IFC = (1 << 0), /* IFC asserted */
+ HR_SRQ = (1 << 1), /* SRQ asserted */
+ HR_MA = (1 << 2), /* My Address */
+ HR_DCAS = (1 << 3), /* Device Clear active State */
+ HR_APT = (1 << 4), /* Address pass Through */
+ HR_UNC = (1 << 5), /* Unrecognized Command */
+ HR_ERR = (1 << 6), /* Data Transmission Error */
+ HR_GET = (1 << 7), /* Group execute Trigger */
+};
+
+/* IMR1 - Register bits */
+enum imr1_bits {
+ HR_IFCIE = (1 << 0), /* */
+ HR_SRQIE = (1 << 1), /* */
+ HR_MAIE = (1 << 2), /* */
+ HR_DCASIE = (1 << 3), /* */
+ HR_APTIE = (1 << 4), /* */
+ HR_UNCIE = (1 << 5), /* */
+ HR_ERRIE = (1 << 6), /* */
+ HR_GETIE = (1 << 7), /* */
+};
+
+/* ADSR - Register bits */
+enum adsr_bits {
+ HR_ULPA = (1 << 0), /* Store last address LSB */
+ HR_TA = (1 << 1), /* Talker Adressed */
+ HR_LA = (1 << 2), /* Listener adressed */
+ HR_TPAS = (1 << 3), /* talker primary address state */
+ HR_LPAS = (1 << 4), /* listener " */
+ HR_ATN = (1 << 5), /* ATN active */
+ HR_LLO = (1 << 6), /* LLO active */
+ HR_REM = (1 << 7), /* REM active */
+};
+
+/* ADR - Register bits */
+enum adr_bits {
+ ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits for ADR */
+ HR_DAT = (1 << 5), /* disable talker */
+ HR_DAL = (1 << 6), /* disable listener */
+ HR_EDPA = (1 << 7), /* enable dual primary addressing */
+};
+
+enum bus_status_bits {
+ BSR_REN_BIT = 0x1,
+ BSR_IFC_BIT = 0x2,
+ BSR_SRQ_BIT = 0x4,
+ BSR_EOI_BIT = 0x8,
+ BSR_NRFD_BIT = 0x10,
+ BSR_NDAC_BIT = 0x20,
+ BSR_DAV_BIT = 0x40,
+ BSR_ATN_BIT = 0x80,
+};
+
+/*---------------------------------------------------------*/
+/* TMS 9914 Auxiliary Commands */
+/*---------------------------------------------------------*/
+
+enum aux_cmd_bits {
+ AUX_CS = 0x80, /* set bit instead of clearing it, used with commands marked 'd' below */
+ AUX_CHIP_RESET = 0x0, /* d Chip reset */
+ AUX_INVAL = 0x1, // release dac holdoff, invalid command byte
+ AUX_VAL = (AUX_INVAL | AUX_CS), // release dac holdoff, valid command byte
+ AUX_RHDF = 0x2, /* X Release RFD holdoff */
+ AUX_HLDA = 0x3, /* d holdoff on all data */
+ AUX_HLDE = 0x4, /* d holdoff on EOI only */
+ AUX_NBAF = 0x5, /* X Set new byte available false */
+ AUX_FGET = 0x6, /* d force GET */
+ AUX_RTL = 0x7, /* d return to local */
+ AUX_SEOI = 0x8, /* X send EOI with next byte */
+ AUX_LON = 0x9, /* d Listen only */
+ AUX_TON = 0xa, /* d Talk only */
+ AUX_GTS = 0xb, /* X goto standby */
+ AUX_TCA = 0xc, /* X take control asynchronously */
+ AUX_TCS = 0xd, /* X take " synchronously */
+ AUX_RPP = 0xe, /* d Request parallel poll */
+ AUX_SIC = 0xf, /* d send interface clear */
+ AUX_SRE = 0x10, /* d send remote enable */
+ AUX_RQC = 0x11, /* X request control */
+ AUX_RLC = 0x12, /* X release control */
+ AUX_DAI = 0x13, /* d disable all interrupts */
+ AUX_PTS = 0x14, /* X pass through next secondary */
+ AUX_STDL = 0x15, /* d short T1 delay */
+ AUX_SHDW = 0x16, /* d shadow handshake */
+ AUX_VSTDL = 0x17, /* d very short T1 delay (smj9914 extension) */
+ AUX_RSV2 = 0x18, /* d request service bit 2 (smj9914 extension) */
+};
+
+#endif //_TMS9914_H
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002, 2004 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _TNT4882_REGISTERS_H
+#define _TNT4882_REGISTERS_H
+
+// tnt4882 register offsets
+enum {
+ ACCWR = 0x5,
+ // offset of auxiliary command register in 9914 mode
+ AUXCR = 0x6,
+ INTRT = 0x7,
+ // register number for auxiliary command register when swap bit is set (9914 mode)
+ SWAPPED_AUXCR = 0xa,
+ HSSEL = 0xd, // handshake select register
+ CNT2 = 0x9,
+ CNT3 = 0xb,
+ CFG = 0x10,
+ SASR = 0x1b,
+ IMR0 = 0x1d,
+ IMR3 = 0x12,
+ CNT0 = 0x14,
+ CNT1 = 0x16,
+ KEYREG = 0x17, // key control register (7210 mode only)
+ CSR = KEYREG,
+ FIFOB = 0x18,
+ FIFOA = 0x19,
+ CCR = 0x1a, // carry cycle register
+ CMDR = 0x1c, // command register
+ TIMER = 0x1e, // timer register
+
+ STS1 = 0x10, /* T488 Status Register 1 */
+ STS2 = 0x1c, /* T488 Status Register 2 */
+ ISR0 = IMR0,
+ ISR3 = 0x1a, /* T488 Interrupt Status Register 3 */
+ BCR = 0x1f, /* bus control/status register */
+ BSR = BCR,
+};
+
+static const int tnt_pagein_offset = 0x11;
+
+/*============================================================*/
+
+/* TURBO-488 registers bit definitions */
+
+enum bus_control_status_bits {
+ BCSR_REN_BIT = 0x1,
+ BCSR_IFC_BIT = 0x2,
+ BCSR_SRQ_BIT = 0x4,
+ BCSR_EOI_BIT = 0x8,
+ BCSR_NRFD_BIT = 0x10,
+ BCSR_NDAC_BIT = 0x20,
+ BCSR_DAV_BIT = 0x40,
+ BCSR_ATN_BIT = 0x80,
+};
+
+/* CFG -- Configuration Register (write only) */
+enum cfg_bits {
+ TNT_COMMAND = 0x80, /* bytes are command bytes instead of data bytes
+ * (tnt4882 one-chip and newer only?)
+ */
+ TNT_TLCHE = (1 << 6), /* halt transfer on imr0, imr1, or imr2 interrupt */
+ TNT_IN = (1 << 5), /* transfer is GPIB read */
+ TNT_A_B = (1 << 4), /* order to use fifos 1=fifo A first(big endian),
+ * 0=fifo b first(little endian)
+ */
+ TNT_CCEN = (1 << 3), /* enable carry cycle */
+ TNT_TMOE = (1 << 2), /* enable CPU bus time limit */
+ TNT_TIM_BYTN = (1 << 1), /* tmot reg is: 1=125ns clocks, 0=num bytes */
+ TNT_B_16BIT = (1 << 0), /* 1=FIFO is 16-bit register, 0=8-bit */
+};
+
+/* CMDR -- Command Register */
+enum cmdr_bits {
+ CLRSC = 0x2, /* clear the system controller bit */
+ SETSC = 0x3, /* set the system controller bit */
+ GO = 0x4, /* start fifos */
+ STOP = 0x8, /* stop fifos */
+ RESET_FIFO = 0x10, /* reset the FIFOs */
+ SOFT_RESET = 0x22, /* issue a software reset */
+ HARD_RESET = 0x40 /* 500x only? */
+};
+
+/* HSSEL -- handshake select register (write only) */
+enum hssel_bits {
+ TNT_ONE_CHIP_BIT = 0x1,
+ NODMA = 0x10,
+ TNT_GO2SIDS_BIT = 0x20,
+};
+
+/* IMR0 -- Interrupt Mode Register 0 */
+enum imr0_bits {
+ TNT_SYNCIE_BIT = 0x1, /* handshake sync */
+ TNT_TOIE_BIT = 0x2, /* timeout */
+ TNT_ATNIE_BIT = 0x4, /* ATN interrupt */
+ TNT_IFCIE_BIT = 0x8, /* interface clear interrupt */
+ TNT_BTO_BIT = 0x10, /* byte timeout */
+ TNT_NLEN_BIT = 0x20, /* treat new line as EOS char */
+ TNT_STBOIE_BIT = 0x40, /* status byte out */
+ TNT_IMR0_ALWAYS_BITS = 0x80, /* always set this bit on write */
+};
+
+/* ISR0 -- Interrupt Status Register 0 */
+enum isr0_bits {
+ TNT_SYNC_BIT = 0x1, /* handshake sync */
+ TNT_TO_BIT = 0x2, /* timeout */
+ TNT_ATNI_BIT = 0x4, /* ATN interrupt */
+ TNT_IFCI_BIT = 0x8, /* interface clear interrupt */
+ TNT_EOS_BIT = 0x10, /* end of string */
+ TNT_NL_BIT = 0x20, /* new line receive */
+ TNT_STBO_BIT = 0x40, /* status byte out */
+ TNT_NBA_BIT = 0x80, /* new byte available */
+};
+
+/* ISR3 -- Interrupt Status Register 3 (read only) */
+enum isr3_bits {
+ HR_DONE = (1 << 0), /* transfer done */
+ HR_TLCI = (1 << 1), /* isr0, isr1, or isr2 interrupt asserted */
+ HR_NEF = (1 << 2), /* NOT empty fifo */
+ HR_NFF = (1 << 3), /* NOT full fifo */
+ HR_STOP = (1 << 4), /* fifo empty or STOP command issued */
+ HR_SRQI_CIC = (1 << 5), /* SRQ asserted and we are CIC (500x only?)*/
+ HR_INTR = (1 << 7), /* isr3 interrupt active */
+};
+
+enum keyreg_bits {
+ MSTD = 0x20, // enable 350ns T1 delay
+};
+
+/* STS1 -- Status Register 1 (read only) */
+enum sts1_bits {
+ S_DONE = 0x80, /* DMA done */
+ S_SC = 0x40, /* is system controller */
+ S_IN = 0x20, /* DMA in (to memory) */
+ S_DRQ = 0x10, /* DRQ line (for diagnostics) */
+ S_STOP = 0x08, /* DMA stopped */
+ S_NDAV = 0x04, /* inverse of DAV */
+ S_HALT = 0x02, /* status of transfer machine */
+ S_GSYNC = 0x01, /* indicates if GPIB is in sync w I/O */
+};
+
+/* STS2 -- Status Register 2 */
+enum sts2_bits {
+ AFFN = (1 << 3), /* "A full FIFO NOT" (0=FIFO full) */
+ AEFN = (1 << 2), /* "A empty FIFO NOT" (0=FIFO empty) */
+ BFFN = (1 << 1), /* "B full FIFO NOT" (0=FIFO full) */
+ BEFN = (1 << 0), /* "B empty FIFO NOT" (0=FIFO empty) */
+};
+
+// Auxiliary commands
+enum tnt4882_aux_cmds {
+ AUX_9914 = 0x15, // switch to 9914 mode
+ AUX_REQT = 0x18,
+ AUX_REQF = 0x19,
+ AUX_PAGEIN = 0x50, /* page in alternate registers */
+ AUX_HLDI = 0x51, // rfd holdoff immediately
+ AUX_CLEAR_END = 0x55,
+ AUX_7210 = 0x99, // switch to 7210 mode
+};
+
+enum tnt4882_aux_regs {
+ AUXRG = 0x40,
+ AUXRI = 0xe0,
+};
+
+enum auxg_bits {
+ /* no talking when no listeners bit (prevents bus errors when data written at wrong time) */
+ NTNL_BIT = 0x8,
+ RPP2_BIT = 0x4, /* set/clear local rpp message */
+ CHES_BIT = 0x1, /*clear holdoff on end select bit*/
+};
+
+enum auxi_bits {
+ SISB = 0x1, // static interrupt bits (don't clear isr1, isr2 on read)
+ PP2 = 0x4, // ignore remote parallel poll configuration
+ USTD = 0x8, // ultra short (1100 nanosec) T1 delay
+};
+
+enum sasr_bits {
+ ACRDY_BIT = 0x4, /* acceptor ready state */
+ ADHS_BIT = 0x8, /* acceptor data holdoff state */
+ ANHS2_BIT = 0x10, /* acceptor not ready holdoff immediately state */
+ ANHS1_BIT = 0x20, /* acceptor not ready holdoff state */
+ AEHS_BIT = 0x40, /* acceptor end holdoff state */
+};
+
+#endif // _TNT4882_REGISTERS_H