root/dev/ic/rlnsubr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rln_enable
  2. rln_reset
  3. rln_wakeup
  4. rln_tx_request
  5. rln_tx_end
  6. rln_rx_request
  7. rln_rx_pdata
  8. rln_rx_data
  9. rln_rx_end
  10. rln_clear_nak
  11. rln_msg_tx_start
  12. rln_msg_tx_data
  13. rln_msg_tx_end
  14. rln_newseq
  15. rln_msg_txrx
  16. rln_mbox_create
  17. rln_mbox_wait
  18. rln_mbox_lock
  19. rln_mbox_unlock

    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 

/* [<][>][^][v][top][bottom][index][help] */