diff options
Diffstat (limited to 'sys/dev/ic/rlnsubr.c')
-rw-r--r-- | sys/dev/ic/rlnsubr.c | 941 |
1 files changed, 0 insertions, 941 deletions
diff --git a/sys/dev/ic/rlnsubr.c b/sys/dev/ic/rlnsubr.c deleted file mode 100644 index 7c4d2f95196..00000000000 --- a/sys/dev/ic/rlnsubr.c +++ /dev/null @@ -1,941 +0,0 @@ -/* $OpenBSD: rlnsubr.c,v 1.5 2002/03/14 01:26:55 millert Exp $ */ -/* - * David Leonard <d@openbsd.org>, 1999. Public Domain. - * - * Low level card protocol access to the Proxim RangeLAN2 wireless - * network adaptor. - * - * Information and ideas gleaned from - * - disassembly of Dave Koberstein's <davek@komacke.com> Linux driver - * (which is built with Proxim source), - * - Yoichi Shinoda's <shinoda@cs.washington.edu> BSDI driver, and - * - Geoff Voelker's <voelker@cs.washington.edu> Linux port of the same. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/syslog.h> -#include <sys/device.h> -#include <sys/queue.h> -#include <sys/proc.h> -#include <sys/kernel.h> - -#include <net/if.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/if_ether.h> -#endif - -#include <machine/bus.h> -#include <machine/intr.h> - -#include <dev/ic/rln.h> -#include <dev/ic/rlnvar.h> -#include <dev/ic/rlnreg.h> -#include <dev/ic/rlncmd.h> - -static int rln_tx_request(struct rln_softc *, u_int16_t); -static int rln_tx_end(struct rln_softc *); - -/* - * Disables or enables interrupts from the card. Returns the old - * interrupt-enable state. - */ -int -rln_enable(sc, enable) - struct rln_softc * sc; - int enable; -{ - int s; - int was_enabled; - - s = splhigh(); - was_enabled = (sc->sc_intsel & RLN_INTSEL_ENABLE) ? 1 : 0; - if (enable != was_enabled) { - if (enable) - sc->sc_intsel |= RLN_INTSEL_ENABLE; - else - sc->sc_intsel &=~RLN_INTSEL_ENABLE; - _rln_register_write_1(sc, RLN_REG_INTSEL, sc->sc_intsel); - } - splx(s); - return (was_enabled); -} - -/* - * Perform a hard reset of the card. Determines bus width (8 or - * 16 bit), if sc->sc_width is unset. Returns 0 on success. - * Note: takes about 200ms at splhigh, meaning this is an expensive call, - * but normal (error-free) operation of the card will not need more than - * two resets - one at probe time, and the other when the interface is - * brought up. - */ -int -rln_reset(sc) - struct rln_softc * sc; -{ - int s; - int i; - int status; - u_int8_t op = 0x00; - - s = splhigh(); - dprintf(" R["); - if (sc->sc_cardtype & (RLN_CTYPE_UISA | RLN_CTYPE_ONE_PIECE)) - op = 0x04; - if (rln_status_read(sc) & RLN_STATUS_WAKEUP) { - rln_control_write(sc, op); - rln_control_write(sc, op | RLN_CONTROL_RESET); - dprintf(" 7ms"); - DELAY(7000); - rln_control_write(sc, op); - dprintf(" 7ms"); - DELAY(7000); - } - rln_control_write(sc, op); - rln_control_write(sc, op); - rln_control_write(sc, op | RLN_CONTROL_BIT3); - dprintf(" 67ms"); - DELAY(67000); - rln_status_write(sc, 0x00); - if (sc->sc_cardtype & (RLN_CTYPE_UISA | RLN_CTYPE_ONE_PIECE)) - rln_control_write(sc, 0x38); - /* RLN_CONTROL_BIT3 | RLN_CONTROL_RESET | RLN_CONTROL_16BIT */ - else - rln_control_write(sc, 0x2c); - /* RLN_CONTROL_BIT3 | RLN_CONTROL_BIT2 | RLN_CONTROL_16BIT */ - dprintf(" 67ms"); - DELAY(67000); - rln_data_write_2(sc, 0xaa55); - rln_status_write(sc, 0x5a); - splx(s); - for (i = 0; i < 200 * 10; i++) { /* Proxim says 200. */ - if ((status = rln_status_read(sc)) == 0x5a) - break; - DELAY(1000); - } - dprintf(" (%dms)", i); - s = splhigh(); - if (status != 0x5a) { - splx(s); - /* Only winge if bus width not yet probed */ - if (sc->sc_width != 0) - printf("%s: reset timeout\n", sc->sc_dev.dv_xname); - dprintf("]=-1"); - return (-1); - } - if (sc->sc_width == 8) { - if (sc->sc_cardtype & (RLN_CTYPE_UISA | RLN_CTYPE_ONE_PIECE)) - rln_control_write(sc, RLN_CONTROL_BIT3); - else - rln_control_write(sc, RLN_CONTROL_BIT3 | - RLN_CONTROL_BIT2); - rln_data_write_1(sc, 0x20); - } else if (sc->sc_width == 16) { - rln_data_write_2(sc, 0x0000); - } else { - if (rln_data_read_2(sc) == 0x55aa) { - rln_data_write_2(sc, 0x0000); - sc->sc_width = 16; - } else { - if (sc->sc_cardtype & (RLN_CTYPE_UISA | - RLN_CTYPE_ONE_PIECE)) - rln_control_write(sc, RLN_CONTROL_BIT3); - else - rln_control_write(sc, RLN_CONTROL_BIT3 | - RLN_CONTROL_BIT2); - rln_data_write_1(sc, 0x20); - sc->sc_width = 8; - } - /* printf("%s: %d bit bus\n", sc->sc_dev.dv_xname, - sc->sc_width); */ - } - rln_status_write(sc, 0x00); - sc->sc_intsel = 0; - rln_intsel_write(sc, sc->sc_irq); - splx(s); - dprintf("]"); - return (0); -} - -/* - * Sets the new 'wakeup' state. Returns the old wakeup state. - * The special state value RLN_WAKEUP_SET should be used to wake the - * card up. The card can be partially put to sleep (presumably to save - * power) by sending it the 'Standby' command. - */ -u_int8_t -rln_wakeup(sc, wnew) - struct rln_softc * sc; - u_int8_t wnew; -{ - u_int8_t wold, s; - int i; - - /* Save what the last-written values were. */ - wold = (sc->sc_status & RLN_STATUS_WAKEUP) | - (sc->sc_control & RLN_CONTROL_RESET); - - if (wnew == RLN_WAKEUP_SET) { - /* SetWakeupBit() */ - dprintf(" Ws["); - rln_status_set(sc, RLN_STATUS_WAKEUP); - if (0/*LLDInactivityTimeOut && - (sc->sc_cardtype & RLN_CTYPE_OEM)*/) { - dprintf (" 167ms"); - DELAY(167000); - } else { - dprintf (" .1ms"); - DELAY(100); - } - s = rln_status_read(sc); - rln_control_set(sc, RLN_CONTROL_RESET); - if ((s & RLN_STATUS_WAKEUP) != 0) - for (i = 0; i < 9; i++) { - dprintf(" 2ms"); - DELAY(2000); - rln_status_set(sc, RLN_STATUS_WAKEUP); - } - dprintf("]"); - } else { - /* ClearWakeupBit() */ - dprintf(" Wc["); - if ((wnew & RLN_STATUS_WAKEUP) == 0) - rln_status_clear(sc, RLN_STATUS_WAKEUP); - if ((wnew & RLN_CONTROL_RESET) == 0) - rln_control_clear(sc, RLN_CONTROL_RESET); - dprintf("]"); - } - return (wold); -} - -/* - * Performs the first (request) stage of transmitting a command message - * to the card. 'len' is the expected length of the message is needed. - * Returns: 0 on success - * 1 on timeout - * 2 on NAK (card busy, and will need a rln_clear_nak() after 100ms) - */ -static int -rln_tx_request(sc, len) - struct rln_softc * sc; - u_int16_t len; -{ - /* TxRequest() */ - int s; - int i; - u_int8_t status; - - /* u_int8_t w; */ - /* w = rln_wakeup(sc, RLN_WAKEUP_SET); */ - - dprintf(" Tr["); - if (sc->sc_width == 16) { - rln_status_tx_write(sc, RLN_STATUS_TX_HILEN_AVAIL); - rln_data_write_2(sc, len); - rln_status_tx_int(sc); - - s = spl0(); - for (i = 0; i < 600; i++) { - status = rln_status_tx_read(sc); - if (status == RLN_STATUS_TX_HILEN_ACCEPT || - status == RLN_STATUS_TX_ERROR) - break; - DELAY(1000); - } - splx(s); - dprintf(" %dms", i); - if (status == RLN_STATUS_TX_HILEN_ACCEPT) - goto success; - if (status == RLN_STATUS_TX_ERROR) - goto error; - } else if (sc->sc_width == 8) { - rln_status_tx_write(sc, RLN_STATUS_TX_LOLEN_AVAIL); - rln_data_write_1(sc, len & 0xff); - rln_status_tx_int(sc); - s = spl0(); - for (i = 0; i < 6800; i++) { - status = rln_status_tx_read(sc); - if (status == RLN_STATUS_TX_LOLEN_ACCEPT) - break; - DELAY(1000); - } - splx(s); - dprintf(" %dms", i); - if (status == RLN_STATUS_TX_LOLEN_ACCEPT) { - rln_data_write_1(sc, (len >> 8) & 0xff); - rln_status_tx_write(sc, RLN_STATUS_TX_HILEN_AVAIL); - s = spl0(); - for (i = 0; i < 600; i++) { - status = rln_status_tx_read(sc); - if (status == RLN_STATUS_TX_HILEN_ACCEPT || - status == RLN_STATUS_TX_ERROR) - break; - DELAY(1000); - } - splx(s); - dprintf(" %dms", i); - if (status == RLN_STATUS_TX_HILEN_ACCEPT) - goto success; - if (status == RLN_STATUS_TX_ERROR) - goto error; - } - } -#ifdef DIAGNOSTIC - else - panic("rln: bus width"); -#endif - - printf("%s: tx_request timed out, status 0x%02x", - sc->sc_dev.dv_xname, status); - dprintf("]=(1)"); - return (1); - -error: - /* Will need to clear nak within 100 ms. */ - dprintf("]=2"); -#ifdef DIAGNOSTIC - printf("%s: tx protocol fault (nak)\n", sc->sc_dev.dv_xname); -#endif - return (2); - -success: - /* rln_wakeup(sc, w); */ - dprintf("]=0"); - return (0); -} - -/* - * Performs the third (and final) stage of transmitting a command - * message to the card. - * Returns: 0 on command success. - * non-zero on failure (card will need reset) - */ -static int -rln_tx_end(sc) - struct rln_softc * sc; -{ - /* EndOfTx() */ - int i; - int s; - u_int8_t status; - - dprintf(" Te["); - s = spl0(); - for (i = 0; i < 600; i++) { - status = rln_status_tx_read(sc); - if (status == RLN_STATUS_TX_XFR_COMPLETE) - break; - DELAY(1000); - } - splx(s); - if (status == RLN_STATUS_TX_XFR_COMPLETE) { - rln_status_tx_write(sc, RLN_STATUS_TX_IDLE); - dprintf("]=0"); - return (0); - } else { - printf("%s: tx cmd failed (%02x)\n", sc->sc_dev.dv_xname, - status); - rln_need_reset(sc); - dprintf("]=-1"); - return (-1); - } -} - -/* - * Performs first (request) stage of receiving a message from the card. - * Returns: 0 on failure, - * n>0 on success, where 'n' is the length of the message - */ - -int -rln_rx_request(sc, timeo) - struct rln_softc * sc; - int timeo; /* milliseconds */ -{ - /* RxRequest */ - int s; - int len = 0; - int i; - u_int8_t status; - u_int8_t hi, lo; - - dprintf(" Rr["); - status = rln_status_rx_read(sc); - - /* Short wait for states 1|5|6. */ - s = spl0(); - for (i = 0; i < timeo; i++) { - if (status == RLN_STATUS_RX_LOLEN_AVAIL || - status == RLN_STATUS_RX_HILEN_AVAIL || - status == RLN_STATUS_RX_ERROR) - break; - DELAY(1000); - status = rln_status_rx_read(sc); - } - splx(s); - dprintf(" (%dms)",i); - - if (sc->sc_width == 16) { - if (status != RLN_STATUS_RX_HILEN_AVAIL) - goto badstatus_quiet; - /* Read 2 octets. */ - len = rln_data_read_2(sc); - } else if (sc->sc_width == 8) { - if (status != RLN_STATUS_RX_LOLEN_AVAIL) - goto badstatus_quiet; - /* Read low octet. */ - lo = rln_data_read_1(sc); - rln_status_rx_write(sc, RLN_STATUS_RX_LOLEN_ACCEPT); - rln_status_rx_int(sc); - s = spl0(); - for (i = 0; i < 600; i++) { - status = rln_status_rx_read(sc); - if (status == RLN_STATUS_RX_HILEN_AVAIL) - break; - DELAY(1000); - } - splx(s); - if (status != RLN_STATUS_RX_HILEN_AVAIL) - goto badstatus; - /* Read high octet. */ - hi = rln_data_read_1(sc); - len = lo | (hi << 8); - } -#ifdef DIAGNOSTIC - else - panic("rln: bus width %d", sc->sc_width); -#endif - - dprintf(" len=%d]", len); - return (len); - -badstatus: - printf("%s: rx_request timed out, status %02x\n", - sc->sc_dev.dv_xname, status); -badstatus_quiet: - if (status == RLN_STATUS_RX_ERROR) - printf("%s: rx protocol error (nak)\n", sc->sc_dev.dv_xname); - dprintf("]"); - return (-1); -} - -/* Performs part of the second (transfer) stage of receiving a data message. */ -void -rln_rx_pdata(sc, buf, len, pd) - struct rln_softc * sc; - void * buf; - int len; - struct rln_pdata * pd; -{ - char * data = (char *)buf; - - if (pd->p_nremain) { - *data++ = pd->p_data; - if (--len == 0) - return; - } - - pd->p_nremain = 0; - - if (sc->sc_width == 16) { - /* Round down to the closest even multiple. */ - rln_data_read_multi_2(sc, data, len / 2); -#ifdef RLNDEBUG_REG - dprintf(" D>"); - dprinthex(data, len); -#endif - if (len & 1) { - /* Read the last octet plus a bit extra. */ - union { - u_int16_t w; - u_int8_t b[2]; - } u; - - u.w = rln_data_read_2(sc); - data[len - 1] = u.b[0]; - pd->p_data = u.b[1]; - pd->p_nremain = 1; -#ifdef RLNDEBUG_REG - dprintf(" D>{%02x%02x}", u.b[0], u.b[1]); -#endif - } - } else if (sc->sc_width == 8) { - rln_data_read_multi_1(sc, data, len); -#ifdef RLNDEBUG_REG - dprintf(" D>"); - dprinthex(data, len); -#endif - if (len & 1) { - /* Must read multiples of two. */ - pd->p_data = rln_data_read_1(sc); - pd->p_nremain = 1; -#ifdef RLNDEBUG_REG - dprintf(" D>{%02x}", pd->p_data); -#endif - } - } - -} - -int -rln_rx_data(sc, buf, len) - struct rln_softc * sc; - void * buf; - int len; -{ - /* RxData() */ - struct rln_pdata pd = { 0, 0 }; - int s; - int i; - u_int8_t status; - - dprintf(" Rd["); - rln_status_rx_write(sc, RLN_STATUS_RX_HILEN_ACCEPT); - rln_status_rx_int(sc); - s = spl0(); - for (i = 0; i < 600; i++) { - status = rln_status_rx_read(sc); - if (status == RLN_STATUS_RX_XFR) - break; - DELAY(1000); - } - splx(s); - if (status != RLN_STATUS_RX_XFR) { - dprintf("]=-1"); - return (-1); - } - - rln_rx_pdata(sc, buf, len, &pd); -#ifdef DIAGNOSTIC - /* We should have nothing left over. */ - if (pd.p_nremain || len & 1) - panic("rln_rx_data: leftover"); -#endif - - dprintf("]=0"); - return (0); -} - -void -rln_rx_end(sc) - struct rln_softc * sc; -{ - /* EndOfRx() */ - - dprintf(" Re["); - rln_status_rx_write(sc, RLN_STATUS_RX_XFR_COMPLETE); - rln_status_rx_int(sc); - /* rln_wakeup(sc, 0); */ - dprintf("]"); -} - -/* Clear a transmission NAK from the card. */ -void -rln_clear_nak(sc) - struct rln_softc * sc; -{ - /* ClearNAK() */ - - rln_status_tx_write(sc, RLN_STATUS_CLRNAK); - rln_status_tx_int(sc); -} - -/* - * Send a command message to the card. Returns; - * 2: NAK - * -1: failure - * 0: success - */ -int -rln_msg_tx_start(sc, buf, pktlen, state) - struct rln_softc * sc; - void * buf; - int pktlen; - struct rln_msg_tx_state * state; -{ - struct rln_mm_cmd * cmd = (struct rln_mm_cmd *)buf; - int ret; - - state->ien = rln_enable(sc, 0); - state->pd.p_nremain = 0; - - if (!(cmd->cmd_letter == 'A' && cmd->cmd_fn == 6)) /* Standby. */ - state->w = rln_wakeup(sc, RLN_WAKEUP_SET); - else - state->w = RLN_WAKEUP_NOCHANGE; - - ret = rln_tx_request(sc, pktlen); - if (ret == 2) { - rln_clear_nak(sc); - if (sc->sc_cardtype & RLN_CTYPE_OEM) - rln_need_reset(sc); - ret = 2; - } - else if (ret == 1) { - /* Timeout. */ - rln_status_tx_write(sc, RLN_STATUS_TX_XFR); - ret = -1; - } - return (ret); -} - -void -rln_msg_tx_data(sc, buf, len, state) - struct rln_softc * sc; - void * buf; - u_int16_t len; - struct rln_msg_tx_state * state; -{ - char * data = (char *)buf; - - if (sc->sc_width == 16 && state->pd.p_nremain) { - /* XXX htons() needed? */ - union { - u_int8_t b[2]; - u_int16_t w; - } u; - - u.b[0] = state->pd.p_data; - if (len) { - u.b[1] = *data++; - len--; - } else - u.b[1] = '\0'; -#ifdef RLNDEBUG_REG - dprintf(" D<%02x%02x", u.b[0], u.b[1]); -#endif - rln_data_write_2(sc, u.w); - state->pd.p_nremain = 0; - } - - if (len) { - if (sc->sc_width == 16) { - if (len >= 2) - rln_data_write_multi_2(sc, buf, len / 2); - if (len & 1) { - state->pd.p_nremain = 1; - state->pd.p_data = data[len - 1]; - } - } else if (sc->sc_width == 8) - rln_data_write_multi_1(sc, buf, len); -#ifdef DIAGNOSTIC - else - panic("rln_msg_tx_data width %d", sc->sc_width); -#endif -#ifdef RLNDEBUG_REG - dprintf(" D<"); - dprinthex(data, len); -#endif - } -} - - -int -rln_msg_tx_end(sc, state) - struct rln_softc * sc; - struct rln_msg_tx_state * state; -{ - int ret; - - /* Flush the tx buffer. */ - if (state->pd.p_nremain) - rln_msg_tx_data(sc, NULL, 0, state); - -#ifdef DIAGNOSTIC - if (state->pd.p_nremain) - panic("rln_msg_tx_end remain %d", state->pd.p_nremain); -#endif - ret = rln_tx_end(sc); - if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE) - state->w = RLN_WAKEUP_NOCHANGE; - rln_wakeup(sc, state->w); - rln_enable(sc, state->ien); - return (ret); -} - -/* Return the next unique sequence number to use for a transmitted command */ -u_int8_t -rln_newseq(sc) - struct rln_softc * sc; -{ - int s; - u_int8_t seq; - - s = splhigh(); - seq = sc->sc_pktseq++; - if (sc->sc_pktseq > RLN_MAXSEQ) - sc->sc_pktseq = 0; - splx(s); - return (seq); -} - -/* - * Transmit a command message to, and (optionally) receive a response - * message from the card. Each transmitted message has a sequence - * number, and corresponding reply messages have the same sequence - * number. We use the sequence numbers to index the mailboxes so - * that rlnsoftintr() can signal this routine when it has serviced - * and correctly received a response. - */ - -int -rln_msg_txrx(sc, tx, txlen, rx, rxlen) - struct rln_softc * sc; - void * tx; - int txlen; - void * rx; - int rxlen; -{ - struct rln_mm_cmd * txc = (struct rln_mm_cmd *)tx; - struct rln_mm_cmd * rxc = (struct rln_mm_cmd *)rx; - struct rln_msg_tx_state state; - int ien; - int ret; - -#ifdef DIAGNOSTIC - if (rx != NULL && rxlen < sizeof *rxc) - panic("rln_msg_txrx"); -#endif - - txc->cmd_seq = rln_newseq(sc); - -#ifdef RLNDUMP - printf("%s: send %c%d seq %d data ", sc->sc_dev.dv_xname, - txc->cmd_letter, txc->cmd_fn, txc->cmd_seq); - RLNDUMPHEX(txc, sizeof *txc); - printf(":"); - RLNDUMPHEX((char *)tx + sizeof *txc, txlen - sizeof *txc); - printf("\n"); -#endif - - if (rx != NULL) - if (rln_mbox_create(sc, txc->cmd_seq, rx, rxlen) < 0) - /* Mailbox collision. */ - return (-1); - - /* Start the transfer. */ - if ((ret = rln_msg_tx_start(sc, tx, txlen, &state))) { - if (rx != NULL) - rln_mbox_wait(sc, txc->cmd_seq, -1); - return (ret); - } - - /* Always send an even number of octets. */ - rln_msg_tx_data(sc, tx, (txlen + 1) & ~1, &state); - - /* End the transmission. */ - if ((ret = rln_msg_tx_end(sc, &state))) { - /* Destroy mailbox. */ - if (rx != NULL) - rln_mbox_wait(sc, txc->cmd_seq, -1); - return (ret); - } - - /* Don't wait for reply if there is nowhere to put it. */ - if (rx == NULL) - return (0); - - /* Enable interrupts if not already. */ - ien = rln_enable(sc, 1); - - /* Wait for the reply message. */ - if (rln_mbox_wait(sc, txc->cmd_seq, 4000) <= 0) { - printf("%s: lost message %c%d seq %d\n", sc->sc_dev.dv_xname, - txc->cmd_letter, txc->cmd_fn, txc->cmd_seq); - rln_enable(sc, ien); - return (-1); - } - rln_enable(sc, ien); - -#ifdef RLNDUMP - printf("%s: recv %c%d seq %d data ", sc->sc_dev.dv_xname, - rxc->cmd_letter, rxc->cmd_fn, rxc->cmd_seq); - RLNDUMPHEX(rxc, sizeof *rxc); - printf(":"); - RLNDUMPHEX(((char *)rx) + sizeof *rxc, rxlen - sizeof *rxc); - printf("\n"); -#endif - - /* Check for errors in the received message. */ - if (rxc->cmd_error & 0x80) { - printf("%s: command error 0x%02x command %c%d\n", - sc->sc_dev.dv_xname, - rxc->cmd_error & ~0x80, - rxc->cmd_letter, rxc->cmd_fn); - return (-1); - } - - return (0); -} - -/* - * Mailboxes provide a simple way to tell the interrupt - * service routine that someone is expecting a reply message. - * Mailboxes are identified by the message sequence number - * and also hold a pointer to storage supplied by the waiter. - * The interrupt service routine signals the mailbox when it - * gets the reply message. - */ - -/* Create a mailbox for filling. */ -int -rln_mbox_create(sc, seq, buf, len) - struct rln_softc * sc; - u_int8_t seq; - void * buf; - size_t len; -{ - int s; - struct rln_mbox * mb = &sc->sc_mbox[seq]; - - dprintf(" <create %d", seq); - -#ifdef DIAGNOSTIC - if (seq > RLN_NMBOX) - panic("mbox create"); -#endif - - s = splhigh(); - if (mb->mb_state != RLNMBOX_VOID) { -#ifdef DIAGNOSTIC - printf("mbox collision"); -#endif - splx(s); - return (-1); - } - mb->mb_buf = buf; - mb->mb_len = len; - mb->mb_actlen = 0; - mb->mb_state = RLNMBOX_EMPTY; - dprintf(" empty>"); - splx(s); - return (0); -} - - -/* Wait for a mailbox to be filled. */ -int -rln_mbox_wait(sc, seq, timeo) - struct rln_softc * sc; - u_int8_t seq; - int timeo; -{ - int i; - int s; - int ret; - volatile struct rln_mbox * mb = &sc->sc_mbox[seq]; - - dprintf(" <wait %d", seq); - -#ifdef DIAGNOSTIC - if (seq > RLN_NMBOX) - panic("mbox wait"); -#endif - -#if defined(RLN_TSLEEP) - if (!cold) { - tsleep((void *)mb, PRIBIO, "rlnmbox", hz * timeo / 1000); - if (mb->mb_state == RLNMBOX_FILLING) { - /* Must wait until filled. */ - s = spl0(); - while (mb->mb_state == RLNMBOX_FILLING) - ; - splx(s); - } - } else { - /* Autoconfiguration - spin at spl0. */ -#endif - s = spl0(); - i = 0; - while (mb->mb_state == RLNMBOX_EMPTY && i < timeo) { - DELAY(1000); - i++; - } - if (i) - dprintf(" %dms", i); - while (mb->mb_state == RLNMBOX_FILLING) - ; - splx(s); -#if defined(RLN_TSLEEP) - } -#endif - - s = splhigh(); - -#ifdef DIAGNOSTIC - if (mb->mb_state != RLNMBOX_EMPTY && mb->mb_state != RLNMBOX_FILLED) - panic("mbox wait %d", mb->mb_state); -#endif - ret = mb->mb_actlen; - mb->mb_state = RLNMBOX_VOID; - dprintf(" void>=%d", ret); - splx(s); - return (ret); -} - -/* Lock a mailbox for filling. */ -int -rln_mbox_lock(sc, seq, bufp, lenp) - struct rln_softc * sc; - u_int8_t seq; - void ** bufp; - size_t * lenp; -{ - int s; - struct rln_mbox * mb = &sc->sc_mbox[seq]; - - dprintf(" <lock %d", seq); - - s = splhigh(); -#ifdef DIAGNOSTIC - if (seq > RLN_NMBOX) - panic("mbox lock"); -#endif - if (mb->mb_state != RLNMBOX_EMPTY) { - splx(s); - dprintf(" ?>"); - return (-1); - } - - mb->mb_state = RLNMBOX_FILLING; - dprintf(" filling>"); - *bufp = mb->mb_buf; - *lenp = mb->mb_len; - - splx(s); - return (0); -} - -/* Unlock a mailbox and inform the waiter of the actual number of octets. */ -void -rln_mbox_unlock(sc, seq, actlen) - struct rln_softc * sc; - u_int8_t seq; - size_t actlen; -{ - int s; - struct rln_mbox * mb = &sc->sc_mbox[seq]; - - dprintf(" <unlock %d", seq); - - s = splhigh(); -#ifdef DIAGNOSTIC - if (seq > RLN_NMBOX) - panic("mbox unlock seq"); - if (mb->mb_state != RLNMBOX_FILLING) - panic("mbox unlock"); -#endif - mb->mb_state = RLNMBOX_FILLED; - dprintf(" filled>"); - mb->mb_actlen = actlen; -#if defined(RLN_TSLEEP) - wakeup(mb); -#endif - splx(s); -} - |