| /* 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 |