1 /*	$OpenBSD: rlnreg.h,v 1.3 2002/03/14 01:26:55 millert Exp $	*/
2 /*
3  * David Leonard <d@openbsd.org>, 1999. Public Domain.
4  *
5  * RangeLAN2 registers
6  */
7 
8 /*
9  * The RangeLAN2 cards provide four control registers for transferring
10  * messaged between the host and the card using programmed i/o.
11  *
12  * A transfer protocol is followed when sending asynchronous messages to,
13  * and receiving messages from, the card.
14  *
15  * DATA
16  *      7       6       5       4       3       2       1       0
17  *  +-------+-------+-------+-------+-------+-------+-------+-------+
18  *  |                             data                              |
19  *  +-------+-------+-------+-------+-------+-------+-------+-------+
20  *
21  * STATUS
22  *      7       6       5       4       3       2       1       0
23  *  +-------+-------+-------+-------+-------+-------+-------+-------+
24  *  |WAKEUP |   tx message state    |CLRNAK |   rx message state    |
25  *  +-------+-------+-------+-------+-------+-------+-------+-------+
26  *
27  * CONTROL
28  *      7       6       5       4       3       2       1       0
29  *  +-------+-------+-------+-------+-------+-------+-------+-------+
30  *  |       |       | 16BIT | RESET |       |       | TXINT | RXINT |
31  *  +-------+-------+-------+-------+-------+-------+-------+-------+
32  *
33  * INTSEL
34  *      7       6       5       4       3       2       1       0
35  *  +-------+-------+-------+-------+-------+-------+-------+-------+
36  *  |       |       |       |ENABLE |        interrupt line         |
37  *  +-------+-------+-------+-------+-------+-------+-------+-------+
38  */
39 
40 /* Register offsets. */
41 #define RLN_REG_DATA			0
42 #define RLN_REG_STATUS			2
43 #define RLN_REG_CONTROL			4
44 #define RLN_REG_EOI			5
45 #define RLN_REG_INTSEL			6
46 #define RLN_NPORTS                      8
47 
48 /*
49  * A short delay is needed (16ms?) after register writes on some cards.
50  * XXX This is done by performing an innocent and harmless bus read. (i386)
51  * This is what Proxim's driver does, anyway.
52  */
53 #define _rln_regacc_delay() \
54 	bus_space_read_1(I386_BUS_SPACE_IO, 0, 0x61)
55 
56 static void	_rln_register_write_1(struct rln_softc *, u_int8_t,
57 			u_int8_t);
58 static void	_rln_register_write_2(struct rln_softc *, u_int8_t,
59 			u_int16_t);
60 static u_int8_t	_rln_register_read_1(struct rln_softc *, u_int8_t);
61 static u_int16_t _rln_register_read_2(struct rln_softc *, u_int8_t);
62 static int	rln_status_rx_ready(struct rln_softc *);
63 
64 /* Write to a register. */
65 static inline void
_rln_register_write_1(sc,regoff,value)66 _rln_register_write_1(sc, regoff, value)
67 	struct rln_softc *sc;
68 	u_int8_t regoff;
69 	u_int8_t value;
70 {
71 
72 #ifdef RLNDEBUG_REG
73 	printf(" %c<%02x", "DDS3CEI7"[regoff], value);
74 #endif
75 	bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (regoff), (value));
76 	_rln_regacc_delay();
77 }
78 
79 static inline void
_rln_register_write_2(sc,regoff,value)80 _rln_register_write_2(sc, regoff, value)
81 	struct rln_softc *sc;
82 	u_int8_t regoff;
83 	u_int16_t value;
84 {
85 
86 #ifdef RLNDEBUG_REG
87 	printf(" %c<%04x", "DDS3CEI7"[regoff], value);
88 #endif
89 	bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (regoff), (value));
90 	_rln_regacc_delay();
91 }
92 
93 /* Read from a register. */
94 static inline u_int8_t
_rln_register_read_1(sc,regoff)95 _rln_register_read_1(sc, regoff)
96 	struct rln_softc *sc;
97 	u_int8_t regoff;
98 {
99 	u_int8_t ret;
100 
101 	ret = bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (regoff));
102 #ifdef RLNDEBUG_REG
103 	if (ret != (sc)->dbg_oreg[regoff]) {
104 		/* avoid spewing out too much debug info */
105 		printf(" %c>%02x", "DDS3CEI7"[regoff], ret);
106 		(sc)->dbg_oreg[regoff] = ret;
107 	}
108 #endif
109 	return (ret);
110 }
111 
112 
113 static inline u_int16_t
_rln_register_read_2(sc,regoff)114 _rln_register_read_2(sc, regoff)
115 	struct rln_softc *sc;
116 	u_int8_t regoff;
117 {
118 	u_int16_t ret;
119 
120 	ret = bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (regoff));
121 #ifdef RLNDEBUG_REG
122 	if (ret != (sc)->dbg_oreg[regoff]) {
123 		printf(" %c>%04x", "DDS3CEI7"[regoff], ret);
124 		(sc)->dbg_oreg[regoff] = ret;
125 	}
126 #endif
127 	return (ret);
128 }
129 
130 /* 8-bit data register access. */
131 #define rln_data_write_1(sc, value) 					\
132 		_rln_register_write_1(sc, RLN_REG_DATA, (value))
133 #define rln_data_read_1(sc) 						\
134 		_rln_register_read_1(sc, RLN_REG_DATA)
135 #define rln_data_write_multi_1(sc, buf, len) 				\
136 		bus_space_write_multi_1((sc)->sc_iot, (sc)->sc_ioh,	\
137 			RLN_REG_DATA, (buf), (len))
138 #define rln_data_read_multi_1(sc, buf, len) 				\
139 		bus_space_read_multi_1((sc)->sc_iot, (sc)->sc_ioh,	\
140 			RLN_REG_DATA, (buf), (len))
141 
142 /* 16-bit data register access. */
143 #define rln_data_write_2(sc, value) 					\
144 		_rln_register_write_2(sc, RLN_REG_DATA, (value))
145 #define rln_data_read_2(sc) 						\
146 		_rln_register_read_2(sc, RLN_REG_DATA)
147 #define rln_data_write_multi_2(sc, buf, len) 				\
148 		bus_space_write_multi_2((sc)->sc_iot, (sc)->sc_ioh,	\
149 			RLN_REG_DATA, (buf), (len))
150 #define rln_data_read_multi_2(sc, buf, len)				\
151 		bus_space_read_multi_2((sc)->sc_iot, (sc)->sc_ioh,	\
152 			RLN_REG_DATA, (buf), (len))
153 
154 /* Status register. */
155 #define RLN_STATUS_CLRNAK		0x08
156 #define RLN_STATUS_WAKEUP		0x80
157 
158 #define RLN_STATUS_TX_IDLE		0x00
159 #define RLN_STATUS_TX_HILEN_AVAIL	0x01
160 #define RLN_STATUS_TX_HILEN_ACCEPT	0x02
161 #define RLN_STATUS_TX_XFR_COMPLETE	0x03
162 #define RLN_STATUS_TX_XFR		0x04
163 #define RLN_STATUS_TX_ERROR		0x05
164 #define RLN_STATUS_TX_LOLEN_AVAIL	0x06
165 #define RLN_STATUS_TX_LOLEN_ACCEPT	0x07
166 #define RLN_STATUS_TX_MASK		0x0f
167 
168 #define RLN_STATUS_RX_IDLE		0x00
169 #define RLN_STATUS_RX_HILEN_AVAIL	0x10
170 #define RLN_STATUS_RX_HILEN_ACCEPT	0x20
171 #define RLN_STATUS_RX_XFR_COMPLETE	0x30
172 #define RLN_STATUS_RX_XFR		0x40
173 #define RLN_STATUS_RX_ERROR		0x50
174 #define RLN_STATUS_RX_LOLEN_AVAIL	0x60
175 #define RLN_STATUS_RX_LOLEN_ACCEPT	0x70
176 #define RLN_STATUS_RX_MASK		0x70
177 
178 #define rln_status_write(sc, value) 					\
179 		_rln_register_write_1(sc, RLN_REG_STATUS, (value))
180 #define rln_status_set(sc, bits) 					\
181 		rln_status_write(sc, (sc)->sc_status |= (bits))
182 #define rln_status_clear(sc, bits) 					\
183 		rln_status_write(sc, (sc)->sc_status &= ~(bits))
184 #define _rln_status_setmask(sc, mask, bits)				\
185 do {									\
186 		int _s;							\
187 									\
188 		_s = splhigh();						\
189 	    	(sc)->sc_status = ((sc)->sc_status & (mask)) | (bits);	\
190 		rln_status_write(sc, (sc)->sc_status);			\
191 		splx(_s);						\
192 } while (0);
193 #define rln_status_rx_write(sc, state)  				\
194 		_rln_status_setmask((sc), ~RLN_STATUS_RX_MASK, state)
195 #define rln_status_tx_write(sc, state)  				\
196 		_rln_status_setmask((sc), ~RLN_STATUS_TX_MASK, state)
197 #define rln_status_read(sc) 						\
198 		_rln_register_read_1(sc, RLN_REG_STATUS)
199 #define rln_status_rx_read(sc) 						\
200 		(rln_status_read(sc) & ~RLN_STATUS_TX_MASK)
201 #define rln_status_tx_read(sc) 						\
202 		(rln_status_read(sc) & ~RLN_STATUS_RX_MASK)
203 
204 static inline int
rln_status_rx_ready(sc)205 rln_status_rx_ready(sc)
206 	struct rln_softc *sc;
207 {
208 	u_int8_t status;
209 
210 	status = rln_status_rx_read(sc);
211 	return (status == RLN_STATUS_RX_LOLEN_AVAIL ||
212 	    status == RLN_STATUS_RX_HILEN_AVAIL ||
213 	    status == RLN_STATUS_RX_ERROR);
214 }
215 
216 #define rln_status_tx_int(sc) do { 					\
217 		int _s = splhigh();					\
218 									\
219 		rln_control_clear(sc, RLN_CONTROL_TXINT);		\
220 		rln_control_set(sc, RLN_CONTROL_TXINT);			\
221 		splx(_s);						\
222 } while (0)
223 #define rln_status_rx_int(sc) do { 					\
224 		int _s = splhigh();					\
225 									\
226 		rln_control_clear(sc, RLN_CONTROL_RXINT);		\
227 		rln_control_set(sc, RLN_CONTROL_RXINT);			\
228 		splx(_s);						\
229 } while (0)
230 
231 /* Control register. */
232 #define RLN_CONTROL_RXINT		0x01
233 #define RLN_CONTROL_TXINT		0x02
234 #define RLN_CONTROL_BIT2		0x04
235 #define RLN_CONTROL_BIT3		0x08
236 #define RLN_CONTROL_RESET		0x10
237 #define RLN_CONTROL_16BIT		0x20
238 #define RLN_CONTROL_MASK		0x3f
239 
240 #define rln_control_write(sc, value) 					\
241 		_rln_register_write_1(sc, RLN_REG_CONTROL,		\
242 			(sc)->sc_control = (value))
243 #define rln_control_read(sc) 						\
244 		_rln_register_read_1(sc, RLN_REG_CONTROL)
245 #define rln_control_set(sc, bits) 					\
246 		rln_control_write(sc, (sc)->sc_control | (bits))
247 #define rln_control_clear(sc, bits) 					\
248 		rln_control_write(sc, (sc)->sc_control & ~(bits))
249 #define rln_control_outofstandby(sc) do {				\
250 		rln_control_write(sc, (sc)->sc_control | RLN_CONTROL_RESET);\
251 		DELAY(30000);						\
252 		rln_control_write(sc, (sc)->sc_control);		\
253 } while (0)
254 
255 /* Interrupt selection register. */
256 #define RLN_INTSEL_IRQMASK		0x07
257 #define RLN_INTSEL_ENABLE		0x10
258 #define RLN_INTSEL_BIT7			0x80
259 
260 #define rln_intsel_disable(sc) do {					\
261 		int _s;							\
262 									\
263 		_s = splhigh();						\
264 		_rln_register_write_1(sc, RLN_REG_INTSEL, 		\
265 			(sc)->sc_intsel &= ~RLN_INTSEL_ENABLE);		\
266 		splx(_s);						\
267 } while (0)
268 #define rln_intsel_enable(sc) do {					\
269 		int _s;							\
270 									\
271 		_s = splhigh();						\
272 		_rln_register_write_1(sc, RLN_REG_INTSEL, 		\
273 			(sc)->sc_intsel |= RLN_INTSEL_ENABLE);		\
274 		splx(_s);						\
275 } while (0)
276 #define rln_intsel_write(sc, value) 					\
277 		_rln_register_write_1(sc, RLN_REG_INTSEL, 		\
278 		    (sc)->sc_intsel |= (value))
279 
280 /* End of interrupt signal, used on some newer cards. */
281 #define rln_eoi(sc)							\
282 		(void) _rln_register_read_1(sc, RLN_REG_EOI)
283 
284