Hardware Checksum support on NetBSD-current

ハードウェアで補助されたチェックサム計算
FreeBSDのmanを読んだらこんなん乗ってたので、NetBSDではどうよ?と思ったら、3.0のアナウンスに
gem(4) and hme(4) now have hardware checksum support.
とか書いてあった。
manのどこに書いてあるのかは良く分からんけど。

で、gem(4)のコードを読んでみたら、
gem_attach()に

	/*
	 * The GEM hardware supports basic TCP checksum offloading only.
	 * Several (all?) revisions (Sun rev. 01 and Apple rev. 00 and 80)
	 * have bugs in the receive checksum, so don't enable it for now.
	if ((GEM_IS_SUN(sc) && sc->sc_chiprev != 1) ||
	    (GEM_IS_APPLE(sc) &&
	    (sc->sc_chiprev != 0 && sc->sc_chiprev != 0x80)))
		ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Rx;
	*/
	ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Tx;

gem_start()に

#ifdef INET
				/* h/w checksum */
				if (ifp->if_csum_flags_tx & M_CSUM_TCPv4 &&
				    m0->m_pkthdr.csum_flags & M_CSUM_TCPv4) {
					struct ether_header *eh;
					uint16_t offset, start;

					eh = mtod(m0, struct ether_header *);
					switch (ntohs(eh->ether_type)) {
					case ETHERTYPE_IP:
						start = ETHER_HDR_LEN;
						break;
					case ETHERTYPE_VLAN:
						start = ETHER_HDR_LEN +
							ETHER_VLAN_ENCAP_LEN;
						break;
					default:
						/* unsupported, drop it */
						m_free(m0);
						continue;
					}
					start += M_CSUM_DATA_IPv4_IPHL(m0->m_pkthdr.csum_data);
					offset = M_CSUM_DATA_IPv4_OFFSET(m0->m_pkthdr.csum_data) + start;
					flags |= (start <<
						  GEM_TD_CXSUM_STARTSHFT) |
						 (offset <<
						  GEM_TD_CXSUM_STUFFSHFT) |
						 GEM_TD_CXSUM_ENABLE;
				}
#endif

gem_rint()に

#ifdef INET
		/* hardware checksum */
		if (ifp->if_csum_flags_rx & M_CSUM_TCPv4) {
			struct ether_header *eh;
			struct ip *ip;
			int32_t hlen, pktlen;

			if (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) {
				pktlen = m->m_pkthdr.len - ETHER_HDR_LEN -
					 ETHER_VLAN_ENCAP_LEN;
				eh = (struct ether_header *) (mtod(m, char *) +
					ETHER_VLAN_ENCAP_LEN);
			} else {
				pktlen = m->m_pkthdr.len - ETHER_HDR_LEN;
				eh = mtod(m, struct ether_header *);
			}
			if (ntohs(eh->ether_type) != ETHERTYPE_IP)
				goto swcsum;
			ip = (struct ip *) ((char *)eh + ETHER_HDR_LEN);

			/* IPv4 only */
			if (ip->ip_v != IPVERSION)
				goto swcsum;

			hlen = ip->ip_hl << 2;
			if (hlen < sizeof(struct ip))
				goto swcsum;

			/*
			 * bail if too short, has random trailing garbage,
			 * truncated, fragment, or has ethernet pad.
			 */
			if ((ntohs(ip->ip_len) < hlen) ||
			    (ntohs(ip->ip_len) != pktlen) ||
			    (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK)))
				goto swcsum;

			switch (ip->ip_p) {
			case IPPROTO_TCP:
				if (! (ifp->if_csum_flags_rx & M_CSUM_TCPv4))
					goto swcsum;
				if (pktlen < (hlen + sizeof(struct tcphdr)))
					goto swcsum;
				m->m_pkthdr.csum_flags = M_CSUM_TCPv4;
				break;
			case IPPROTO_UDP:
				/* FALLTHROUGH */
			default:
				goto swcsum;
			}

			/* the uncomplemented sum is expected */
			m->m_pkthdr.csum_data = (~rxstat) & GEM_RD_CHECKSUM;

			/* if the pkt had ip options, we have to deduct them */
			if (hlen > sizeof(struct ip)) {
				uint16_t *opts;
				uint32_t optsum, temp;

				optsum = 0;
				temp = hlen - sizeof(struct ip);
				opts = (uint16_t *) ((char *) ip +
					sizeof(struct ip));

				while (temp > 1) {
					optsum += ntohs(*opts++);
					temp -= 2;
				}
				while (optsum >> 16)
					optsum = (optsum >> 16) +
						 (optsum & 0xffff);

				/* Deduct ip opts sum from hwsum (rfc 1624). */
				m->m_pkthdr.csum_data =
					~((~m->m_pkthdr.csum_data) - ~optsum);

				while (m->m_pkthdr.csum_data >> 16)
					m->m_pkthdr.csum_data =
						(m->m_pkthdr.csum_data >> 16) +
						(m->m_pkthdr.csum_data &
						 0xffff);
			}

			m->m_pkthdr.csum_flags |= M_CSUM_DATA |
						  M_CSUM_NO_PSEUDOHDR;
		} else
swcsum:
			m->m_pkthdr.csum_flags = 0;
#endif

とかいうよーなコードが入ってた。
多分これを真似すれば他のデバイスでも同じ事ができるであらう。

re(4) and wm(4) now support TCPv4 hardware transmit segment offload.
というのもどうなっているのかちょっと気になる。

#というあたりはどこを見れば書いてあるですか???
manでifnetとかやったら何もないし、ぐぐってもみあたんないし・・・