diff options
| author | Niklas Cassel <cassel@kernel.org> | 2026-09-16 15:00:32 +0200 |
|---|---|---|
| committer | Niklas Cassel <cassel@kernel.org> | 2026-09-16 16:18:00 +0200 |
| commit | 8d836581f9b1f57ceaa2b47654754ef1260b410b (patch) | |
| tree | 1dbd4d0dfb99c2e238356cbe947e5b0be3e3a571 /drivers/gpib/include | |
| download | linux-stable-8d836581f9b1f57ceaa2b47654754ef1260b410b.tar.gz linux-stable-8d836581f9b1f57ceaa2b47654754ef1260b410b.zip | |
ata: libata-scsi: fix ata_dsm_trim_pages() kernel-docgrafted
make htmldocs fails with:
Documentation/driver-api/libata:604: ./drivers/ata/libata-scsi.c:2301:
ERROR: Unexpected indentation. [docutils]
The Return: section of ata_dsm_trim_pages() ends its first sentence with
a colon and continues with an indented bullet list. reStructuredText
requires a blank line before an indented block, so docutils chokes on
the list.
Simply adding the missing blank line does not work either: Return: is a
kernel-doc "special section", which is terminated by the first blank
line, so the bullet list would end up in the Description section,
detached from the sentence introducing it.
Spell the two bounds out as prose instead, so that the Return: section
stays self-contained. Documentation-only change.
Fixes: e64e6b5dc867 ("ata: libata-scsi: scale DSM TRIM payload by MAX PAGES PER DSM COMMAND")
Reported-by: Thomas Huth <thuth@redhat.com>
Closes: https://lore.kernel.org/linux-ide/b0a0b8e8-cc4f-4c7b-8bc5-fee0712d405a@redhat.com/
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Link: https://lore.kernel.org/r/20260916130031.29990-2-cassel@kernel.org
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Diffstat (limited to 'drivers/gpib/include')
| -rw-r--r-- | drivers/gpib/include/amcc5920.h | 49 | ||||
| -rw-r--r-- | drivers/gpib/include/amccs5933.h | 59 | ||||
| -rw-r--r-- | drivers/gpib/include/gpibP.h | 41 | ||||
| -rw-r--r-- | drivers/gpib/include/gpib_cmd.h | 112 | ||||
| -rw-r--r-- | drivers/gpib/include/gpib_pci_ids.h | 23 | ||||
| -rw-r--r-- | drivers/gpib/include/gpib_proto.h | 49 | ||||
| -rw-r--r-- | drivers/gpib/include/gpib_state_machines.h | 23 | ||||
| -rw-r--r-- | drivers/gpib/include/gpib_types.h | 389 | ||||
| -rw-r--r-- | drivers/gpib/include/nec7210.h | 141 | ||||
| -rw-r--r-- | drivers/gpib/include/nec7210_registers.h | 218 | ||||
| -rw-r--r-- | drivers/gpib/include/plx9050.h | 72 | ||||
| -rw-r--r-- | drivers/gpib/include/quancom_pci.h | 22 | ||||
| -rw-r--r-- | drivers/gpib/include/tms9914.h | 280 | ||||
| -rw-r--r-- | drivers/gpib/include/tnt4882_registers.h | 192 |
14 files changed, 1670 insertions, 0 deletions
diff --git a/drivers/gpib/include/amcc5920.h b/drivers/gpib/include/amcc5920.h new file mode 100644 index 000000000..7a88bd282 --- /dev/null +++ b/drivers/gpib/include/amcc5920.h @@ -0,0 +1,49 @@ +/* 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); +}; + diff --git a/drivers/gpib/include/amccs5933.h b/drivers/gpib/include/amccs5933.h new file mode 100644 index 000000000..f8a80bdc7 --- /dev/null +++ b/drivers/gpib/include/amccs5933.h @@ -0,0 +1,59 @@ +/* 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 +static 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 +static inline int INBOX_BYTE_BITS(unsigned int byte) +{ + return (byte & 0x3) << 8; +}; + +// select incoming mailbox 0 to 3 +static inline int INBOX_SELECT_BITS(unsigned int mailbox) +{ + return (mailbox & 0x3) << 10; +}; + +// select byte 0 to 3 of outgoing mailbox +static inline int OUTBOX_BYTE_BITS(unsigned int byte) +{ + return (byte & 0x3); +}; + +// select outgoing mailbox 0 to 3 +static 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 +}; + diff --git a/drivers/gpib/include/gpibP.h b/drivers/gpib/include/gpibP.h new file mode 100644 index 000000000..e3938ada3 --- /dev/null +++ b/drivers/gpib/include/gpibP.h @@ -0,0 +1,41 @@ +/* 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_cmd.h" +#include <linux/gpib.h> +#include <linux/gpib_ioctl.h> + +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/io.h> + +int gpib_register_driver(struct gpib_interface *interface, struct module *mod); +void gpib_unregister_driver(struct gpib_interface *interface); +struct pci_dev *gpib_pci_get_device(const struct gpib_board_config *config, unsigned int vendor_id, + unsigned int device_id, struct pci_dev *from); +struct pci_dev *gpib_pci_get_subsys(const struct gpib_board_config *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 struct gpib_event_queue *queue); +int push_gpib_event(struct gpib_board *board, short event_type); +int pop_gpib_event(struct gpib_board *board, struct gpib_event_queue *queue, short *event_type); +int gpib_request_pseudo_irq(struct gpib_board *board, irqreturn_t (*handler)(int, void *)); +void gpib_free_pseudo_irq(struct gpib_board *board); +int gpib_match_device_path(struct device *dev, const char *device_path_in); + +extern struct gpib_board board_array[GPIB_MAX_NUM_BOARDS]; + +extern struct list_head registered_drivers; + +#endif // _GPIB_P_H + diff --git a/drivers/gpib/include/gpib_cmd.h b/drivers/gpib/include/gpib_cmd.h new file mode 100644 index 000000000..9e96a3bfa --- /dev/null +++ b/drivers/gpib/include/gpib_cmd.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _GPIB_CMD_H +#define _GPIB_CMD_H + +#include <linux/types.h> + +/* Command byte definitions tests and functions */ + +/* mask of bits that actually matter in a command byte */ +enum { + gpib_command_mask = 0x7f, +}; + +/* Possible GPIB command messages */ + +enum cmd_byte { + GTL = 0x1, /* go to local */ + SDC = 0x4, /* selected device clear */ + PP_CONFIG = 0x5, + GET = 0x8, /* group execute trigger */ + TCT = 0x9, /* take control */ + LLO = 0x11, /* local lockout */ + DCL = 0x14, /* device clear */ + PPU = 0x15, /* parallel poll unconfigure */ + SPE = 0x18, /* serial poll enable */ + SPD = 0x19, /* serial poll disable */ + CFE = 0x1f, /* configure enable */ + LAD = 0x20, /* value to be 'ored' in to obtain listen address */ + UNL = 0x3F, /* unlisten */ + TAD = 0x40, /* value to be 'ored' in to obtain talk address */ + UNT = 0x5F, /* untalk */ + SAD = 0x60, /* my secondary address (base) */ + PPE = 0x60, /* parallel poll enable (base) */ + PPD = 0x70 /* parallel poll disable */ +}; + +/* confine address to range 0 to 30. */ +static inline unsigned int gpib_address_restrict(u32 addr) +{ + addr &= 0x1f; + if (addr == 0x1f) + addr = 0; + return addr; +} + +static inline u8 MLA(u32 addr) +{ + return gpib_address_restrict(addr) | LAD; +} + +static inline u8 MTA(u32 addr) +{ + return gpib_address_restrict(addr) | TAD; +} + +static inline u8 MSA(u32 addr) +{ + return (addr & 0x1f) | SAD; +} + +static inline s32 gpib_address_equal(u32 pad1, s32 sad1, u32 pad2, s32 sad2) +{ + if (pad1 == pad2) { + if (sad1 == sad2) + return 1; + if (sad1 < 0 && sad2 < 0) + return 1; + } + + return 0; +} + +static inline s32 is_PPE(u8 command) +{ + return (command & 0x70) == 0x60; +} + +static inline s32 is_PPD(u8 command) +{ + return (command & 0x70) == 0x70; +} + +static inline s32 in_addressed_command_group(u8 command) +{ + return (command & 0x70) == 0x0; +} + +static inline s32 in_universal_command_group(u8 command) +{ + return (command & 0x70) == 0x10; +} + +static inline s32 in_listen_address_group(u8 command) +{ + return (command & 0x60) == 0x20; +} + +static inline s32 in_talk_address_group(u8 command) +{ + return (command & 0x60) == 0x40; +} + +static inline s32 in_primary_command_group(u8 command) +{ + return in_addressed_command_group(command) || + in_universal_command_group(command) || + in_listen_address_group(command) || + in_talk_address_group(command); +} + +#endif /* _GPIB_CMD_H */ diff --git a/drivers/gpib/include/gpib_pci_ids.h b/drivers/gpib/include/gpib_pci_ids.h new file mode 100644 index 000000000..52dcab07a --- /dev/null +++ b/drivers/gpib/include/gpib_pci_ids.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __GPIB_PCI_IDS_H +#define __GPIB_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 + diff --git a/drivers/gpib/include/gpib_proto.h b/drivers/gpib/include/gpib_proto.h new file mode 100644 index 000000000..42e736e3b --- /dev/null +++ b/drivers/gpib/include/gpib_proto.h @@ -0,0 +1,49 @@ +/* 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); +void os_start_timer(struct gpib_board *board, unsigned int usec_timeout); +void os_remove_timer(struct gpib_board *board); +void init_gpib_board(struct gpib_board *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(struct gpib_board *board, unsigned int usec_timeout); +void init_gpib_descriptor(struct gpib_descriptor *desc); +int dvrsp(struct gpib_board *board, unsigned int pad, int sad, + unsigned int usec_timeout, u8 *result); +int ibcac(struct gpib_board *board, int sync, int fallback_to_async); +int ibcmd(struct gpib_board *board, u8 *buf, size_t length, size_t *bytes_written); +int ibgts(struct gpib_board *board); +int ibonline(struct gpib_board *board); +int iboffline(struct gpib_board *board); +int iblines(const struct gpib_board *board, short *lines); +int ibrd(struct gpib_board *board, u8 *buf, size_t length, int *end_flag, size_t *bytes_read); +int ibrpp(struct gpib_board *board, u8 *buf); +int ibrsv2(struct gpib_board *board, u8 status_byte, int new_reason_for_service); +int ibrsc(struct gpib_board *board, int request_control); +int ibsic(struct gpib_board *board, unsigned int usec_duration); +int ibsre(struct gpib_board *board, int enable); +int ibpad(struct gpib_board *board, unsigned int addr); +int ibsad(struct gpib_board *board, int addr); +int ibeos(struct gpib_board *board, int eos, int eosflags); +int ibwait(struct gpib_board *board, int wait_mask, int clear_mask, int set_mask, + int *status, unsigned long usec_timeout, struct gpib_descriptor *desc); +int ibwrt(struct gpib_board *board, u8 *buf, size_t cnt, int send_eoi, size_t *bytes_written); +int ibstatus(struct gpib_board *board); +int general_ibstatus(struct gpib_board *board, const struct gpib_status_queue *device, + int clear_mask, int set_mask, struct gpib_descriptor *desc); +int io_timed_out(struct gpib_board *board); +int ibppc(struct gpib_board *board, u8 configuration); + +#endif /* GPIB_PROTO_INCLUDED */ diff --git a/drivers/gpib/include/gpib_state_machines.h b/drivers/gpib/include/gpib_state_machines.h new file mode 100644 index 000000000..7488c00f1 --- /dev/null +++ b/drivers/gpib/include/gpib_state_machines.h @@ -0,0 +1,23 @@ +/* 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 diff --git a/drivers/gpib/include/gpib_types.h b/drivers/gpib/include/gpib_types.h new file mode 100644 index 000000000..28b73157f --- /dev/null +++ b/drivers/gpib/include/gpib_types.h @@ -0,0 +1,389 @@ +/* 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 */ diff --git a/drivers/gpib/include/nec7210.h b/drivers/gpib/include/nec7210.h new file mode 100644 index 000000000..9835aa5ef --- /dev/null +++ b/drivers/gpib/include/nec7210.h @@ -0,0 +1,141 @@ +/* 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 { +#ifdef CONFIG_HAS_IOPORT + u32 iobase; +#endif + void __iomem *mmiobase; + 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(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, + size_t length, int *end, size_t *bytes_read); +int nec7210_write(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, + size_t length, int send_eoi, size_t *bytes_written); +int nec7210_command(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, + size_t length, size_t *bytes_written); +int nec7210_take_control(struct gpib_board *board, struct nec7210_priv *priv, int syncronous); +int nec7210_go_to_standby(struct gpib_board *board, struct nec7210_priv *priv); +int nec7210_request_system_control(struct gpib_board *board, + struct nec7210_priv *priv, int request_control); +void nec7210_interface_clear(struct gpib_board *board, struct nec7210_priv *priv, int assert); +void nec7210_remote_enable(struct gpib_board *board, struct nec7210_priv *priv, int enable); +int nec7210_enable_eos(struct gpib_board *board, struct nec7210_priv *priv, u8 eos_bytes, + int compare_8_bits); +void nec7210_disable_eos(struct gpib_board *board, struct nec7210_priv *priv); +unsigned int nec7210_update_status(struct gpib_board *board, struct nec7210_priv *priv, + unsigned int clear_mask); +unsigned int nec7210_update_status_nolock(struct gpib_board *board, struct nec7210_priv *priv); +int nec7210_primary_address(const struct gpib_board *board, + struct nec7210_priv *priv, unsigned int address); +int nec7210_secondary_address(const struct gpib_board *board, struct nec7210_priv *priv, + unsigned int address, int enable); +int nec7210_parallel_poll(struct gpib_board *board, struct nec7210_priv *priv, u8 *result); +void nec7210_serial_poll_response(struct gpib_board *board, + struct nec7210_priv *priv, u8 status); +void nec7210_parallel_poll_configure(struct gpib_board *board, + struct nec7210_priv *priv, unsigned int configuration); +void nec7210_parallel_poll_response(struct gpib_board *board, + struct nec7210_priv *priv, int ist); +u8 nec7210_serial_poll_status(struct gpib_board *board, struct nec7210_priv *priv); +int nec7210_t1_delay(struct gpib_board *board, + struct nec7210_priv *priv, unsigned int nano_sec); +void nec7210_return_to_local(const struct gpib_board *board, struct nec7210_priv *priv); + +// utility functions +void nec7210_board_reset(struct nec7210_priv *priv, const struct gpib_board *board); +void nec7210_board_online(struct nec7210_priv *priv, const struct gpib_board *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(struct gpib_board *board, struct nec7210_priv *priv, int mode); +void nec7210_release_rfd_holdoff(struct gpib_board *board, struct nec7210_priv *priv); +u8 nec7210_read_data_in(struct gpib_board *board, struct nec7210_priv *priv, int *end); + +// wrappers for io functions +u8 nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num); +void nec7210_ioport_write_byte(struct nec7210_priv *priv, u8 data, unsigned int register_num); +u8 nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num); +void nec7210_iomem_write_byte(struct nec7210_priv *priv, u8 data, unsigned int register_num); +u8 nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num); +void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, u8 data, + unsigned int register_num); +u8 nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num); +void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, u8 data, + unsigned int register_num); + +// interrupt service routine +irqreturn_t nec7210_interrupt(struct gpib_board *board, struct nec7210_priv *priv); +irqreturn_t nec7210_interrupt_have_status(struct gpib_board *board, + struct nec7210_priv *priv, int status1, int status2); + +#endif //_NEC7210_H diff --git a/drivers/gpib/include/nec7210_registers.h b/drivers/gpib/include/nec7210_registers.h new file mode 100644 index 000000000..067983d7a --- /dev/null +++ b/drivers/gpib/include/nec7210_registers.h @@ -0,0 +1,218 @@ +/* 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 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 + + // nec7210 has 8 registers + nec7210_num_registers = 8, +}; + +// 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 diff --git a/drivers/gpib/include/plx9050.h b/drivers/gpib/include/plx9050.h new file mode 100644 index 000000000..c911b285a --- /dev/null +++ b/drivers/gpib/include/plx9050.h @@ -0,0 +1,72 @@ +/* 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 diff --git a/drivers/gpib/include/quancom_pci.h b/drivers/gpib/include/quancom_pci.h new file mode 100644 index 000000000..cdaf0d056 --- /dev/null +++ b/drivers/gpib/include/quancom_pci.h @@ -0,0 +1,22 @@ +/* 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 diff --git a/drivers/gpib/include/tms9914.h b/drivers/gpib/include/tms9914.h new file mode 100644 index 000000000..e66b75e0f --- /dev/null +++ b/drivers/gpib/include/tms9914.h @@ -0,0 +1,280 @@ +/* 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 { +#ifdef CONFIG_HAS_IOPORT + u32 iobase; +#endif + void __iomem *mmiobase; + 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(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, + size_t length, int *end, size_t *bytes_read); +int tms9914_write(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, + size_t length, int send_eoi, size_t *bytes_written); +int tms9914_command(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, + size_t length, size_t *bytes_written); +int tms9914_take_control(struct gpib_board *board, struct tms9914_priv *priv, int syncronous); +/* + * alternate version of tms9914_take_control which works around buggy tcs + * implementation. + */ +int tms9914_take_control_workaround(struct gpib_board *board, struct tms9914_priv *priv, + int syncronous); +int tms9914_go_to_standby(struct gpib_board *board, struct tms9914_priv *priv); +int tms9914_request_system_control(struct gpib_board *board, struct tms9914_priv *priv, + int request_control); +void tms9914_interface_clear(struct gpib_board *board, struct tms9914_priv *priv, int assert); +void tms9914_remote_enable(struct gpib_board *board, struct tms9914_priv *priv, int enable); +int tms9914_enable_eos(struct gpib_board *board, struct tms9914_priv *priv, u8 eos_bytes, + int compare_8_bits); +void tms9914_disable_eos(struct gpib_board *board, struct tms9914_priv *priv); +unsigned int tms9914_update_status(struct gpib_board *board, struct tms9914_priv *priv, + unsigned int clear_mask); +int tms9914_primary_address(struct gpib_board *board, + struct tms9914_priv *priv, unsigned int address); +int tms9914_secondary_address(struct gpib_board *board, struct tms9914_priv *priv, + unsigned int address, int enable); +int tms9914_parallel_poll(struct gpib_board *board, struct tms9914_priv *priv, u8 *result); +void tms9914_parallel_poll_configure(struct gpib_board *board, + struct tms9914_priv *priv, u8 config); +void tms9914_parallel_poll_response(struct gpib_board *board, + struct tms9914_priv *priv, int ist); +void tms9914_serial_poll_response(struct gpib_board *board, + struct tms9914_priv *priv, u8 status); +u8 tms9914_serial_poll_status(struct gpib_board *board, struct tms9914_priv *priv); +int tms9914_line_status(const struct gpib_board *board, struct tms9914_priv *priv); +unsigned int tms9914_t1_delay(struct gpib_board *board, struct tms9914_priv *priv, + unsigned int nano_sec); +void tms9914_return_to_local(const struct gpib_board *board, struct tms9914_priv *priv); + +// utility functions +void tms9914_board_reset(struct tms9914_priv *priv); +void tms9914_online(struct gpib_board *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 +u8 tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num); +void tms9914_ioport_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num); +u8 tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num); +void tms9914_iomem_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num); + +// interrupt service routine +irqreturn_t tms9914_interrupt(struct gpib_board *board, struct tms9914_priv *priv); +irqreturn_t tms9914_interrupt_have_status(struct gpib_board *board, struct tms9914_priv *priv, + int status1, int status2); + +// tms9914 has 8 registers +enum { + ms9914_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 diff --git a/drivers/gpib/include/tnt4882_registers.h b/drivers/gpib/include/tnt4882_registers.h new file mode 100644 index 000000000..d54c4cc61 --- /dev/null +++ b/drivers/gpib/include/tnt4882_registers.h @@ -0,0 +1,192 @@ +/* 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, +}; + +enum { + 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 |
