/* 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 () */
/* 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 */