1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
|
//* 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, 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
|