Exemplo n.º 1
0
/* Send packet */
void mc9328mxl_enet_sendpacket (struct ifnet *ifp, struct mbuf *m)
{
    struct mbuf *l = NULL;
    int size = 0;
    int tmp;
    int i;
    int start;
    uint16_t d;

    /* How big is the packet ? */
    l = m;
    do {
        size += l->m_len;
        l = l->m_next;
    } while (l != NULL);

    /* Allocate a TX buffer */
    lan91c11x_write_reg(LAN91C11X_MMUCMD,
                        (LAN91C11X_MMUCMD_ALLOCTX |
                         (size >> 8)));

    /* Wait for the allocation */
    while ((lan91c11x_read_reg(LAN91C11X_INT) & LAN91C11X_INT_ALLOC) == 0) {
        continue;
    }

    tmp = lan91c11x_read_reg(LAN91C11X_PNR);
    lan91c11x_write_reg(LAN91C11X_PNR, ((tmp >> 8) & 0xff));

    /* Set the data pointer for auto increment */
    lan91c11x_write_reg(LAN91C11X_PTR, LAN91C11X_PTR_AUTOINC);

    /* A delay is needed between pointer and data access ?!? */
    for (i = 0; i < 10; i++) {
        continue;
    }

    /* Write status word */
    lan91c11x_write_reg(LAN91C11X_DATA, 0);

    /* Write byte count */
    if (size & 1) {
        size++;
    }
    lan91c11x_write_reg(LAN91C11X_DATA, size + 6);

    lan91c11x_lock();

    /* Copy the mbuf */
    l = m;
    start = 0;
    d = 0;
    while (l != NULL)
    {
        uint8_t *data;

        data = mtod(l, uint8_t *);

        for (i = start; i < l->m_len; i++) {
            if ((i & 1) == 0) {
                d = data[i] << 8;
            } else {
                d = d | data[i];
                lan91c11x_write_reg_fast(LAN91C11X_DATA, htons(d));
            }
        }

        /* If everything is 2 byte aligned, i will be even */
        start = (i & 1);

        l = l->m_next;
    }

    /* write control byte */
    if (i & 1) {
        lan91c11x_write_reg_fast(LAN91C11X_DATA,
                            htons(LAN91C11X_PKT_CTRL_ODD | d));
    } else {
        lan91c11x_write_reg_fast(LAN91C11X_DATA, 0);
    }

    lan91c11x_unlock();

    /* Enable TX interrupts */
    lan91c11x_write_reg(LAN91C11X_INT,
                        (lan91c11x_read_reg(LAN91C11X_INT) |
                         LAN91C11X_INT_TXMASK |
                         LAN91C11X_INT_TXEMASK));

    /* Enqueue it */
    lan91c11x_write_reg(LAN91C11X_MMUCMD,
                        LAN91C11X_MMUCMD_ENQUEUE);

    /* free the mbuf chain we just copied */
    m_freem(m);

} /* mc9328mxl_enet_sendpacket () */
Exemplo n.º 2
0
/* reader task */
void mc9328mxl_enet_rx_task(void *arg)
{
    mc9328mxl_enet_softc_t *sc = (mc9328mxl_enet_softc_t *)arg;
    struct ifnet *ifp = &sc->arpcom.ac_if;
    struct mbuf *m;
    struct ether_header *eh;
    rtems_event_set events;
    int pktlen;
    uint16_t rsw;
    uint16_t bc;
    uint16_t cbyte;
    int i;
    uint16_t int_reg;

    /* Input packet handling loop */
    while (1) {
        rtems_bsdnet_event_receive(
            START_RECEIVE_EVENT,
            RTEMS_EVENT_ANY | RTEMS_WAIT,
            RTEMS_NO_TIMEOUT,
            &events);

        /* Configure for reads from RX data area */
        lan91c11x_write_reg(LAN91C11X_PTR,
                            (LAN91C11X_PTR_AUTOINC |
                             LAN91C11X_PTR_RCV |
                             LAN91C11X_PTR_READ));

        /* read the receive status word */
        rsw = lan91c11x_read_reg(LAN91C11X_DATA);
        /* TBD: Need to check rsw here */

        /* read the byte count */
        bc = lan91c11x_read_reg(LAN91C11X_DATA);
        pktlen = (bc & 0x7ff) - 6;

        /* get an mbuf for this packet */
        MGETHDR(m, M_WAIT, MT_DATA);

        /* now get a cluster pointed to by the mbuf */
        /* since an mbuf by itself is too small */
        MCLGET(m, M_WAIT);

        lan91c11x_lock();

        /* Copy the received packet into an mbuf */
        for (i = 0; i < (pktlen / 2); i++) {
            ((uint16_t*)m->m_ext.ext_buf)[i] =
                lan91c11x_read_reg_fast(LAN91C11X_DATA);
        }

        cbyte = lan91c11x_read_reg_fast(LAN91C11X_DATA);
        if (cbyte & LAN91C11X_PKT_CTRL_ODD) {
            ((uint16_t*)m->m_ext.ext_buf)[i] = cbyte;
            pktlen++;
        }
        lan91c11x_unlock();

        /* Release the packets memory */
        lan91c11x_write_reg(LAN91C11X_MMUCMD,
                            LAN91C11X_MMUCMD_REMTOP);

        /* set the receiving interface */
        m->m_pkthdr.rcvif = ifp;
        m->m_nextpkt = 0;

        /* set the length of the mbuf */
        m->m_len = pktlen - (sizeof(struct ether_header));
        m->m_pkthdr.len = m->m_len;

        /* strip off the ethernet header from the mbuf */
        /* but save the pointer to it */
        eh = mtod (m, struct ether_header *);
        m->m_data += sizeof(struct ether_header);


        softc.stats.rx_packets++;

        /* give all this stuff to the stack */
        ether_input(ifp, eh, m);

        /* renable RX interrupts */
        int_reg = lan91c11x_read_reg(LAN91C11X_INT);
        int_reg |= LAN91C11X_INT_RXMASK;
        lan91c11x_write_reg(LAN91C11X_INT, int_reg);

    }
} /* mc9328mxl_enet_rx_task */