//* SPDX-License-Identifier: GPL-2.0 */ /*************************************************************************** * copyright : (C) 2002 by Frank Mori Hess ***************************************************************************/ #ifndef _TMS9914_H #define _TMS9914_H #include #include #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, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); int tms9914_write(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written); int tms9914_command(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *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); void 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, uint8_t 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, uint8_t *result); void tms9914_parallel_poll_configure(struct gpib_board *board, struct tms9914_priv *priv, uint8_t 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, uint8_t status); uint8_t 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 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(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