1 /*	$OpenBSD: rlnsubr.c,v 1.5 2002/03/14 01:26:55 millert Exp $	*/
2 /*
3  * David Leonard <d@openbsd.org>, 1999. Public Domain.
4  *
5  * Low level card protocol access to the Proxim RangeLAN2 wireless
6  * network adaptor.
7  *
8  * Information and ideas gleaned from
9  *   - disassembly of Dave Koberstein's <davek@komacke.com> Linux driver
10  *     (which is built with Proxim source),
11  *   - Yoichi Shinoda's <shinoda@cs.washington.edu> BSDI driver, and
12  *   - Geoff Voelker's <voelker@cs.washington.edu> Linux port of the same.
13  */
14 
15 #include <sys/param.h>
16 #include <sys/systm.h>
17 #include <sys/mbuf.h>
18 #include <sys/socket.h>
19 #include <sys/ioctl.h>
20 #include <sys/syslog.h>
21 #include <sys/device.h>
22 #include <sys/queue.h>
23 #include <sys/proc.h>
24 #include <sys/kernel.h>
25 
26 #include <net/if.h>
27 
28 #ifdef INET
29 #include <netinet/in.h>
30 #include <netinet/if_ether.h>
31 #endif
32 
33 #include <machine/bus.h>
34 #include <machine/intr.h>
35 
36 #include <dev/ic/rln.h>
37 #include <dev/ic/rlnvar.h>
38 #include <dev/ic/rlnreg.h>
39 #include <dev/ic/rlncmd.h>
40 
41 static int	rln_tx_request(struct rln_softc *, u_int16_t);
42 static int	rln_tx_end(struct rln_softc *);
43 
44 /*
45  * Disables or enables interrupts from the card. Returns the old
46  * interrupt-enable state.
47  */
48 int
rln_enable(sc,enable)49 rln_enable(sc, enable)
50 	struct rln_softc * sc;
51 	int		enable;
52 {
53 	int		s;
54 	int		was_enabled;
55 
56 	s = splhigh();
57 	was_enabled = (sc->sc_intsel & RLN_INTSEL_ENABLE) ? 1 : 0;
58 	if (enable != was_enabled) {
59 		if (enable)
60 			sc->sc_intsel |= RLN_INTSEL_ENABLE;
61 		else
62 			sc->sc_intsel &=~RLN_INTSEL_ENABLE;
63 		_rln_register_write_1(sc, RLN_REG_INTSEL, sc->sc_intsel);
64 	}
65 	splx(s);
66 	return (was_enabled);
67 }
68 
69 /*
70  * Perform a hard reset of the card.  Determines bus width (8 or
71  * 16 bit), if sc->sc_width is unset.  Returns 0 on success.
72  * Note: takes about 200ms at splhigh, meaning this is an expensive call,
73  * but normal (error-free) operation of the card will not need more than
74  * two resets - one at probe time, and the other when the interface is
75  * brought up.
76  */
77 int
rln_reset(sc)78 rln_reset(sc)
79 	struct rln_softc * sc;
80 {
81 	int		s;
82 	int		i;
83 	int		status;
84 	u_int8_t	op = 0x00;
85 
86 	s = splhigh();
87 	dprintf(" R[");
88 	if (sc->sc_cardtype & (RLN_CTYPE_UISA | RLN_CTYPE_ONE_PIECE))
89 		op = 0x04;
90 	if (rln_status_read(sc) & RLN_STATUS_WAKEUP) {
91 		rln_control_write(sc, op);
92 		rln_control_write(sc, op | RLN_CONTROL_RESET);
93 		dprintf(" 7ms");
94 		DELAY(7000);
95 		rln_control_write(sc, op);
96 		dprintf(" 7ms");
97 		DELAY(7000);
98 	}
99 	rln_control_write(sc, op);
100 	rln_control_write(sc, op);
101 	rln_control_write(sc, op | RLN_CONTROL_BIT3);
102 	dprintf(" 67ms");
103 	DELAY(67000);
104 	rln_status_write(sc, 0x00);
105 	if (sc->sc_cardtype & (RLN_CTYPE_UISA | RLN_CTYPE_ONE_PIECE))
106 		rln_control_write(sc, 0x38);
107 		/* RLN_CONTROL_BIT3 | RLN_CONTROL_RESET | RLN_CONTROL_16BIT */
108 	else
109 		rln_control_write(sc, 0x2c);
110 		/* RLN_CONTROL_BIT3 | RLN_CONTROL_BIT2  | RLN_CONTROL_16BIT */
111 	dprintf(" 67ms");
112 	DELAY(67000);
113 	rln_data_write_2(sc, 0xaa55);
114 	rln_status_write(sc, 0x5a);
115 	splx(s);
116 	for (i = 0; i < 200 * 10; i++) {	/* Proxim says 200. */
117 		if ((status = rln_status_read(sc)) == 0x5a)
118 			break;
119 		DELAY(1000);
120 	}
121 	dprintf(" (%dms)", i);
122 	s = splhigh();
123 	if (status != 0x5a) {
124 		splx(s);
125 		/* Only winge if bus width not yet probed */
126 		if (sc->sc_width != 0)
127 			printf("%s: reset timeout\n", sc->sc_dev.dv_xname);
128 		dprintf("]=-1");
129 		return (-1);
130 	}
131 	if (sc->sc_width == 8) {
132 		if (sc->sc_cardtype & (RLN_CTYPE_UISA | RLN_CTYPE_ONE_PIECE))
133 			rln_control_write(sc, RLN_CONTROL_BIT3);
134 		else
135 			rln_control_write(sc, RLN_CONTROL_BIT3 |
136 			    RLN_CONTROL_BIT2);
137 		rln_data_write_1(sc, 0x20);
138 	} else if (sc->sc_width == 16) {
139 		rln_data_write_2(sc, 0x0000);
140 	} else {
141 		if (rln_data_read_2(sc) == 0x55aa) {
142 			rln_data_write_2(sc, 0x0000);
143 			sc->sc_width = 16;
144 		} else {
145 			if (sc->sc_cardtype & (RLN_CTYPE_UISA |
146 			    RLN_CTYPE_ONE_PIECE))
147 				rln_control_write(sc, RLN_CONTROL_BIT3);
148 			else
149 				rln_control_write(sc, RLN_CONTROL_BIT3 |
150 				    RLN_CONTROL_BIT2);
151 			rln_data_write_1(sc, 0x20);
152 			sc->sc_width = 8;
153 		}
154 		/* printf("%s: %d bit bus\n", sc->sc_dev.dv_xname,
155 		   sc->sc_width); */
156 	}
157 	rln_status_write(sc, 0x00);
158 	sc->sc_intsel = 0;
159 	rln_intsel_write(sc, sc->sc_irq);
160 	splx(s);
161 	dprintf("]");
162 	return (0);
163 }
164 
165 /*
166  * Sets the new 'wakeup' state. Returns the old wakeup state.
167  * The special state value RLN_WAKEUP_SET should be used to wake the
168  * card up. The card can be partially put to sleep (presumably to save
169  * power) by sending it the 'Standby' command.
170  */
171 u_int8_t
rln_wakeup(sc,wnew)172 rln_wakeup(sc, wnew)
173 	struct rln_softc *	sc;
174 	u_int8_t		wnew;
175 {
176 	u_int8_t		wold, s;
177 	int			i;
178 
179 	/* Save what the last-written values were. */
180 	wold = (sc->sc_status & RLN_STATUS_WAKEUP) |
181 	    (sc->sc_control & RLN_CONTROL_RESET);
182 
183 	if (wnew == RLN_WAKEUP_SET) {
184 		/* SetWakeupBit() */
185 		dprintf(" Ws[");
186 		rln_status_set(sc, RLN_STATUS_WAKEUP);
187 		if (0/*LLDInactivityTimeOut &&
188 		    (sc->sc_cardtype & RLN_CTYPE_OEM)*/) {
189 			dprintf (" 167ms");
190 			DELAY(167000);
191 		} else {
192 			dprintf (" .1ms");
193 			DELAY(100);
194 		}
195 		s = rln_status_read(sc);
196 		rln_control_set(sc, RLN_CONTROL_RESET);
197 		if ((s & RLN_STATUS_WAKEUP) != 0)
198 			for (i = 0; i < 9; i++) {
199 				dprintf(" 2ms");
200 				DELAY(2000);
201 				rln_status_set(sc, RLN_STATUS_WAKEUP);
202 			}
203 		dprintf("]");
204 	} else {
205 		/* ClearWakeupBit() */
206 		dprintf(" Wc[");
207 		if ((wnew & RLN_STATUS_WAKEUP) == 0)
208 			rln_status_clear(sc, RLN_STATUS_WAKEUP);
209 		if ((wnew & RLN_CONTROL_RESET) == 0)
210 			rln_control_clear(sc, RLN_CONTROL_RESET);
211 		dprintf("]");
212 	}
213 	return (wold);
214 }
215 
216 /*
217  * Performs the first (request) stage of transmitting a command message
218  * to the card. 'len' is the expected length of the message is needed.
219  * Returns: 0 on success
220  *          1 on timeout
221  *          2 on NAK (card busy, and will need a rln_clear_nak() after 100ms)
222  */
223 static int
rln_tx_request(sc,len)224 rln_tx_request(sc, len)
225 	struct rln_softc *	sc;
226 	u_int16_t		len;
227 {
228 	/* TxRequest() */
229 	int			s;
230 	int			i;
231 	u_int8_t		status;
232 
233 	/* u_int8_t w; */
234 	/* w = rln_wakeup(sc, RLN_WAKEUP_SET); */
235 
236 	dprintf(" Tr[");
237 	if (sc->sc_width == 16) {
238 		rln_status_tx_write(sc, RLN_STATUS_TX_HILEN_AVAIL);
239 		rln_data_write_2(sc, len);
240 		rln_status_tx_int(sc);
241 
242 		s = spl0();
243 		for (i = 0; i < 600; i++) {
244 			status = rln_status_tx_read(sc);
245 			if (status == RLN_STATUS_TX_HILEN_ACCEPT ||
246 			    status == RLN_STATUS_TX_ERROR)
247 				break;
248 			DELAY(1000);
249 		}
250 		splx(s);
251 		dprintf(" %dms", i);
252 		if (status == RLN_STATUS_TX_HILEN_ACCEPT)
253 			goto success;
254 		if (status == RLN_STATUS_TX_ERROR)
255 			goto error;
256 	} else if (sc->sc_width == 8) {
257 		rln_status_tx_write(sc, RLN_STATUS_TX_LOLEN_AVAIL);
258 		rln_data_write_1(sc, len & 0xff);
259 		rln_status_tx_int(sc);
260 		s = spl0();
261 		for (i = 0; i < 6800; i++) {
262 			status = rln_status_tx_read(sc);
263 			if (status == RLN_STATUS_TX_LOLEN_ACCEPT)
264 				break;
265 			DELAY(1000);
266 		}
267 		splx(s);
268 		dprintf(" %dms", i);
269 		if (status == RLN_STATUS_TX_LOLEN_ACCEPT) {
270 			rln_data_write_1(sc, (len >> 8) & 0xff);
271 			rln_status_tx_write(sc, RLN_STATUS_TX_HILEN_AVAIL);
272 			s = spl0();
273 			for (i = 0; i < 600; i++) {
274 				status = rln_status_tx_read(sc);
275 				if (status == RLN_STATUS_TX_HILEN_ACCEPT ||
276 				    status == RLN_STATUS_TX_ERROR)
277 					break;
278 				DELAY(1000);
279 			}
280 			splx(s);
281 			dprintf(" %dms", i);
282 			if (status == RLN_STATUS_TX_HILEN_ACCEPT)
283 				goto success;
284 			if (status == RLN_STATUS_TX_ERROR)
285 				goto error;
286 		}
287 	}
288 #ifdef DIAGNOSTIC
289 	else
290 		panic("rln: bus width");
291 #endif
292 
293 	printf("%s: tx_request timed out, status 0x%02x",
294 	    sc->sc_dev.dv_xname, status);
295 	dprintf("]=(1)");
296 	return (1);
297 
298 error:
299 	/* Will need to clear nak within 100 ms. */
300 	dprintf("]=2");
301 #ifdef DIAGNOSTIC
302 	printf("%s: tx protocol fault (nak)\n", sc->sc_dev.dv_xname);
303 #endif
304 	return (2);
305 
306 success:
307 	/* rln_wakeup(sc, w); */
308 	dprintf("]=0");
309 	return (0);
310 }
311 
312 /*
313  * Performs the third (and final) stage of transmitting a command
314  * message to the card.
315  * Returns: 0 on command success.
316  *          non-zero on failure (card will need reset)
317  */
318 static int
rln_tx_end(sc)319 rln_tx_end(sc)
320 	struct rln_softc * sc;
321 {
322 	/* EndOfTx() */
323 	int		i;
324 	int		s;
325 	u_int8_t	status;
326 
327 	dprintf(" Te[");
328 	s = spl0();
329 	for (i = 0; i < 600; i++) {
330 		status = rln_status_tx_read(sc);
331 		if (status == RLN_STATUS_TX_XFR_COMPLETE)
332 			break;
333 		DELAY(1000);
334 	}
335 	splx(s);
336 	if (status == RLN_STATUS_TX_XFR_COMPLETE) {
337 		rln_status_tx_write(sc, RLN_STATUS_TX_IDLE);
338 		dprintf("]=0");
339 		return (0);
340 	} else {
341 		printf("%s: tx cmd failed (%02x)\n", sc->sc_dev.dv_xname,
342 		    status);
343 		rln_need_reset(sc);
344 		dprintf("]=-1");
345 		return (-1);
346 	}
347 }
348 
349 /*
350  * Performs first (request) stage of receiving a message from the card.
351  * Returns: 0 on failure,
352  *          n>0 on success, where 'n' is the length of the message
353  */
354 
355 int
rln_rx_request(sc,timeo)356 rln_rx_request(sc, timeo)
357 	struct rln_softc *	sc;
358 	int 			timeo;	/* milliseconds */
359 {
360 	/* RxRequest */
361 	int			s;
362 	int			len = 0;
363 	int			i;
364 	u_int8_t		status;
365 	u_int8_t		hi, lo;
366 
367 	dprintf(" Rr[");
368 	status = rln_status_rx_read(sc);
369 
370 	/* Short wait for states 1|5|6. */
371 	s = spl0();
372 	for (i = 0; i < timeo; i++) {
373 		if (status == RLN_STATUS_RX_LOLEN_AVAIL ||
374 		    status == RLN_STATUS_RX_HILEN_AVAIL ||
375 		    status == RLN_STATUS_RX_ERROR)
376 			break;
377 		DELAY(1000);
378 		status = rln_status_rx_read(sc);
379 	}
380 	splx(s);
381 	dprintf(" (%dms)",i);
382 
383 	if (sc->sc_width == 16) {
384 		if (status != RLN_STATUS_RX_HILEN_AVAIL)
385 			goto badstatus_quiet;
386 		/* Read 2 octets. */
387 		len = rln_data_read_2(sc);
388 	} else if (sc->sc_width == 8) {
389 		if (status != RLN_STATUS_RX_LOLEN_AVAIL)
390 			goto badstatus_quiet;
391 		/* Read low octet. */
392 		lo = rln_data_read_1(sc);
393 		rln_status_rx_write(sc, RLN_STATUS_RX_LOLEN_ACCEPT);
394 		rln_status_rx_int(sc);
395 		s = spl0();
396 		for (i = 0; i < 600; i++) {
397 			status = rln_status_rx_read(sc);
398 			if (status == RLN_STATUS_RX_HILEN_AVAIL)
399 				break;
400 			DELAY(1000);
401 		}
402 		splx(s);
403 		if (status != RLN_STATUS_RX_HILEN_AVAIL)
404 			goto badstatus;
405 		/* Read high octet. */
406 		hi = rln_data_read_1(sc);
407 		len = lo | (hi << 8);
408 	}
409 #ifdef DIAGNOSTIC
410 	else
411 		panic("rln: bus width %d", sc->sc_width);
412 #endif
413 
414 	dprintf(" len=%d]", len);
415 	return (len);
416 
417 badstatus:
418 	printf("%s: rx_request timed out, status %02x\n",
419 	    sc->sc_dev.dv_xname, status);
420 badstatus_quiet:
421 	if (status == RLN_STATUS_RX_ERROR)
422 		printf("%s: rx protocol error (nak)\n", sc->sc_dev.dv_xname);
423 	dprintf("]");
424 	return (-1);
425 }
426 
427 /* Performs part of the second (transfer) stage of receiving a data message. */
428 void
rln_rx_pdata(sc,buf,len,pd)429 rln_rx_pdata(sc, buf, len, pd)
430 	struct rln_softc *	sc;
431 	void *			buf;
432 	int			len;
433 	struct rln_pdata *	pd;
434 {
435 	char *			data = (char *)buf;
436 
437 	if (pd->p_nremain) {
438 		*data++ = pd->p_data;
439 		if (--len == 0)
440 			return;
441 	}
442 
443 	pd->p_nremain = 0;
444 
445 	if (sc->sc_width == 16) {
446 		/* Round down to the closest even multiple. */
447 		rln_data_read_multi_2(sc, data, len / 2);
448 #ifdef RLNDEBUG_REG
449 		dprintf(" D>");
450 		dprinthex(data, len);
451 #endif
452 		if (len & 1) {
453 			/* Read the last octet plus a bit extra. */
454 			union {
455 				u_int16_t w;
456 				u_int8_t  b[2];
457 			} u;
458 
459 			u.w = rln_data_read_2(sc);
460 			data[len - 1] = u.b[0];
461 			pd->p_data = u.b[1];
462 			pd->p_nremain = 1;
463 #ifdef RLNDEBUG_REG
464 			dprintf(" D>{%02x%02x}", u.b[0], u.b[1]);
465 #endif
466 		}
467 	} else if (sc->sc_width == 8) {
468 		rln_data_read_multi_1(sc, data, len);
469 #ifdef RLNDEBUG_REG
470 		dprintf(" D>");
471 		dprinthex(data, len);
472 #endif
473 		if (len & 1) {
474 			/* Must read multiples of two. */
475 			pd->p_data = rln_data_read_1(sc);
476 			pd->p_nremain = 1;
477 #ifdef RLNDEBUG_REG
478 			dprintf(" D>{%02x}", pd->p_data);
479 #endif
480 		}
481 	}
482 
483 }
484 
485 int
rln_rx_data(sc,buf,len)486 rln_rx_data(sc, buf, len)
487 	struct rln_softc *	sc;
488 	void *			buf;
489 	int			len;
490 {
491 	/* RxData() */
492 	struct rln_pdata	pd = { 0, 0 };
493 	int			s;
494 	int			i;
495 	u_int8_t		status;
496 
497 	dprintf(" Rd[");
498 	rln_status_rx_write(sc, RLN_STATUS_RX_HILEN_ACCEPT);
499 	rln_status_rx_int(sc);
500 	s = spl0();
501 	for (i = 0; i < 600; i++) {
502 		status = rln_status_rx_read(sc);
503 		if (status == RLN_STATUS_RX_XFR)
504 			break;
505 		DELAY(1000);
506 	}
507 	splx(s);
508 	if (status != RLN_STATUS_RX_XFR) {
509 		dprintf("]=-1");
510 		return (-1);
511 	}
512 
513 	rln_rx_pdata(sc, buf, len, &pd);
514 #ifdef DIAGNOSTIC
515 	/* We should have nothing left over. */
516 	if (pd.p_nremain || len & 1)
517 		panic("rln_rx_data: leftover");
518 #endif
519 
520 	dprintf("]=0");
521 	return (0);
522 }
523 
524 void
rln_rx_end(sc)525 rln_rx_end(sc)
526 	struct rln_softc * sc;
527 {
528 	/* EndOfRx() */
529 
530 	dprintf(" Re[");
531 	rln_status_rx_write(sc, RLN_STATUS_RX_XFR_COMPLETE);
532 	rln_status_rx_int(sc);
533 	/* rln_wakeup(sc, 0); */
534 	dprintf("]");
535 }
536 
537 /* Clear a transmission NAK from the card. */
538 void
rln_clear_nak(sc)539 rln_clear_nak(sc)
540 	struct rln_softc * sc;
541 {
542 	/* ClearNAK() */
543 
544 	rln_status_tx_write(sc, RLN_STATUS_CLRNAK);
545 	rln_status_tx_int(sc);
546 }
547 
548 /*
549  * Send a command message to the card. Returns;
550  *	2: NAK
551  *	-1: failure
552  *	0: success
553  */
554 int
rln_msg_tx_start(sc,buf,pktlen,state)555 rln_msg_tx_start(sc, buf, pktlen, state)
556 	struct rln_softc *	sc;
557 	void *			buf;
558 	int			pktlen;
559 	struct rln_msg_tx_state * state;
560 {
561 	struct rln_mm_cmd *	cmd = (struct rln_mm_cmd *)buf;
562 	int			ret;
563 
564 	state->ien = rln_enable(sc, 0);
565 	state->pd.p_nremain = 0;
566 
567 	if (!(cmd->cmd_letter == 'A' && cmd->cmd_fn == 6)) 	/* Standby. */
568 		state->w = rln_wakeup(sc, RLN_WAKEUP_SET);
569 	else
570 		state->w = RLN_WAKEUP_NOCHANGE;
571 
572 	ret = rln_tx_request(sc, pktlen);
573 	if (ret == 2) {
574 		rln_clear_nak(sc);
575 		if (sc->sc_cardtype & RLN_CTYPE_OEM)
576 			rln_need_reset(sc);
577 		ret = 2;
578 	}
579 	else if (ret == 1) {
580 		/* Timeout. */
581 		rln_status_tx_write(sc, RLN_STATUS_TX_XFR);
582 		ret = -1;
583 	}
584 	return (ret);
585 }
586 
587 void
rln_msg_tx_data(sc,buf,len,state)588 rln_msg_tx_data(sc, buf, len, state)
589 	struct rln_softc *	sc;
590 	void *			buf;
591 	u_int16_t		len;
592 	struct rln_msg_tx_state * state;
593 {
594 	char *			data = (char *)buf;
595 
596 	if (sc->sc_width == 16 && state->pd.p_nremain) {
597 		/* XXX htons() needed? */
598 		union {
599 			u_int8_t  b[2];
600 			u_int16_t w;
601 		} u;
602 
603 		u.b[0] = state->pd.p_data;
604 		if (len) {
605 			u.b[1] = *data++;
606 			len--;
607 		} else
608 			u.b[1] = '\0';
609 #ifdef RLNDEBUG_REG
610 		dprintf(" D<%02x%02x", u.b[0], u.b[1]);
611 #endif
612 		rln_data_write_2(sc, u.w);
613 		state->pd.p_nremain = 0;
614 	}
615 
616 	if (len) {
617 		if (sc->sc_width == 16) {
618 			if (len >= 2)
619 				rln_data_write_multi_2(sc, buf, len / 2);
620 			if (len & 1) {
621 				state->pd.p_nremain = 1;
622 				state->pd.p_data = data[len - 1];
623 			}
624 		} else if (sc->sc_width == 8)
625 			rln_data_write_multi_1(sc, buf, len);
626 #ifdef DIAGNOSTIC
627 		else
628 			panic("rln_msg_tx_data width %d", sc->sc_width);
629 #endif
630 #ifdef RLNDEBUG_REG
631 		dprintf(" D<");
632 		dprinthex(data, len);
633 #endif
634 	}
635 }
636 
637 
638 int
rln_msg_tx_end(sc,state)639 rln_msg_tx_end(sc, state)
640 	struct rln_softc *	sc;
641 	struct rln_msg_tx_state * state;
642 {
643 	int			ret;
644 
645 	/* Flush the tx buffer. */
646 	if (state->pd.p_nremain)
647 		rln_msg_tx_data(sc, NULL, 0, state);
648 
649 #ifdef DIAGNOSTIC
650 	if (state->pd.p_nremain)
651 		panic("rln_msg_tx_end remain %d", state->pd.p_nremain);
652 #endif
653 	ret = rln_tx_end(sc);
654 	if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE)
655 		state->w = RLN_WAKEUP_NOCHANGE;
656 	rln_wakeup(sc, state->w);
657 	rln_enable(sc, state->ien);
658 	return (ret);
659 }
660 
661 /* Return the next unique sequence number to use for a transmitted command */
662 u_int8_t
rln_newseq(sc)663 rln_newseq(sc)
664 	struct rln_softc * sc;
665 {
666 	int s;
667 	u_int8_t seq;
668 
669 	s = splhigh();
670 	seq = sc->sc_pktseq++;
671 	if (sc->sc_pktseq > RLN_MAXSEQ)
672 		sc->sc_pktseq = 0;
673 	splx(s);
674 	return (seq);
675 }
676 
677 /*
678  * Transmit a command message to, and (optionally) receive a response
679  * message from the card.  Each transmitted message has a sequence
680  * number, and corresponding reply messages have the same sequence
681  * number.  We use the sequence numbers to index the mailboxes so
682  * that rlnsoftintr() can signal this routine when it has serviced
683  * and correctly received a response.
684  */
685 
686 int
rln_msg_txrx(sc,tx,txlen,rx,rxlen)687 rln_msg_txrx(sc, tx, txlen, rx, rxlen)
688 	struct rln_softc *	sc;
689 	void *			tx;
690 	int 			txlen;
691 	void *			rx;
692 	int			rxlen;
693 {
694 	struct rln_mm_cmd *	txc = (struct rln_mm_cmd *)tx;
695 	struct rln_mm_cmd *	rxc = (struct rln_mm_cmd *)rx;
696 	struct rln_msg_tx_state state;
697 	int			ien;
698 	int			ret;
699 
700 #ifdef DIAGNOSTIC
701 	if (rx != NULL && rxlen < sizeof *rxc)
702 		panic("rln_msg_txrx");
703 #endif
704 
705 	txc->cmd_seq = rln_newseq(sc);
706 
707 #ifdef RLNDUMP
708 	printf("%s: send %c%d seq %d data ", sc->sc_dev.dv_xname,
709 	    txc->cmd_letter, txc->cmd_fn, txc->cmd_seq);
710 	RLNDUMPHEX(txc, sizeof *txc);
711 	printf(":");
712 	RLNDUMPHEX((char *)tx + sizeof *txc, txlen - sizeof *txc);
713 	printf("\n");
714 #endif
715 
716 	if (rx != NULL)
717 		if (rln_mbox_create(sc, txc->cmd_seq, rx, rxlen) < 0)
718 			/* Mailbox collision. */
719 			return (-1);
720 
721 	/* Start the transfer. */
722 	if ((ret = rln_msg_tx_start(sc, tx, txlen, &state))) {
723 		if (rx != NULL)
724 			rln_mbox_wait(sc, txc->cmd_seq, -1);
725 		return (ret);
726 	}
727 
728 	/* Always send an even number of octets. */
729 	rln_msg_tx_data(sc, tx, (txlen + 1) & ~1, &state);
730 
731 	/* End the transmission. */
732 	if ((ret = rln_msg_tx_end(sc, &state))) {
733 		/* Destroy mailbox. */
734 		if (rx != NULL)
735 			rln_mbox_wait(sc, txc->cmd_seq, -1);
736 		return (ret);
737 	}
738 
739 	/* Don't wait for reply if there is nowhere to put it. */
740 	if (rx == NULL)
741 		return (0);
742 
743 	/* Enable interrupts if not already. */
744 	ien = rln_enable(sc, 1);
745 
746 	/* Wait for the reply message. */
747 	if (rln_mbox_wait(sc, txc->cmd_seq, 4000) <= 0) {
748 		printf("%s: lost message %c%d seq %d\n", sc->sc_dev.dv_xname,
749 			txc->cmd_letter, txc->cmd_fn, txc->cmd_seq);
750 		rln_enable(sc, ien);
751 		return (-1);
752 	}
753 	rln_enable(sc, ien);
754 
755 #ifdef RLNDUMP
756 	printf("%s: recv %c%d seq %d data ", sc->sc_dev.dv_xname,
757 	    rxc->cmd_letter, rxc->cmd_fn, rxc->cmd_seq);
758 	RLNDUMPHEX(rxc, sizeof *rxc);
759 	printf(":");
760 	RLNDUMPHEX(((char *)rx) + sizeof *rxc, rxlen - sizeof *rxc);
761 	printf("\n");
762 #endif
763 
764 	/* Check for errors in the received message. */
765 	if (rxc->cmd_error & 0x80) {
766 		printf("%s: command error 0x%02x command %c%d\n",
767 			sc->sc_dev.dv_xname,
768 			rxc->cmd_error & ~0x80,
769 			rxc->cmd_letter, rxc->cmd_fn);
770 		return (-1);
771 	}
772 
773 	return (0);
774 }
775 
776 /*
777  * Mailboxes provide a simple way to tell the interrupt
778  * service routine that someone is expecting a reply message.
779  * Mailboxes are identified by the message sequence number
780  * and also hold a pointer to storage supplied by the waiter.
781  * The interrupt service routine signals the mailbox when it
782  * gets the reply message.
783  */
784 
785 /* Create a mailbox for filling. */
786 int
rln_mbox_create(sc,seq,buf,len)787 rln_mbox_create(sc, seq, buf, len)
788 	struct rln_softc *	sc;
789 	u_int8_t		seq;
790 	void *			buf;
791 	size_t			len;
792 {
793 	int			s;
794 	struct rln_mbox *	mb = &sc->sc_mbox[seq];
795 
796 	dprintf(" <create %d", seq);
797 
798 #ifdef DIAGNOSTIC
799 	if (seq > RLN_NMBOX)
800 		panic("mbox create");
801 #endif
802 
803 	s = splhigh();
804 	if (mb->mb_state != RLNMBOX_VOID) {
805 #ifdef DIAGNOSTIC
806 		printf("mbox collision");
807 #endif
808 		splx(s);
809 		return (-1);
810 	}
811 	mb->mb_buf = buf;
812 	mb->mb_len = len;
813 	mb->mb_actlen = 0;
814 	mb->mb_state = RLNMBOX_EMPTY;
815 	dprintf(" empty>");
816 	splx(s);
817 	return (0);
818 }
819 
820 
821 /* Wait for a mailbox to be filled. */
822 int
rln_mbox_wait(sc,seq,timeo)823 rln_mbox_wait(sc, seq, timeo)
824 	struct rln_softc *	sc;
825 	u_int8_t		seq;
826 	int			timeo;
827 {
828 	int			i;
829 	int			s;
830 	int			ret;
831 	volatile struct rln_mbox * mb = &sc->sc_mbox[seq];
832 
833 	dprintf(" <wait %d", seq);
834 
835 #ifdef DIAGNOSTIC
836 	if (seq > RLN_NMBOX)
837 		panic("mbox wait");
838 #endif
839 
840 #if defined(RLN_TSLEEP)
841 	if (!cold) {
842 		tsleep((void *)mb, PRIBIO, "rlnmbox", hz * timeo / 1000);
843 		if (mb->mb_state == RLNMBOX_FILLING) {
844 			/* Must wait until filled. */
845 			s = spl0();
846 			while (mb->mb_state == RLNMBOX_FILLING)
847 				;
848 			splx(s);
849 		}
850 	} else {
851 		/* Autoconfiguration - spin at spl0. */
852 #endif
853 		s = spl0();
854 		i = 0;
855 		while (mb->mb_state == RLNMBOX_EMPTY && i < timeo) {
856 			DELAY(1000);
857 			i++;
858 		}
859 		if (i)
860 			dprintf(" %dms", i);
861 		while (mb->mb_state == RLNMBOX_FILLING)
862 			;
863 		splx(s);
864 #if defined(RLN_TSLEEP)
865 	}
866 #endif
867 
868 	s = splhigh();
869 
870 #ifdef DIAGNOSTIC
871 	if (mb->mb_state != RLNMBOX_EMPTY && mb->mb_state != RLNMBOX_FILLED)
872 		panic("mbox wait %d", mb->mb_state);
873 #endif
874 	ret = mb->mb_actlen;
875 	mb->mb_state = RLNMBOX_VOID;
876 	dprintf(" void>=%d", ret);
877 	splx(s);
878 	return (ret);
879 }
880 
881 /* Lock a mailbox for filling. */
882 int
rln_mbox_lock(sc,seq,bufp,lenp)883 rln_mbox_lock(sc, seq, bufp, lenp)
884 	struct rln_softc *	sc;
885 	u_int8_t		seq;
886 	void **			bufp;
887 	size_t *		lenp;
888 {
889 	int			s;
890 	struct rln_mbox *	mb = &sc->sc_mbox[seq];
891 
892 	dprintf(" <lock %d", seq);
893 
894 	s = splhigh();
895 #ifdef DIAGNOSTIC
896 	if (seq > RLN_NMBOX)
897 		panic("mbox lock");
898 #endif
899 	if (mb->mb_state != RLNMBOX_EMPTY) {
900 		splx(s);
901 		dprintf(" ?>");
902 		return (-1);
903 	}
904 
905 	mb->mb_state = RLNMBOX_FILLING;
906 	dprintf(" filling>");
907 	*bufp = mb->mb_buf;
908 	*lenp = mb->mb_len;
909 
910 	splx(s);
911 	return (0);
912 }
913 
914 /* Unlock a mailbox and inform the waiter of the actual number of octets. */
915 void
rln_mbox_unlock(sc,seq,actlen)916 rln_mbox_unlock(sc, seq, actlen)
917 	struct rln_softc *	sc;
918 	u_int8_t		seq;
919 	size_t			actlen;
920 {
921 	int			s;
922 	struct rln_mbox *	mb = &sc->sc_mbox[seq];
923 
924 	dprintf(" <unlock %d", seq);
925 
926 	s = splhigh();
927 #ifdef DIAGNOSTIC
928 	if (seq > RLN_NMBOX)
929 		panic("mbox unlock seq");
930 	if (mb->mb_state != RLNMBOX_FILLING)
931 		panic("mbox unlock");
932 #endif
933 	mb->mb_state = RLNMBOX_FILLED;
934 	dprintf(" filled>");
935 	mb->mb_actlen = actlen;
936 #if defined(RLN_TSLEEP)
937 	wakeup(mb);
938 #endif
939 	splx(s);
940 }
941 
942