[BACK]Return to rlnsubr.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

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