eh = *(mtod(m, struct ether_header *));
2
eh.ether_type = ntohs((unsigned short)eh.ether_type);
3
m->= sizeof(struct ether_header);
4
ADD_RECV_PACKET(ifp, sc, m->m_pkthdr.len);
5
if (eh.ether_dhost[0] & 0x1) {
ADD_RECV_MPACKET(ifp, sc, m->m_pkthdr.len);
}
i = READ_RXS(sc);
6
if (i &= 0x7ff) {
if ((i & 0x400) == 0) {
m_freem(m);
goto scrap;
}
}
ether_input(ifp, &eh, m);
7
}
}
1
Calls the
io_blockread( )
routine to perform the data transfer from
the FIFO buffer on the adapter to the
mbuf
in host memory.
2
Makes a copy of the
ether_header
data structure for the
ether_input( )
routine.
3
Converts the 2-byte
ether_type
field from network byte order to host
byte order and saves it in the
ether_header
data structure.
4
Adjusts the pointer to the received data to point past the MAC header
(skips past the destination address, source address, and
ether_type
fields).
5
Calls the
ADD_RECV_PACKET
macro to increment the receive packet
(block) count. If this packet was destined for a broadcast or multicast
address, calls the
ADD_RECV_MPACKET
macro to increment those
statistics as well.
6
Calls the
READ_RXS
macro to read the receive status. If the packet just
received was not fully received, scraps the packet.
7
Calls the
ether_input( )
routine to process the received Ethernet
packet. The packet is in the
mbuf
chain without the
ether_header
data structure, which is provided separately.
13.2.5 Discarding a Packet
The following code shows how the
el_rint( )
routine discards a packet.
Some receive
interrupt
handlers perform a copy of a few bytes of the
packet to determine if the packet is actually destined for the device. Thus,
this task is an optional optimization.
scrap:
WRITE_CMD(sc, CMD_RXDTP);
1
status = READ_RXS(sc);
}
Implementing the Interrupt Section 13–9