Annotation of sys/dev/ic/rlnsubr.c, Revision 1.1.1.1
1.1 nbrk 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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:
CVSweb