diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index c72caf0199c9..b8e63315cb95 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -1,1049 +1,1056 @@
 #	@(#)Makefile	8.1 (Berkeley) 6/18/93
 # $FreeBSD$
 
 .include <src.opts.mk>
 
 MAN=	aac.4 \
 	aacraid.4 \
 	acpi.4 \
 	${_acpi_asus.4} \
 	${_acpi_asus_wmi.4} \
 	${_acpi_dock.4} \
 	${_acpi_fujitsu.4} \
 	${_acpi_hp.4} \
 	${_acpi_ibm.4} \
 	${_acpi_panasonic.4} \
 	${_acpi_rapidstart.4} \
 	${_acpi_sony.4} \
 	acpi_thermal.4 \
 	acpi_battery.4 \
 	${_acpi_toshiba.4} \
 	acpi_video.4 \
 	${_acpi_wmi.4} \
 	ada.4 \
 	adm6996fc.4 \
 	ads111x.4 \
 	ae.4 \
 	${_aesni.4} \
 	age.4 \
 	agp.4 \
 	ahc.4 \
 	ahci.4 \
 	ahd.4 \
 	${_aibs.4} \
 	aio.4 \
 	alc.4 \
 	ale.4 \
 	alpm.4 \
 	altera_atse.4 \
 	altera_avgen.4 \
 	altera_jtag_uart.4 \
 	altera_sdcard.4 \
 	altq.4 \
 	amdpm.4 \
 	${_amdsbwd.4} \
 	${_amdsmb.4} \
 	${_amdsmn.4} \
 	${_amdtemp.4} \
 	${_bxe.4} \
 	amr.4 \
 	an.4 \
 	${_aout.4} \
 	${_apic.4} \
 	arcmsr.4 \
 	${_asmc.4} \
 	at45d.4 \
 	ata.4 \
 	ath.4 \
 	ath_ahb.4 \
 	ath_hal.4 \
 	ath_pci.4 \
 	atkbd.4 \
 	atkbdc.4 \
 	atp.4 \
 	${_atf_test_case.4} \
 	${_atrtc.4} \
 	${_attimer.4} \
 	audit.4 \
 	auditpipe.4 \
 	aue.4 \
 	axe.4 \
 	axge.4 \
 	bce.4 \
 	bcma.4 \
 	bfe.4 \
 	bge.4 \
 	${_bhyve.4} \
 	bhnd.4 \
 	bhnd_chipc.4 \
 	bhnd_pmu.4 \
 	bhndb.4 \
 	bhndb_pci.4 \
 	blackhole.4 \
 	bnxt.4 \
 	bpf.4 \
 	bridge.4 \
 	bt.4 \
 	bwi.4 \
 	bwn.4 \
 	${_bytgpio.4} \
 	capsicum.4 \
 	cardbus.4 \
 	carp.4 \
 	cas.4 \
 	cc_cdg.4 \
 	cc_chd.4 \
 	cc_cubic.4 \
 	cc_dctcp.4 \
 	cc_hd.4 \
 	cc_htcp.4 \
 	cc_newreno.4 \
 	cc_vegas.4 \
 	${_ccd.4} \
 	ccr.4 \
 	cd.4 \
 	cdce.4 \
 	cdceem.4 \
 	cfi.4 \
 	cfumass.4 \
+	${_cgem.4} \
 	ch.4 \
 	chromebook_platform.4 \
 	${_chvgpio.4} \
 	ciss.4 \
 	cloudabi.4 \
 	${_coretemp.4} \
 	cp2112.4 \
 	${_cpuctl.4} \
 	cpufreq.4 \
 	crypto.4 \
 	ctl.4 \
 	cue.4 \
 	cxgb.4 \
 	cxgbe.4 \
 	cxgbev.4 \
 	cyapa.4 \
 	da.4 \
 	dc.4 \
 	dcons.4 \
 	dcons_crom.4 \
 	ddb.4 \
 	devctl.4 \
 	disc.4 \
 	disk.4 \
 	divert.4 \
 	${_dpms.4} \
 	ds1307.4 \
 	ds3231.4 \
 	${_dtrace_provs} \
 	dummynet.4 \
 	edsc.4 \
 	ehci.4 \
 	em.4 \
 	ena.4 \
 	enc.4 \
 	epair.4 \
 	esp.4 \
 	est.4 \
 	et.4 \
 	etherswitch.4 \
 	eventtimers.4 \
 	exca.4 \
 	e6060sw.4 \
 	fd.4 \
 	fdc.4 \
 	fdt.4 \
 	fdt_pinctrl.4 \
 	fdtbus.4 \
 	ffclock.4 \
 	filemon.4 \
 	firewire.4 \
 	${_ftwd.4} \
 	full.4 \
 	fwe.4 \
 	fwip.4 \
 	fwohci.4 \
 	fxp.4 \
 	gbde.4 \
 	gdb.4 \
 	gem.4 \
 	geom.4 \
 	geom_linux_lvm.4 \
 	geom_map.4 \
 	geom_uzip.4 \
 	gif.4 \
 	gpio.4 \
 	gpioiic.4 \
 	gpiokeys.4 \
 	gpioled.4 \
 	gpioths.4 \
 	gre.4 \
 	h_ertt.4 \
 	hconf.4 \
 	hcons.4 \
 	hgame.4 \
 	hidbus.4 \
 	hidquirk.4 \
 	hidraw.4 \
 	hifn.4 \
 	hkbd.4 \
 	hms.4 \
 	hmt.4 \
 	hpen.4 \
 	hpet.4 \
 	${_hpt27xx.4} \
 	${_hptiop.4} \
 	${_hptmv.4} \
 	${_hptnr.4} \
 	${_hptrr.4} \
 	hsctrl.4 \
 	${_hv_kvp.4} \
 	${_hv_netvsc.4} \
 	${_hv_storvsc.4} \
 	${_hv_utils.4} \
 	${_hv_vmbus.4} \
 	${_hv_vss.4} \
 	hwpmc.4 \
 	${_hwpstate_intel.4} \
 	iavf.4 \
 	ichsmb.4 \
 	${_ichwd.4} \
 	icmp.4 \
 	icmp6.4 \
 	ida.4 \
 	if_ipsec.4 \
 	iflib.4 \
 	ifmib.4 \
 	ig4.4 \
 	igmp.4 \
 	iic.4 \
 	iic_gpiomux.4 \
 	iicbb.4 \
 	iicbus.4 \
 	iichid.4 \
 	iicmux.4 \
 	iicsmb.4 \
 	iir.4 \
 	${_imcsmb.4} \
 	inet.4 \
 	inet6.4 \
 	intpm.4 \
 	intro.4 \
 	${_io.4} \
 	${_ioat.4} \
 	ip.4 \
 	ip6.4 \
 	ipfirewall.4 \
 	ipheth.4 \
 	${_ipmi.4} \
 	ips.4 \
 	ipsec.4 \
 	ipw.4 \
 	ipwfw.4 \
 	isci.4 \
 	isl.4 \
 	ismt.4 \
 	isp.4 \
 	ispfw.4 \
 	${_itwd.4} \
 	iwi.4 \
 	iwifw.4 \
 	iwm.4 \
 	iwmfw.4 \
 	iwn.4 \
 	iwnfw.4 \
 	ixgbe.4 \
 	ixl.4 \
 	jedec_dimm.4 \
 	jme.4 \
 	kbdmux.4 \
 	kcov.4 \
 	keyboard.4 \
 	kld.4 \
 	ksyms.4 \
 	ksz8995ma.4 \
 	ktls.4 \
 	ktr.4 \
 	kue.4 \
 	lagg.4 \
 	le.4 \
 	led.4 \
 	lge.4 \
 	${_linux.4} \
 	liquidio.4 \
 	lm75.4 \
 	lo.4 \
 	lp.4 \
 	lpbb.4 \
 	lpt.4 \
 	ltc430x.4 \
 	mac.4 \
 	mac_biba.4 \
 	mac_bsdextended.4 \
 	mac_ifoff.4 \
 	mac_lomac.4 \
 	mac_mls.4 \
 	mac_none.4 \
 	mac_ntpd.4 \
 	mac_partition.4 \
 	mac_portacl.4 \
 	mac_seeotheruids.4 \
 	mac_stub.4 \
 	mac_test.4 \
 	malo.4 \
 	md.4 \
 	mdio.4 \
 	me.4 \
 	mem.4 \
 	meteor.4 \
 	mfi.4 \
 	miibus.4 \
 	mld.4 \
 	mlx.4 \
 	mlx4en.4 \
 	mlx5en.4 \
 	mly.4 \
 	mmc.4 \
 	mmcsd.4 \
 	mn.4 \
 	mod_cc.4 \
 	mos.4 \
 	mouse.4 \
 	mpr.4 \
 	mps.4 \
 	mpt.4 \
 	mrsas.4 \
 	msk.4 \
 	mtio.4 \
 	multicast.4 \
 	muge.4 \
 	mvs.4 \
 	mwl.4 \
 	mwlfw.4 \
 	mx25l.4 \
 	mxge.4 \
 	my.4 \
 	${_ndis.4} \
 	net80211.4 \
 	netdump.4 \
 	netfpga10g_nf10bmac.4 \
 	netgdb.4 \
 	netgraph.4 \
 	netintro.4 \
 	netmap.4 \
 	${_nfe.4} \
 	${_nfsmb.4} \
 	ng_async.4 \
 	ngatmbase.4 \
 	ng_atmllc.4 \
 	ng_bpf.4 \
 	ng_bridge.4 \
 	ng_btsocket.4 \
 	ng_car.4 \
 	ng_ccatm.4 \
 	ng_checksum.4 \
 	ng_cisco.4 \
 	ng_deflate.4 \
 	ng_device.4 \
 	nge.4 \
 	ng_echo.4 \
 	ng_eiface.4 \
 	ng_etf.4 \
 	ng_ether.4 \
 	ng_ether_echo.4 \
 	ng_frame_relay.4 \
 	ng_gif.4 \
 	ng_gif_demux.4 \
 	ng_h4.4 \
 	ng_hci.4 \
 	ng_hole.4 \
 	ng_hub.4 \
 	ng_iface.4 \
 	ng_ipfw.4 \
 	ng_ip_input.4 \
 	ng_ksocket.4 \
 	ng_l2cap.4 \
 	ng_l2tp.4 \
 	ng_lmi.4 \
 	ng_macfilter.4 \
 	ng_mppc.4 \
 	ng_nat.4 \
 	ng_netflow.4 \
 	ng_one2many.4 \
 	ng_patch.4 \
 	ng_pipe.4 \
 	ng_ppp.4 \
 	ng_pppoe.4 \
 	ng_pptpgre.4 \
 	ng_pred1.4 \
 	ng_rfc1490.4 \
 	ng_socket.4 \
 	ng_source.4 \
 	ng_split.4 \
 	ng_sppp.4 \
 	ng_sscfu.4 \
 	ng_sscop.4 \
 	ng_tag.4 \
 	ng_tcpmss.4 \
 	ng_tee.4 \
 	ng_tty.4 \
 	ng_ubt.4 \
 	ng_UI.4 \
 	ng_uni.4 \
 	ng_vjc.4 \
 	ng_vlan.4 \
 	nmdm.4 \
 	${_ntb.4} \
 	${_ntb_hw_amd.4} \
 	${_ntb_hw_intel.4} \
 	${_ntb_hw_plx.4} \
 	${_ntb_transport.4} \
 	${_nda.4} \
 	${_if_ntb.4} \
 	null.4 \
 	numa.4 \
 	${_nvd.4} \
 	${_nvdimm.4} \
 	${_nvme.4} \
 	${_nvram.4} \
 	${_nvram2env.4} \
 	oce.4 \
 	ocs_fc.4\
 	ohci.4 \
 	orm.4 \
 	${_ossl.4} \
 	ow.4 \
 	ow_temp.4 \
 	owc.4 \
 	${_padlock.4} \
 	pass.4 \
 	pccard.4 \
 	pccbb.4 \
 	pcf.4 \
 	${_pchtherm.4} \
 	pci.4 \
 	pcib.4 \
 	pcic.4 \
 	pcm.4 \
 	${_pf.4} \
 	${_pflog.4} \
 	${_pfsync.4} \
 	pim.4 \
 	pms.4 \
 	polling.4 \
 	ppbus.4 \
 	ppc.4 \
 	ppi.4 \
 	procdesc.4 \
 	proto.4 \
 	ps4dshock.4 \
 	psm.4 \
 	pst.4 \
 	pt.4 \
 	ptnet.4 \
 	pts.4 \
 	pty.4 \
 	puc.4 \
 	pwmc.4 \
 	${_qat.4} \
 	${_qlxge.4} \
 	${_qlxgb.4} \
 	${_qlxgbe.4} \
 	${_qlnxe.4} \
 	ral.4 \
 	random.4 \
 	rctl.4 \
 	re.4 \
 	rgephy.4 \
 	rights.4 \
 	rl.4 \
 	rndtest.4 \
 	route.4 \
 	rtsx.4 \
 	rtwn.4 \
 	rtwnfw.4 \
 	rtwn_pci.4 \
 	rue.4 \
 	sa.4 \
 	safe.4 \
 	safexcel.4 \
 	sbp.4 \
 	sbp_targ.4 \
 	scc.4 \
 	sched_4bsd.4 \
 	sched_ule.4 \
 	screen.4 \
 	scsi.4 \
 	sctp.4 \
 	sdhci.4 \
 	sem.4 \
 	send.4 \
 	ses.4 \
 	${_sfxge.4} \
 	sge.4 \
 	siba.4 \
 	siftr.4 \
 	siis.4 \
 	simplebus.4 \
 	sis.4 \
 	sk.4 \
 	${_smartpqi.4} \
 	smb.4 \
 	smbios.4 \
 	smbus.4 \
 	smp.4 \
 	smsc.4 \
 	snd_ad1816.4 \
 	snd_als4000.4 \
 	snd_atiixp.4 \
 	snd_cmi.4 \
 	snd_cs4281.4 \
 	snd_csa.4 \
 	snd_ds1.4 \
 	snd_emu10k1.4 \
 	snd_emu10kx.4 \
 	snd_envy24.4 \
 	snd_envy24ht.4 \
 	snd_es137x.4 \
 	snd_ess.4 \
 	snd_fm801.4 \
 	snd_gusc.4 \
 	snd_hda.4 \
 	snd_hdspe.4 \
 	snd_ich.4 \
 	snd_maestro3.4 \
 	snd_maestro.4 \
 	snd_mss.4 \
 	snd_neomagic.4 \
 	snd_sbc.4 \
 	snd_solo.4 \
 	snd_spicds.4 \
 	snd_t4dwave.4 \
 	snd_uaudio.4 \
 	snd_via8233.4 \
 	snd_via82c686.4 \
 	snd_vibes.4 \
 	snp.4 \
 	spigen.4 \
 	${_spkr.4} \
 	splash.4 \
 	sppp.4 \
 	ste.4 \
 	stf.4 \
 	stge.4 \
 	${_sume.4} \
 	${_superio.4} \
 	sym.4 \
 	syncache.4 \
 	syncer.4 \
 	syscons.4 \
 	sysmouse.4 \
 	tap.4 \
 	targ.4 \
 	tcp.4 \
 	tcp_bbr.4 \
 	tdfx.4 \
 	terasic_mtl.4 \
 	termios.4 \
 	textdump.4 \
 	ti.4 \
 	timecounters.4 \
 	${_tpm.4} \
 	tty.4 \
 	tun.4 \
 	twa.4 \
 	twe.4 \
 	tws.4 \
 	udp.4 \
 	udplite.4 \
 	ure.4 \
 	vale.4 \
 	vga.4 \
 	vge.4 \
 	viapm.4 \
 	${_viawd.4} \
 	${_virtio.4} \
 	${_virtio_balloon.4} \
 	${_virtio_blk.4} \
 	${_virtio_console.4} \
 	${_virtio_random.4} \
 	${_virtio_scsi.4} \
 	${_vmci.4} \
 	vkbd.4 \
 	vlan.4 \
 	vxlan.4 \
 	${_vmd.4} \
 	${_vmm.4} \
 	${_vmx.4} \
 	vr.4 \
 	vt.4 \
 	vte.4 \
 	${_vtnet.4} \
 	watchdog.4 \
 	${_wbwd.4} \
 	witness.4 \
 	wlan.4 \
 	wlan_acl.4 \
 	wlan_amrr.4 \
 	wlan_ccmp.4 \
 	wlan_tkip.4 \
 	wlan_wep.4 \
 	wlan_xauth.4 \
 	wmt.4 \
 	${_wpi.4} \
 	wsp.4 \
 	xb360gp.4 \
 	${_xen.4} \
 	xhci.4 \
 	xl.4 \
 	${_xnb.4} \
 	xpt.4 \
 	zero.4
 
 MLINKS=	ads111x.4 ads1013.4 \
 	ads111x.4 ads1014.4 \
 	ads111x.4 ads1015.4 \
 	ads111x.4 ads1113.4 \
 	ads111x.4 ads1114.4 \
 	ads111x.4 ads1115.4
 MLINKS+=ae.4 if_ae.4
 MLINKS+=age.4 if_age.4
 MLINKS+=agp.4 agpgart.4
 MLINKS+=alc.4 if_alc.4
 MLINKS+=ale.4 if_ale.4
 MLINKS+=altera_atse.4 atse.4
 MLINKS+=altera_sdcard.4 altera_sdcardc.4
 MLINKS+=altq.4 ALTQ.4
 MLINKS+=ath.4 if_ath.4
 MLINKS+=ath_pci.4 if_ath_pci.4
 MLINKS+=an.4 if_an.4
 MLINKS+=aue.4 if_aue.4
 MLINKS+=axe.4 if_axe.4
 MLINKS+=bce.4 if_bce.4
 MLINKS+=bfe.4 if_bfe.4
 MLINKS+=bge.4 if_bge.4
 MLINKS+=bnxt.4 if_bnxt.4
 MLINKS+=bridge.4 if_bridge.4
 MLINKS+=bwi.4 if_bwi.4
 MLINKS+=bwn.4 if_bwn.4
 MLINKS+=${_bxe.4} ${_if_bxe.4}
 MLINKS+=cas.4 if_cas.4
 MLINKS+=cdce.4 if_cdce.4
 MLINKS+=cfi.4 cfid.4
 MLINKS+=cloudabi.4 cloudabi32.4 \
 	cloudabi.4 cloudabi64.4
 MLINKS+=crypto.4 cryptodev.4
 MLINKS+=cue.4 if_cue.4
 MLINKS+=cxgb.4 if_cxgb.4
 MLINKS+=cxgbe.4 if_cxgbe.4 \
 	cxgbe.4 vcxgbe.4 \
 	cxgbe.4 if_vcxgbe.4 \
 	cxgbe.4 cxl.4 \
 	cxgbe.4 if_cxl.4 \
 	cxgbe.4 vcxl.4 \
 	cxgbe.4 if_vcxl.4 \
 	cxgbe.4 cc.4 \
 	cxgbe.4 if_cc.4 \
 	cxgbe.4 vcc.4 \
 	cxgbe.4 if_vcc.4
 MLINKS+=cxgbev.4 if_cxgbev.4 \
 	cxgbev.4 cxlv.4 \
 	cxgbev.4 if_cxlv.4 \
 	cxgbev.4 ccv.4 \
 	cxgbev.4 if_ccv.4
 MLINKS+=dc.4 if_dc.4
 MLINKS+=disc.4 if_disc.4
 MLINKS+=edsc.4 if_edsc.4
 MLINKS+=em.4 if_em.4 \
 	em.4 igb.4 \
 	em.4 if_igb.4
 MLINKS+=enc.4 if_enc.4
 MLINKS+=epair.4 if_epair.4
 MLINKS+=et.4 if_et.4
 MLINKS+=fd.4 stderr.4 \
 	fd.4 stdin.4 \
 	fd.4 stdout.4
 MLINKS+=fdt.4 FDT.4
 MLINKS+=firewire.4 ieee1394.4
 MLINKS+=fwe.4 if_fwe.4
 MLINKS+=fwip.4 if_fwip.4
 MLINKS+=fxp.4 if_fxp.4
 MLINKS+=gem.4 if_gem.4
 MLINKS+=geom.4 GEOM.4
 MLINKS+=gif.4 if_gif.4
 MLINKS+=gpio.4 gpiobus.4
 MLINKS+=gpioths.4 dht11.4
 MLINKS+=gpioths.4 dht22.4
 MLINKS+=gre.4 if_gre.4
 MLINKS+=hpet.4 acpi_hpet.4
 MLINKS+=${_hptrr.4} ${_rr232x.4}
 MLINKS+=${_attimer.4} ${_i8254.4}
 MLINKS+=ip.4 rawip.4
 MLINKS+=ipfirewall.4 ipaccounting.4 \
 	ipfirewall.4 ipacct.4 \
 	ipfirewall.4 ipfw.4
 MLINKS+=ipheth.4 if_ipheth.4
 MLINKS+=ipw.4 if_ipw.4
 MLINKS+=iwi.4 if_iwi.4
 MLINKS+=iwm.4 if_iwm.4
 MLINKS+=iwn.4 if_iwn.4
 MLINKS+=ixgbe.4 ix.4
 MLINKS+=ixgbe.4 if_ix.4
 MLINKS+=ixgbe.4 if_ixgbe.4
 MLINKS+=ixl.4 if_ixl.4
 MLINKS+=iavf.4 if_iavf.4
 MLINKS+=jme.4 if_jme.4
 MLINKS+=kue.4 if_kue.4
 MLINKS+=lagg.4 trunk.4
 MLINKS+=lagg.4 if_lagg.4
 MLINKS+=le.4 if_le.4
 MLINKS+=lge.4 if_lge.4
 MLINKS+=lo.4 loop.4
 MLINKS+=lp.4 plip.4
 MLINKS+=malo.4 if_malo.4
 MLINKS+=md.4 vn.4
 MLINKS+=mem.4 kmem.4
 MLINKS+=mfi.4 mfi_linux.4 \
 	mfi.4 mfip.4
 MLINKS+=mlx5en.4 mce.4
 MLINKS+=mn.4 if_mn.4
 MLINKS+=mos.4 if_mos.4
 MLINKS+=msk.4 if_msk.4
 MLINKS+=mwl.4 if_mwl.4
 MLINKS+=mxge.4 if_mxge.4
 MLINKS+=my.4 if_my.4
 MLINKS+=${_ndis.4} ${_if_ndis.4}
 MLINKS+=netfpga10g_nf10bmac.4 if_nf10bmac.4
 MLINKS+=netintro.4 net.4 \
 	netintro.4 networking.4
 MLINKS+=${_nfe.4} ${_if_nfe.4}
 MLINKS+=nge.4 if_nge.4
 MLINKS+=ow.4 onewire.4
 MLINKS+=pccbb.4 cbb.4
 MLINKS+=pcm.4 snd.4 \
 	pcm.4 sound.4
 MLINKS+=pms.4 pmspcv.4
 MLINKS+=ptnet.4 if_ptnet.4
 MLINKS+=ral.4 if_ral.4
 MLINKS+=re.4 if_re.4
 MLINKS+=rl.4 if_rl.4
 MLINKS+=rtwn_pci.4 if_rtwn_pci.4
 MLINKS+=rue.4 if_rue.4
 MLINKS+=scsi.4 CAM.4 \
 	scsi.4 cam.4 \
 	scsi.4 scbus.4 \
 	scsi.4 SCSI.4
 MLINKS+=sge.4 if_sge.4
 MLINKS+=sis.4 if_sis.4
 MLINKS+=sk.4 if_sk.4
 MLINKS+=smp.4 SMP.4
 MLINKS+=smsc.4 if_smsc.4
 MLINKS+=snd_envy24.4 snd_ak452x.4
 MLINKS+=snd_sbc.4 snd_sb16.4 \
 	snd_sbc.4 snd_sb8.4
 MLINKS+=${_spkr.4} ${_speaker.4}
 MLINKS+=splash.4 screensaver.4
 MLINKS+=ste.4 if_ste.4
 MLINKS+=stf.4 if_stf.4
 MLINKS+=stge.4 if_stge.4
 MLINKS+=syncache.4 syncookies.4
 MLINKS+=syscons.4 sc.4
 MLINKS+=tap.4 if_tap.4 \
 	tap.4 vmnet.4 \
 	tap.4 if_vmnet.4
 MLINKS+=tdfx.4 tdfx_linux.4
 MLINKS+=ti.4 if_ti.4
 MLINKS+=tun.4 if_tun.4
 MLINKS+=ure.4 if_ure.4
 MLINKS+=vge.4 if_vge.4
 MLINKS+=vlan.4 if_vlan.4
 MLINKS+=vxlan.4 if_vxlan.4
 MLINKS+=${_vmx.4} ${_if_vmx.4}
 MLINKS+=vr.4 if_vr.4
 MLINKS+=vte.4 if_vte.4
 MLINKS+=${_vtnet.4} ${_if_vtnet.4}
 MLINKS+=watchdog.4 SW_WATCHDOG.4
 MLINKS+=${_wpi.4} ${_if_wpi.4}
 MLINKS+=xl.4 if_xl.4
 
 .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
 _acpi_asus.4=	acpi_asus.4
 _acpi_asus_wmi.4=	acpi_asus_wmi.4
 _acpi_dock.4=	acpi_dock.4
 _acpi_fujitsu.4=acpi_fujitsu.4
 _acpi_hp.4=	acpi_hp.4
 _acpi_ibm.4=	acpi_ibm.4
 _acpi_panasonic.4=acpi_panasonic.4
 _acpi_rapidstart.4=acpi_rapidstart.4
 _acpi_sony.4=	acpi_sony.4
 _acpi_toshiba.4=acpi_toshiba.4
 _acpi_wmi.4=	acpi_wmi.4
 _aesni.4=	aesni.4
 _aout.4=	aout.4
 _apic.4=	apic.4
 _atrtc.4=	atrtc.4
 _attimer.4=	attimer.4
 _aibs.4=	aibs.4
 _amdsbwd.4=	amdsbwd.4
 _amdsmb.4=	amdsmb.4
 _amdsmn.4=	amdsmn.4
 _amdtemp.4=	amdtemp.4
 _asmc.4=	asmc.4
 _bxe.4=		bxe.4
 _bytgpio.4=	bytgpio.4
 _chvgpio.4=	chvgpio.4
 _coretemp.4=	coretemp.4
 _cpuctl.4=	cpuctl.4
 _dpms.4=	dpms.4
 _ftwd.4=	ftwd.4
 _hpt27xx.4=	hpt27xx.4
 _hptiop.4=	hptiop.4
 _hptmv.4=	hptmv.4
 _hptnr.4=	hptnr.4
 _hptrr.4=	hptrr.4
 _hv_kvp.4=	hv_kvp.4
 _hv_netvsc.4=	hv_netvsc.4
 _hv_storvsc.4=	hv_storvsc.4
 _hv_utils.4=	hv_utils.4
 _hv_vmbus.4=	hv_vmbus.4
 _hv_vss.4=	hv_vss.4
 _hwpstate_intel.4=	hwpstate_intel.4
 _i8254.4=	i8254.4
 _ichwd.4=	ichwd.4
 _if_bxe.4=	if_bxe.4
 _if_ndis.4=	if_ndis.4
 _if_nfe.4=	if_nfe.4
 _if_urtw.4=	if_urtw.4
 _if_vmx.4=	if_vmx.4
 _if_vtnet.4=	if_vtnet.4
 _if_wpi.4=	if_wpi.4
 _imcsmb.4=	imcsmb.4
 _ipmi.4=	ipmi.4
 _io.4=		io.4
 _itwd.4=	itwd.4
 _linux.4=	linux.4
 _nda.4=		nda.4
 _ndis.4=	ndis.4
 _nfe.4=		nfe.4
 _nfsmb.4=	nfsmb.4
 _if_ntb.4=	if_ntb.4
 _ntb.4=		ntb.4
 _ntb_hw_amd.4=	ntb_hw_amd.4
 _ntb_hw_intel.4=	ntb_hw_intel.4
 _ntb_hw_plx.4=	ntb_hw_plx.4
 _ntb_transport.4=ntb_transport.4
 _nvd.4=		nvd.4
 _nvme.4=	nvme.4
 _nvram.4=	nvram.4
 _ossl.4=	ossl.4
 _padlock.4=	padlock.4
 _pchtherm.4=	pchtherm.4
 _qat.4=		qat.4
 _rr232x.4=	rr232x.4
 _speaker.4=	speaker.4
 _spkr.4=	spkr.4
 _superio.4=	superio.4
 _tpm.4=		tpm.4
 _urtw.4=	urtw.4
 _viawd.4=	viawd.4
 _virtio.4=	virtio.4
 _virtio_balloon.4=virtio_balloon.4
 _virtio_blk.4=	virtio_blk.4
 _virtio_console.4=virtio_console.4
 _virtio_random.4= virtio_random.4
 _virtio_scsi.4= virtio_scsi.4
 _vmci.4=	vmci.4
 _vmx.4=		vmx.4
 _vtnet.4=	vtnet.4
 _wbwd.4=	wbwd.4
 _wpi.4=		wpi.4
 _xen.4=		xen.4
 _xnb.4=		xnb.4
 
 .endif
 
 .if ${MACHINE_CPUARCH} == "amd64"
 _ioat.4=	ioat.4
 _nvdimm.4=	nvdimm.4
 _qlxge.4=	qlxge.4
 _qlxgb.4=	qlxgb.4
 _qlxgbe.4=	qlxgbe.4
 _qlnxe.4=	qlnxe.4
 _sfxge.4=	sfxge.4
 _smartpqi.4=	smartpqi.4
 _sume.4=	sume.4
 _vmd.4=		vmd.4
 
 MLINKS+=qlxge.4 if_qlxge.4
 MLINKS+=qlxgb.4 if_qlxgb.4
 MLINKS+=qlxgbe.4 if_qlxgbe.4
 MLINKS+=qlnxe.4 if_qlnxe.4
 MLINKS+=sfxge.4 if_sfxge.4
 MLINKS+=sume.4 if_sume.4
 
 .if ${MK_BHYVE} != "no"
 _bhyve.4=	bhyve.4
 _vmm.4=		vmm.4
 .endif
 .endif
 
 .if ${MACHINE_CPUARCH} == "mips"
 _nvram2env.4=	nvram2env.4
 .endif
 
 .if ${MACHINE_CPUARCH} == "powerpc"
 _if_vtnet.4=    if_vtnet.4
 _nvd.4= 	nvd.4
 _nvme.4=	nvme.4
 _virtio.4=	virtio.4
 _virtio_balloon.4=virtio_balloon.4
 _virtio_blk.4=	virtio_blk.4
 _virtio_console.4=virtio_console.4
 _virtio_random.4= virtio_random.4
 _virtio_scsi.4=	virtio_scsi.4
 _vtnet.4=	vtnet.4
 .endif
 
+.if ${MACHINE_CPUARCH} == "arm" || ${MACHINE_CPUARCH} == "aarch64" || \
+	 ${MACHINE_CPUARCH} == "riscv"
+_cgem.4=	cgem.4
+MLINKS+=cgem.4 if_cgem.4
+.endif
+
 .if empty(MAN_ARCH)
 __arches=	${MACHINE} ${MACHINE_ARCH} ${MACHINE_CPUARCH}
 .elif ${MAN_ARCH} == "all"
 __arches=	${:!/bin/sh -c "/bin/ls -d ${.CURDIR}/man4.*"!:E}
 .else
 __arches=	${MAN_ARCH}
 .endif
 .for __arch in ${__arches:O:u}
 .if exists(${.CURDIR}/man4.${__arch})
 SUBDIR+=	man4.${__arch}
 .endif
 .endfor
 
 .if ${MK_BLUETOOTH} != "no"
 MAN+=		ng_bluetooth.4
 .endif
 
 .if ${MK_CCD} != "no"
 _ccd.4=		ccd.4
 .endif
 
 .if ${MK_CDDL} != "no"
 _dtrace_provs=	dtrace_audit.4 \
 		dtrace_io.4 \
 		dtrace_ip.4 \
 		dtrace_lockstat.4 \
 		dtrace_proc.4 \
 		dtrace_sched.4 \
 		dtrace_sctp.4 \
 		dtrace_tcp.4 \
 		dtrace_udp.4 \
 		dtrace_udplite.4
 
 MLINKS+=	dtrace_audit.4 dtaudit.4
 .endif
 
 .if ${MK_EFI} != "no"
 MAN+=		efidev.4
 
 MLINKS+=	efidev.4 efirtc.4
 .endif
 
 .if ${MK_ISCSI} != "no"
 MAN+=		cfiscsi.4
 MAN+=		iscsi.4
 MAN+=		iscsi_initiator.4
 MAN+=		iser.4
 .endif
 
 .if ${MK_OFED} != "no"
 MAN+=		mlx4ib.4
 MAN+=		mlx5ib.4
 .endif
 
 .if ${MK_MLX5TOOL} != "no"
 MAN+=		mlx5io.4
 .endif
 
 .if ${MK_TESTS} != "no"
 ATF=            ${SRCTOP}/contrib/atf
 .PATH:          ${ATF}/doc
 _atf_test_case.4=	atf-test-case.4
 .endif
 
 .if ${MK_PF} != "no"
 _pf.4=		pf.4
 _pflog.4=	pflog.4
 _pfsync.4=	pfsync.4
 .endif
 
 .if ${MK_USB} != "no"
 MAN+=	\
 	otus.4 \
 	otusfw.4 \
 	rsu.4 \
 	rsufw.4 \
 	rtwn_usb.4 \
 	rum.4 \
 	run.4 \
 	runfw.4 \
 	u3g.4 \
 	uark.4 \
 	uart.4 \
 	uath.4 \
 	ubsa.4 \
 	ubser.4 \
 	ubtbcmfw.4 \
 	uchcom.4 \
 	ucom.4 \
 	ucycom.4 \
 	udav.4 \
 	udbp.4 \
 	udl.4 \
 	uep.4 \
 	ufoma.4 \
 	uftdi.4 \
 	ugen.4 \
 	ugold.4 \
 	uhci.4 \
 	uhid.4 \
 	uhso.4 \
 	uipaq.4 \
 	ukbd.4 \
 	uled.4 \
 	ulpt.4 \
 	umass.4 \
 	umcs.4 \
 	umct.4 \
 	umodem.4 \
 	umoscom.4 \
 	ums.4 \
 	unix.4 \
 	upgt.4 \
 	uplcom.4 \
 	ural.4 \
 	urio.4 \
 	urndis.4 \
 	${_urtw.4} \
 	usb.4 \
 	usb_quirk.4 \
 	usb_template.4 \
 	usbhid.4 \
 	usfs.4 \
 	uslcom.4 \
 	uvisor.4 \
 	uvscom.4 \
 	zyd.4
 
 MLINKS+=otus.4 if_otus.4
 MLINKS+=rsu.4 if_rsu.4
 MLINKS+=rtwn_usb.4 if_rtwn_usb.4
 MLINKS+=rum.4 if_rum.4
 MLINKS+=run.4 if_run.4
 MLINKS+=u3g.4 u3gstub.4
 MLINKS+=uath.4 if_uath.4
 MLINKS+=udav.4 if_udav.4
 MLINKS+=upgt.4 if_upgt.4
 MLINKS+=ural.4 if_ural.4
 MLINKS+=urndis.4 if_urndis.4
 MLINKS+=${_urtw.4} ${_if_urtw.4}
 MLINKS+=zyd.4 if_zyd.4
 .endif
 
 .include <bsd.prog.mk>
diff --git a/share/man/man4/man4.arm/cgem.4 b/share/man/man4/cgem.4
similarity index 96%
rename from share/man/man4/man4.arm/cgem.4
rename to share/man/man4/cgem.4
index 6de1d7961788..f9f525dc4554 100644
--- a/share/man/man4/man4.arm/cgem.4
+++ b/share/man/man4/cgem.4
@@ -1,298 +1,302 @@
 .\"
 .\" Copyright (c) 2014 Thomas Skibo <thomasskibo@yahoo.com>
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" are met:
 .\" 1. Redistributions of source code must retain the above copyright
 .\"    notice, this list of conditions and the following disclaimer.
 .\" 2. The name of the author may not be used to endorse or promote products
 .\"    derived from this software without specific prior written permission.
 .\"
 .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 .\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 26, 2014
+.Dd January 10, 2021
 .Dt CGEM 4
 .Os
 .Sh NAME
 .Nm cgem
 .Nd "Cadence GEM Gigabit Ethernet driver"
 .Sh SYNOPSIS
 To compile this driver into the kernel,
 place the following lines in your
 kernel configuration file:
 .Bd -ragged -offset indent
 .Cd "device ether"
 .Cd "device miibus"
 .Cd "device cgem"
 .Ed
 .Sh DESCRIPTION
 The
 .Nm
 driver provides support for the Cadence GEM (Gigabit Ethernet MAC).
 The Cadence GEM is used in some SoC (System on a Chip) devices such as
-the Xilinx Zynq-7000 and the Atmel SAMA5D3.
+the Xilinx Zynq-7000, the Xilinx Zynq UltraScale+, and the SiFive
+HiFive Unleashed.
 .Pp
 The
 .Nm
 driver supports the following media types:
 .Bl -tag -width ".Cm 10baseT/UTP"
 .It Cm autoselect
 Enable autoselection of the media type and options.
 The user can manually override
 the autoselected mode using
 .Xr ifconfig 8
 or by adding media options to
 .Xr rc.conf 5 .
 .It Cm 10baseT/UTP
 Set 10Mbps operation.
 The
 .Xr ifconfig 8
 .Cm mediaopt
 option can also be used to select either
 .Cm full-duplex
 or
 .Cm half-duplex
 modes.
 .It Cm 100baseTX
 Set 100Mbps (Fast Ethernet) operation.
 The
 .Xr ifconfig 8
 .Cm mediaopt
 option can also be used to select either
 .Cm full-duplex
 or
 .Cm half-duplex
 modes.
 .It Cm 1000baseT
 Set 1000Mbps (Gigabit Ethernet) operation over twisted pair.
 The GEM supports 1000Mbps in
 .Cm full-duplex
 mode only.
 .El
 .Pp
 The
 .Nm
 driver supports the following media options:
 .Bl -tag -width ".Cm full-duplex"
 .It Cm full-duplex
 Force full-duplex operation.
 .It Cm half-duplex
 Force half-duplex operation.
 .El
 .Pp
 The driver provides support for TCP/UDP/IP checksum offloading (although
 disabled by default).
 The device and driver also support 1536-byte frames for VLANs (vlanmtu).
 .Sh SYSCTL VARIABLES
 The following variables are available as both
 .Xr sysctl 8
 variables and
 .Xr loader 8
 tunables:
 .Bl -tag -width "xxxxxxxx"
 .It Va dev.cgem.%d.rxbufs
 The number of receive buffers allocated to the hardware.
 The default value is 256.
 The maximum value is 511.
 If this number is increased while the interface is UP, it will not
 take effect until the next packet is received.
 If this number is decreased while the interface is UP, buffers will
 not be immediately removed from the receive buffer ring but the
 number of buffers will decrease as packets are received until it
 reaches the new value.
 .It Va dev.cgem.%d.rxhangwar
 This tunable enables a work-around to recover from receive hangs.
 The default value is 1.
 Set to 0 to disable the work-around.
 .El
 .Pp
 The following read-only variables are available as
 .Xr sysctl 8
 variables:
 .Bl -tag -width "xxxxxxxx"
 .It Va dev.cgem.%d._rxoverruns
 This variable counts the number of receive packet buffer overrun interrupts.
 .It Va dev.cgem.%d._rxnobufs
 This variable counts the number of interrupts due to the GEM buffer ring
 going empty.
 .It Va dev.cgem.%d._rxdmamapfails
 This variable is the number of times bus_dmamap_load_mbuf_sg(9) failed in
 the receive path.
 .It Va dev.cgem.%d._txfull
 The number of times the GEM's transmit ring was full.
 .It Va dev.cgem.%d._txdmamapfails
 This variable is the number of times bus_dmamap_load_mbuf_sg(9) failed in
 the transmit path.
 .It Va dev.cgem.%d._txdefrags
 This variable is the number of times the driver needed to call m_defrag(9)
 because a packet queued for transmit had too many DMA segments.
 .It Va dev.cgem.%d._txdefragfails
 This variable is the number of times
 .Xr m_defrag 9
 failed.
 .It Va dev.cgem.%d.stats.*
 The following variables are useful MAC counters supplied by the hardware:
 .It Va dev.cgem.%d.stats.tx_bytes
 A 64-bit counter of the number of bytes transmitted in frames without error.
 .It Va dev.cgem.%d.stats.tx_frames
 Counter of frames transmitted without error excluding pause frames.
 .It Va dev.cgem.%d.stats.tx_frames_bcast
 Counter of broadcast frames transmitted without error excluding
 pause frames.
 .It Va dev.cgem.%d.stats.tx_frames_multi
 Counter of multicast frames transmitted without error excluding
 pause frames.
 .It Va dev.cgem.%d.stats.tx_frames_pause
 Counter of pause frames transmitted without error.
 .It Va dev.cgem.%d.stats.tx_frames_64b
 Counter of 64 byte frames transmitted without error.
 .It Va dev.cgem.%d.stats.tx_frames_65to127b
 Counter of 65 to 127 byte frames transmitted without error.
 .It Va dev.cgem.%d.stats.tx_frames_128to255b
 Counter of 128 to 255 byte frames transmitted without error.
 .It Va dev.cgem.%d.stats.tx_frames_256to511b
 Counter of 256 to 511 byte frames transmitted without error.
 .It Va dev.cgem.%d.stats.tx_frames_512to1023b
 Counter of 512 to 1023 byte frames transmitted without error.
 .It Va dev.cgem.%d.stats.tx_frames_1024to1536b
 Counter of 1024 to 1536 byte frames transmitted without error.
 .It Va dev.cgem.%d.stats.tx_under_runs
 Counter of frames not transmitted due to a transmit underrun.
 .It Va dev.cgem.%d.stats.tx_single_collisn
 Counter of frames experiencing a single collision before being successfully
 transmitted.
 .It Va dev.cgem.%d.stats.tx_multi_collisn
 Counter of frames experiencing between 2 and 15 collisions before
 being successfully transmitted.
 .It Va dev.cgem.%d.stats.tx_excsv_collisn
 Counter of frames that failed to transmit because they experienced 16
 collisions.
 .It Va dev.cgem.%d.stats.tx_late_collisn
 Counter of frames that experienced a late collision.
 .It Va dev.cgem.%d.stats.tx_deferred_frames
 Counter of frames experiencing deferral due to carrier sense being
 active on their first attempt at transmission.
 .It Va dev.cgem.%d.stats.tx_carrier_sense_errs
 Counter of frames transmitted where carrier sense was not seen during
 transmission or where carrier sense was deasserted after being asserted
 in a transmit frame without collision.
 .It Va dev.cgem.%d.stats.rx_bytes
 A 64-bit counter of bytes received without error excluding pause
 frames.
 .It Va dev.cgem.%d.stats.rx_frames
 Counter of frames received without error excluding pause frames.
 .It Va dev.cgem.%d.stats.rx_frames_bcast
 Counter of broadcast frames receive without error excluding pause frames.
 .It Va dev.cgem.%d.stats.rx_frames_multi
 Counter of multicast frames receive without error excluding pause frames.
 .It Va dev.cgem.%d.stats.rx_frames_pause
 Counter of pause frames recevied without error.
 .It Va dev.cgem.%d.stats.rx_frames_64b
 Counter of 64-byte frames received without error.
 .It Va dev.cgem.%d.stats.rx_frames_65to127b
 Counter of 65 to 127 byte frames received without error.
 .It Va dev.cgem.%d.stats.rx_frames_128to255b
 Counter of 128 to 255 byte frames received without error.
 .It Va dev.cgem.%d.stats.rx_frames_256to511b
 Counter of 256 to 511 byte frames received without error.
 .It Va dev.cgem.%d.stats.rx_frames_512to1023b
 Counter of 512 to 1023 byte frames received without error.
 .It Va dev.cgem.%d.stats.rx_frames_1024to1536b
 Counter of 1024 to 1536 byte frames received without error.
 .It Va dev.cgem.%d.stats.rx_frames_undersize
 Counter of frames received less than 64 bytes in length that
 do not also have either a CRC error or an alignment error.
 .It Va dev.cgem.%d.stats.rx_frames_oversize
 Counter of frames received exceeding 1536 bytes and do not also have either
 a CRC error or an alignment error.
 .It Va dev.cgem.%d.stats.rx_frames_jabber
 Counter of frames received exceeding 1536 bytes and also have either a CRC
 error, an alignment error, or a receive symbol error.
 .It Va dev.cgem.%d.stats.rx_frames_fcs_errs
 Counter of frames received with a bad CRC and are between 64
 and 1536 bytes.
 .It Va dev.cgem.%d.stats.rx_frames_length_errs
 Counter of frames received that are shorter than that extracted
 from the length field.
 .It Va dev.cgem.%d.stats.rx_symbol_errs
 Counter of receive symbol errors.
 .It Va dev.cgem.%d.stats.rx_align_errs
 Counter of received frames that are not an integral number of bytes.
 .It Va dev.cgem.%d.stats.rx_resource_errs
 Counter of frames successfully receive by the MAC but could not be
 copied to memory because no receive buffer was available.
 .It Va dev.cgem.%d.stats.rx_overrun_errs
 Counter of frames that are address recognized but were not copied
 to memory due to a receive overrun.
 .It Va dev.cgem.%d.stats.rx_frames_ip_hdr_csum_errs
 Counter of frames discarded due to an incorrect IP header checksum when
 checksum offloading is enabled.
 .It Va dev.cgem.%d.stats.rx_frames_tcp_csum_errs
 Counter of frames discarded due to an incorrect TCP checksum when
 checksum offloading is enabled.
 .It Va dev.cgem.%d.stats.rx_frames_udp_csum_errs
 Counter of frames discarded due to an incorrect UDP checksum when
 checksum offloading is enabled.
 .El
 .Sh SEE ALSO
 .Xr miibus 4 ,
 .Xr ifconfig 8
 .Rs
 .%T "Zynq-7000 SoC Technical Reference Manual (Xilinx doc UG585)"
 .%U http://www.xilinx.com/support/documentation/user_guides/\:ug585-Zynq-7000-TRM.pdf
 .Re
 .Sh HISTORY
 The
 .Nm
 device driver first appeared in
 .Fx 10.0 .
 .Sh AUTHORS
 The
 .Nm
 driver and this manual page was written by
 .An Thomas Skibo Aq Mt thomasskibo@yahoo.com .
 .Sh BUGS
 The GEM can perform TCP/UDP/IP checksum offloading.
 However, when transmit checksum offloading is enabled, the GEM generates and
 replaces checksums for all packets it transmits.
 In a system that is forwarding packets, the device could potentially correct
 the checksum of packet that was corrupted in transit.
 For this reason, checksum offloading is disabled by default but can be
 enabled using ifconfig(8).
 .Pp
 When receive checksum offloading is enabled, the device will discard packets
 with bad TCP/UDP/IP checksums.
 The bad packets will not be counted in any
 .Xr netstat 1
 statistics.
 There are
 .Xr sysctl 8
 variables that count
 packets discarded by the hardware (see below).
 .Pp
-The GEM used in the Zynq-7000 has a bug such that  the receiver can
+The GEM used in the Zynq-7000 has a bug such that the receiver can
 potentially freeze up under a high load.
 The issue is described in sec. 16.7
 "Known Issues" of the Zynq-7000 SoC Technical Reference Manual (Xilinx
 UG585 v1.7).
 The
 .Nm
 driver implements the work-around suggested in the manual.
-If the bug does not exist in other versions of this device, the
-work-around can be disabled by setting the dev.cgem.%d.rxhangwar
+It is believed that the bug does not exist in the Zynq UltraScale+ and
+SiFive SoCs so the work-around is disabled in those instances and enabled
+in all others.
+The work-around can be disabled by setting the
+.Va dev.cgem.%d.rxhangwar
 .Xr sysctl 8
 variable to 0.
diff --git a/share/man/man4/man4.arm/Makefile b/share/man/man4/man4.arm/Makefile
index 21d53f43a7c8..0b3eec427934 100644
--- a/share/man/man4/man4.arm/Makefile
+++ b/share/man/man4/man4.arm/Makefile
@@ -1,25 +1,23 @@
 # $FreeBSD$
 
 MAN=	\
 	aw_gpio.4 \
 	aw_mmc.4 \
 	aw_rtc.4 \
 	aw_sid.4 \
 	aw_spi.4 \
 	aw_syscon.4 \
 	bcm283x_pwm.4 \
-	cgem.4 \
 	devcfg.4 \
 	imx6_ahci.4 \
 	imx6_snvs.4 \
 	imx_wdog.4 \
 	mge.4 \
 	ti_adc.4
 
-MLINKS= cgem.4 if_cgem.4
-MLINKS+= imx_wdog.4 imxwdt.4
+MLINKS= imx_wdog.4 imxwdt.4
 MLINKS+= mge.4 if_mge.4
 
 MANSUBDIR=/arm
 
 .include <bsd.prog.mk>
diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC
index 0f0522eb9802..3cfe16ccfe54 100644
--- a/sys/arm/conf/GENERIC
+++ b/sys/arm/conf/GENERIC
@@ -1,301 +1,301 @@
 #
 # GENERICV6 -- Generic(ish) kernel config.
 #
 # For more information on this file, please read the config(5) manual page,
 # and/or the handbook section on Kernel Configuration Files:
 #
 #    https://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
 #
 # The handbook is also available locally in /usr/share/doc/handbook
 # if you've installed the doc distribution, otherwise always see the
 # FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the
 # latest information.
 #
 # An exhaustive list of options and more detailed explanations of the
 # device lines is also present in the ../../conf/NOTES and NOTES files.
 # If you are in doubt as to the purpose or necessity of a line, check first
 # in NOTES.
 #
 # $FreeBSD$
 
 ident		GENERIC
 
 cpu		CPU_CORTEXA
 cpu		CPU_MV_PJ4B
 options 	SMP_ON_UP
 machine 	arm armv7
 makeoptions	CONF_CFLAGS="-march=armv7a"
 
 include 	"std.armv7"
 files		"../allwinner/files.allwinner"
 files		"../allwinner/files.allwinner_up"
 files		"../allwinner/a10/files.a10"
 files		"../allwinner/a13/files.a13"
 files		"../allwinner/a20/files.a20"
 files		"../allwinner/a31/files.a31"
 files		"../allwinner/a33/files.a33"
 files		"../allwinner/a83t/files.a83t"
 files		"../allwinner/h3/files.h3"
 files		"../broadcom/bcm2835/files.bcm2836"
 files		"../broadcom/bcm2835/files.bcm283x"
 files		"../freescale/imx/files.imx6"
 files		"../mv/files.arm7"
 files		"../nvidia/tegra124/files.tegra124"
 files		"../qemu/files.qemu"
 files		"../rockchip/files.rk32xx"
 files		"../ti/files.ti"
 files		"../ti/am335x/files.am335x"
 files		"../ti/omap4/files.omap4"
 files		"../xilinx/files.zynq7"
 
 options 	SOC_ALLWINNER_A10
 options 	SOC_ALLWINNER_A13
 options 	SOC_ALLWINNER_A20
 options 	SOC_ALLWINNER_A31
 options 	SOC_ALLWINNER_A31S
 options 	SOC_ALLWINNER_A33
 options 	SOC_ALLWINNER_A83T
 options 	SOC_ALLWINNER_H2PLUS
 options 	SOC_ALLWINNER_H3
 options 	SOC_BCM2836
 options 	SOC_BRCM_BCM2837
 options 	SOC_MV_ARMADA38X
 options 	SOC_MV_ARMADAXP
 options		SOC_TI_AM335X
 options		SOC_OMAP4
 
 options 	SCHED_ULE		# ULE scheduler
 options 	SMP			# Enable multiple cores
 options 	PLATFORM
 options 	LINUX_BOOT_ABI
 
 # EXT_RESOURCES pseudo devices
 options 	EXT_RESOURCES
 device		clk
 device		phy
 device		hwreset
 device		nvmem
 device		regulator
 device		syscon
 
 # CPU frequency control
 device		cpufreq
 
 # Interrupt controller
 device		gic
 
 # PMU support (for CCNT).
 device		pmu
 
 # ARM Generic Timer
 device		generic_timer
 device		mpcore_timer
 
 # MMC/SD/SDIO Card slot support
 device		dwmmc
 device		sdhci			# SD controller
 device		mmc			# mmc/sd bus
 device		mmcsd			# mmc/sd flash cards
 
 # ATA controllers
 device		ahci			# AHCI-compatible SATA controllers
 #device		ata			# Legacy ATA/SATA controllers
 
 # PCI
 options 	NEW_PCIB
 device		pci
 device		pci_host_generic
 
 # PCI NICs
 device		re			# RealTek 8139C+/8169/8169S/8110S
 
 # VirtIO
 device		virtio
 device		virtio_mmio
 device		virtio_pci
 device		virtio_blk
 device		vtnet
 
 # Console and misc
 device		uart
 device		uart_ns8250
 device		uart_snps
 device		pl011
 device		pty
 device		snp
 device		md			# Memory "disks"
 device		firmware		# firmware assist module
 device		pl310			# PL310 L2 cache controller
 device		psci
 
 # I2C support
 device		iicbus
 device		iic
 device		twsi
 device		rsb			# Allwinner Reduced Serial Bus
 device		p2wi			# Allwinner Push-Pull Two Wire
 device		axp209			# AXP209 Power Management Unit
 device		axp81x			# AXP813/818 Power Management Unit
 device		bcm2835_bsc
 device		fsliic			# Freescale i2c/iic
 device		icee			# AT24Cxxx and compatible EEPROMs
 device		sy8106a			# SY8106A Buck Regulator
 device		ti_i2c
 device		am335x_pmic		# AM335x Power Management IC (TPC65217)
 device		am335x_rtc		# RTC support (power management only)
 device		twl			# TI TWLX0X0/TPS659x0 Power Management
 device		twl_vreg		# twl voltage regulation
 device		twl_clks		# twl external clocks
 
 # i2c RTCs
 device		ds1307			# Dallas DS1307 RTC and compatible
 device		ds13rtc			# All Dallas/Maxim DS13xx RTCs
 device		ds1672			# Dallas DS1672 RTC
 device		ds3231			# Dallas DS3231 RTC + temperature
 device		nxprtc			# NXP RTCs: PCA/PFC212x PCA/PCF85xx
 device		s35390a			# Seiko s3539x RTCs
 
 # GPIO
 device		dwgpio			# Synopsys DesignWare APB GPIO Controller
 device		gpio
 device		gpiobacklight
 device		gpioled
 device		gpioregulator
 
 # EVDEV support
 device		evdev			# input event device support
 options		EVDEV_SUPPORT		# evdev support in legacy drivers
 device		uinput			# install /dev/uinput cdev
 device		aw_cir
 
 # SPI
 device		spibus
 device		spigen
 device		bcm2835_spi
 device		mv_spi
 device		ti_spi
 device		zy7_qspi		# Xilinx Zynq QSPI controller
 
 # ADC support
 device		ti_adc
 
 # PWM
 device		pwm
 
 # Watchdog support
 # If we don't enable the watchdog driver, the BealeBone could potentially
 # reboot automatically because the boot loader might have enabled the
 # watchdog.
 device		ti_wdt
 device		imxwdt			# Watchdog. WARNING: can't be disabled!!!
 device		aw_wdog			# Allwinner Watchdog
 
 device		scbus			# SCSI bus (required for ATA/SCSI)
 device		da			# Direct Access (disks)
 device		cd			# CD
 device		pass			# Passthrough device (direct ATA/SCSI access)
 
 # USB support
 options 	USB_HOST_ALIGN=64	# Align usb buffers to cache line size.
 device		usb
 device		uhci
 device		ohci
 device		ehci
 device		xhci
 device		dwcotg			# DWC OTG controller
 device		musb
 
 device		axe			# USB-Ethernet
 device		umass			# Disks/Mass storage - Requires scbus and da
 device		uhid			# "Human Interface Devices"
 device		ukbd			# Allow keyboard like HIDs to control console
 
 # Device mode support
 device		usb_template    	# Control of the gadget
 
 # Ethernet
 device		loop
 device		ether
 device		vlan			# 802.1Q VLAN support
 device		bpf
 device		mii
 device		mdio
 device		etherswitch
 device		e6000sw
 
 # Ethernet NICs that use the common MII bus controller code.
 # NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
 device		miibus
 
 device		awg			# 10/100/1000 integrated EMAC controller
+device		cgem			# Cadence GEM Gigabit Ethernet device
 device		cpsw			# TI Common Platform Ethernet Switch (CPSW)
-device		cgem			# Zynq-7000 gig ethernet device
 device		dwc			# 10/100/1000 integrated GMAC controller
 device		emac			# 10/100 integrated EMAC controller
 device		ffec			# Freescale Fast Ethernet Controller
 device		neta			# Marvell 10/100/1000 Network controller
 device		smsc			# SMSC LAN91C111
 
 # Sound support
 device		sound
 
 # Framebuffer support
 device		vt
 device		kbdmux
 device		ums
 device		videomode
 device		hdmi
 device		vchiq
 
 # Pinmux
 device		fdt_pinctrl
 
 # TI Programmable Realtime Unit support
 device		ti_pruss
 
 # Mailbox support
 device		ti_mbox
 
 # DMA controller
 device		fslsdma
 device		ti_sdma
 device		a10_dmac
 device		a31_dmac
 
 # Extensible Firmware Interface
 options 	EFI
 
 # Marvell Cryptographic Engine and Security Accelerator
 device		cesa
 device		crypto
 device		cryptodev
 
 # RTC
 device		imx6_snvs		# IMX6 On-chip RTC
 device		aw_rtc			# Allwinner On-chip RTC
 
 # EFUSE
 device		aw_sid		# Allwinner Secure ID EFUSE
 
 # Thermal sensors
 device		aw_thermal	# Allwinner Thermal Sensor Controller
 
 # HID support
 device		hid		# Generic HID support
 
 # Flattened Device Tree
 options 	FDT			# Configure using FDT/DTB data
 makeoptions	MODULES_EXTRA+="dtb/allwinner"
 makeoptions	MODULES_EXTRA+="dtb/am335x"
 makeoptions	MODULES_EXTRA+="dtb/imx6"
 makeoptions	MODULES_EXTRA+="dtb/nvidia"
 makeoptions	MODULES_EXTRA+="dtb/omap4"
 makeoptions	MODULES_EXTRA+="dtb/rockchip"
 makeoptions	MODULES_EXTRA+="dtb/rpi"
 makeoptions	MODULES_EXTRA+="dtb/zynq"
 
 # SOC-specific modules
 makeoptions	MODULES_EXTRA+="allwinner"
 makeoptions	MODULES_EXTRA+="arm_ti"
 makeoptions	MODULES_EXTRA+="imx"
 
diff --git a/sys/arm/conf/ZEDBOARD b/sys/arm/conf/ZEDBOARD
index 613e0c73a16d..24490a5129e5 100644
--- a/sys/arm/conf/ZEDBOARD
+++ b/sys/arm/conf/ZEDBOARD
@@ -1,85 +1,85 @@
 #
 # ZEDBOARD -- Custom configuration for the Xilinx Zynq-7000 based
 #             ZedBoard (www.zedboard.org) and similar Zynq boards.
 #
 # For more information on this file, please read the config(5) manual page,
 # and/or the handbook section on Kernel Configuration Files:
 #
 #    https://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
 #
 # The handbook is also available locally in /usr/share/doc/handbook
 # if you've installed the doc distribution, otherwise always see the
 # FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the
 # latest information.
 #
 # An exhaustive list of options and more detailed explanations of the
 # device lines is also present in the ../../conf/NOTES and NOTES files.
 # If you are in doubt as to the purpose or necessity of a line, check first
 # in NOTES.
 #
 # $FreeBSD$
 
 ident		ZEDBOARD
 
 include 	"std.armv7"
 include 	"../xilinx/std.zynq7"
 
 makeoptions	MODULES_EXTRA="dtb/zynq"
 
 options 	SCHED_ULE		# ULE scheduler
 options 	PLATFORM		# Platform based SoC
 #options 	NFSSD			# Network Filesystem Server
 options 	SMP			# Enable multiple cores
 
 # NFS root from boopt/dhcp
 #options 	BOOTP
 #options 	BOOTP_NFSROOT
 #options 	BOOTP_COMPAT
 #options 	BOOTP_NFSV3
 
 options 	ROOTDEVNAME=\"ufs:mmcsd0s2a\"
 
 # Interrupt controller
 device		gic
 
 # Cache controller
 device		pl310			# PL310 L2 cache controller
 # ARM MPCore timer
 device		mpcore_timer
 
 device		loop
 device		ether
-device		cgem			# Zynq-7000 gig ethernet device
+device		cgem			# Cadence GEM Gigabit Ethernet device
 device		mii
 device		e1000phy
 device		rgephy			# Zybo uses Realtek RTL8211E
 device		pty
 device		uart
 device		gpio
 
 device		spibus
 device		spigen
 device		mx25l
 device		zy7_qspi		# Xilinx Zynq QSPI controller
 device		zy7_spi			# Xilinx Zynq SPI controller
 
 device		md
 device		mmc			# mmc/sd bus
 device		mmcsd			# mmc/sd flash cards
 device		sdhci			# generic sdhci
 device		bpf			# Berkeley packet filter
 
 # USB support
 device		usb
 device		ehci
 device		umass
 device		scbus			# SCSI bus (required for ATA/SCSI)
 device		da			# Direct Access (disks)
 device		axe			# USB-Ethernet
 
 
 # Flattened Device Tree
 options 	FDT			# Configure using FDT/DTB data
 #options 	FDT_DTB_STATIC
 #makeoptions	FDT_DTS_FILE=zedboard.dts
 
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
index 268089dba1fc..463271d1db26 100644
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -1,386 +1,387 @@
 #
 # GENERIC -- Generic kernel configuration file for FreeBSD/arm64
 #
 # For more information on this file, please read the config(5) manual page,
 # and/or the handbook section on Kernel Configuration Files:
 #
 #    https://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
 #
 # The handbook is also available locally in /usr/share/doc/handbook
 # if you've installed the doc distribution, otherwise always see the
 # FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the
 # latest information.
 #
 # An exhaustive list of options and more detailed explanations of the
 # device lines is also present in the ../../conf/NOTES and NOTES files.
 # If you are in doubt as to the purpose or necessity of a line, check first
 # in NOTES.
 #
 # $FreeBSD$
 
 cpu		ARM64
 ident		GENERIC
 
 makeoptions	DEBUG=-g		# Build kernel with gdb(1) debug symbols
 makeoptions	WITH_CTF=1		# Run ctfconvert(1) for DTrace support
 
 options 	SCHED_ULE		# ULE scheduler
 options 	NUMA			# Non-Uniform Memory Architecture support
 options 	PREEMPTION		# Enable kernel thread preemption
 options 	VIMAGE			# Subsystem virtualization, e.g. VNET
 options 	INET			# InterNETworking
 options 	INET6			# IPv6 communications protocols
 options 	IPSEC_SUPPORT		# Allow kldload of ipsec and tcpmd5
 options		ROUTE_MPATH		# Multipath routing support
 options 	TCP_OFFLOAD		# TCP offload
 options 	TCP_HHOOK		# hhook(9) framework for TCP
 options		TCP_RFC7413		# TCP Fast Open
 options 	SCTP_SUPPORT		# Allow kldload of SCTP
 options 	FFS			# Berkeley Fast Filesystem
 options 	SOFTUPDATES		# Enable FFS soft updates support
 options 	UFS_ACL			# Support for access control lists
 options 	UFS_DIRHASH		# Improve performance on big directories
 options 	UFS_GJOURNAL		# Enable gjournal-based UFS journaling
 options 	QUOTA			# Enable disk quotas for UFS
 options 	MD_ROOT			# MD is a potential root device
 options 	NFSCL			# Network Filesystem Client
 options 	NFSD			# Network Filesystem Server
 options 	NFSLOCKD		# Network Lock Manager
 options 	NFS_ROOT		# NFS usable as /, requires NFSCL
 options 	MSDOSFS			# MSDOS Filesystem
 options 	CD9660			# ISO 9660 Filesystem
 options 	PROCFS			# Process filesystem (requires PSEUDOFS)
 options 	PSEUDOFS		# Pseudo-filesystem framework
 options 	TMPFS			# Efficient memory filesystem
 options 	GEOM_RAID		# Soft RAID functionality.
 options 	GEOM_LABEL		# Provides labelization
 options 	EFIRT			# EFI Runtime Services support
 options 	COMPAT_FREEBSD32	# Compatible with FreeBSD/arm
 options 	COMPAT_FREEBSD11	# Compatible with FreeBSD11
 options 	COMPAT_FREEBSD12	# Compatible with FreeBSD12
 options 	SCSI_DELAY=5000		# Delay (in ms) before probing SCSI
 options 	KTRACE			# ktrace(1) support
 options 	STACK			# stack(9) support
 options 	SYSVSHM			# SYSV-style shared memory
 options 	SYSVMSG			# SYSV-style message queues
 options 	SYSVSEM			# SYSV-style semaphores
 options 	_KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
 options 	PRINTF_BUFR_SIZE=128	# Prevent printf output being interspersed.
 options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
 options 	HWPMC_HOOKS		# Necessary kernel hooks for hwpmc(4)
 options 	AUDIT			# Security event auditing
 options 	CAPABILITY_MODE		# Capsicum capability mode
 options 	CAPABILITIES		# Capsicum capabilities
 options 	MAC			# TrustedBSD MAC Framework
 options 	KDTRACE_FRAME		# Ensure frames are compiled in
 options 	KDTRACE_HOOKS		# Kernel DTrace hooks
 options 	DDB_CTF			# Kernel ELF linker loads CTF data
 options 	VFP			# Floating-point support
 options 	RACCT			# Resource accounting framework
 options 	RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
 options 	RCTL			# Resource limits
 options 	INTRNG
 options 	LINUX_BOOT_ABI		# Boot using booti command from U-Boot
 
 # Debugging support.  Always need this:
 options 	KDB			# Enable kernel debugger support.
 options 	KDB_TRACE		# Print a stack trace for a panic.
 # For full debugger support use (turn off in stable branch):
 options 	DDB			# Support DDB.
 options 	GDB			# Support remote GDB.
 options 	DEADLKRES		# Enable the deadlock resolver
 options 	INVARIANTS		# Enable calls of extra sanity checking
 options 	INVARIANT_SUPPORT	# Extra sanity checks of internal structures, required by INVARIANTS
 options 	WITNESS			# Enable checks to detect deadlocks and cycles
 options 	WITNESS_SKIPSPIN	# Don't run witness on spinlocks for speed
 options 	MALLOC_DEBUG_MAXZONES=8	# Separate malloc(9) zones
 options 	ALT_BREAK_TO_DEBUGGER	# Enter debugger on keyboard escape sequence
 options 	VERBOSE_SYSINIT=0	# Support debug.verbose_sysinit, off by default
 
 # Kernel Sanitizers
 #options 	COVERAGE		# Generic kernel coverage. Used by KCOV
 #options 	KCOV			# Kernel Coverage Sanitizer
 # Warning: KUBSAN can result in a kernel too large for loader to load
 #options 	KUBSAN			# Kernel Undefined Behavior Sanitizer
 #options 	KCSAN			# Kernel Concurrency Sanitizer
 
 # Kernel dump features.
 options 	EKCD			# Support for encrypted kernel dumps
 options 	GZIO			# gzip-compressed kernel and user dumps
 options 	ZSTDIO			# zstd-compressed kernel and user dumps
 options 	DEBUGNET		# debugnet networking
 options 	NETDUMP			# netdump(4) client support
 
 # Make an SMP-capable kernel by default
 options 	SMP			# Symmetric MultiProcessor Kernel
 
 # SoC support
 options 	SOC_ALLWINNER_A64
 options 	SOC_ALLWINNER_H5
 options 	SOC_ALLWINNER_H6
 options 	SOC_CAVM_THUNDERX
 options 	SOC_FREESCALE_IMX8
 options 	SOC_HISI_HI6220
 options 	SOC_INTEL_STRATIX10
 options 	SOC_BRCM_BCM2837
 options 	SOC_BRCM_BCM2838
 options 	SOC_MARVELL_8K
 options 	SOC_NVIDIA_TEGRA210
 options		SOC_NXP_LS
 options 	SOC_ROCKCHIP_RK3328
 options 	SOC_ROCKCHIP_RK3399
 options 	SOC_XILINX_ZYNQ
 
 # Timer drivers
 device		a10_timer
 
 # Annapurna Alpine drivers
 device		al_ccu			# Alpine Cache Coherency Unit
 device		al_nb_service		# Alpine North Bridge Service
 device		al_iofic		# I/O Fabric Interrupt Controller
 device		al_serdes		# Serializer/Deserializer
 device		al_udma			# Universal DMA
 
 # Qualcomm Snapdragon drivers
 device		qcom_gcc		# Global Clock Controller
 
 # CPU frequency control
 device		cpufreq
 
 # Bus drivers
 device		pci
 device		pci_n1sdp	# ARM Neoverse N1 SDP PCI
 device		al_pci		# Annapurna Alpine PCI-E
 options 	PCI_HP			# PCI-Express native HotPlug
 options 	PCI_IOV		# PCI SR-IOV support
 
 # Block devices
 device		ahci
 device		scbus
 device		da
 
 # ATA/SCSI peripherals
 device		cd		# CD
 device		pass		# Passthrough device (direct ATA/SCSI access)
 
 # NVM Express (NVMe) support
 device		nvme		# base NVMe driver
 options 	NVME_USE_NVD=0	# prefer the cam(4) based nda(4) driver
 device		nvd		# expose NVMe namespaces as disks, depends on nvme
 
 # DMA controller
 device		a31_dmac
 
 # GPIO / PINCTRL
 device		a37x0_gpio	# Marvell Armada 37x0 GPIO controller
 device		aw_gpio		# Allwinner GPIO controller
 device		dwgpio		# Synopsys DesignWare APB GPIO Controller
 device		gpio
 device		gpioled
 device		fdt_pinctrl
 device		gpioregulator
 device		ls1046_gpio	# LS1046A GPIO controller
 device		mv_gpio		# Marvell GPIO controller
 device		mvebu_pinctrl	# Marvell Pinmux Controller
 device		pl061		# Arm PL061 GPIO controller
 device		rk_gpio		# RockChip GPIO Controller
 device		rk_pinctrl	# RockChip Pinmux Controller
 
 # I2C
 device		a37x0_iic	# Armada 37x0 I2C controller
 device		aw_rsb		# Allwinner Reduced Serial Bus
 device		bcm2835_bsc	# Broadcom BCM283x I2C bus
 device		iicbus
 device		iicmux
 device		iic
 device		icee		# Generic IIC eeprom
 device		twsi		# Allwinner I2C controller
 device		pca9547		# NPX I2C bus multiplexer
 device		pcf8563		# NXP Real-time clock/calendar
 device		rk_i2c		# RockChip I2C controller
 device		syr827		# Silergy SYR827 PMIC
 device		sy8106a		# SY8106A Buck Regulator
 device		vf_i2c		# Freescale Vybrid I2C controller
 device		fsliic		# Freescale iMX I2C controller
 
 # Clock and reset controllers
 device		aw_ccu		# Allwinner clock controller
 
 # Interrupt controllers
 device		aw_nmi		# Allwinner NMI support
 device		mv_cp110_icu	# Marvell CP110 ICU
 device		mv_ap806_gicp	# Marvell AP806 GICP
 device		mv_ap806_sei	# Marvell AP806 SEI
 
 # Real-time clock support
 device		aw_rtc		# Allwinner Real-time Clock
 device		mv_rtc		# Marvell Real-time Clock
 
 # Crypto accelerators
 device		safexcel	# Inside Secure EIP-97
 
 # Watchdog controllers
 device		aw_wdog		# Allwinner Watchdog
 
 # Power management controllers
 device		axp81x		# X-Powers AXP81x PMIC
 device		rk805		# RockChip RK805 PMIC
 
 # EFUSE
 device		aw_sid		# Allwinner Secure ID EFUSE
 
 # Thermal sensors
 device		aw_thermal	# Allwinner Thermal Sensor Controller
 device		mv_thermal	# Marvell Thermal Sensor Controller
 
 # SPI
 device		spibus
 device		a37x0_spi	# Marvell Armada 37x0 SPI Controller
 device		bcm2835_spi	# Broadcom BCM283x SPI bus
 device		rk_spi		# RockChip SPI controller
 
 # PWM
 device		pwm
 device		aw_pwm
 device		rk_pwm
 
 # Console
 device		vt
 device		kbdmux
 
 device		vt_efifb
 
 # EVDEV support
 device		evdev			# input event device support
 options		EVDEV_SUPPORT		# evdev support in legacy drivers
 device		uinput			# install /dev/uinput cdev
 device		aw_cir
 
 # Serial (COM) ports
 device		uart			# Generic UART driver
 device		uart_imx		# iMX8 UART
 device		uart_msm		# Qualcomm MSM UART driver
 device		uart_mu			# RPI3 aux port
 device		uart_mvebu		# Armada 3700 UART driver
 device		uart_ns8250		# ns8250-type UART driver
 device		uart_snps
 device		pl011
 
 # PCI/PCI-X/PCIe Ethernet NICs that use iflib infrastructure
 device		iflib
 device		em			# Intel PRO/1000 Gigabit Ethernet Family
 device		ix			# Intel 10Gb Ethernet Family
 
 # Ethernet NICs
 device		mdio
 device		mii
 device		miibus			# MII bus support
 device		al_eth			# Annapurna Alpine Ethernet NIC
 device		awg			# Allwinner EMAC Gigabit Ethernet
 device		axa			# AMD Opteron A1100 integrated NIC
+device		cgem			# Cadence GEM Gigabit Ethernet device
 device		dwc_rk			# Rockchip Designware
 device		dwc_socfpga		# Altera SOCFPGA Ethernet MAC
 device		ffec			# iMX FFEC
 device		genet			# Broadcom on RPi4
 device		msk			# Marvell/SysKonnect Yukon II Gigabit Ethernet
 device		neta			# Marvell Armada 370/38x/XP/3700 NIC
 device		re			# RealTek 8139C+/8169/8169S/8110S
 device		smc			# SMSC LAN91C111
 device		vnic			# Cavium ThunderX NIC
 
 # Etherswitch devices
 device		etherswitch		# Enable etherswitch support
 device		miiproxy		# Required for etherswitch
 device		e6000sw			# Marvell mv88e6085 based switches
 
 
 # Pseudo devices.
 device		crypto			# core crypto support
 device		loop			# Network loopback
 device		ether			# Ethernet support
 device		vlan			# 802.1Q VLAN support
 device		tuntap			# Packet tunnel.
 device		md			# Memory "disks"
 device		gif			# IPv6 and IPv4 tunneling
 device		firmware		# firmware assist module
 
 # EXT_RESOURCES pseudo devices
 options 	EXT_RESOURCES
 device		clk
 device		phy
 device		hwreset
 device		nvmem
 device		regulator
 device		syscon
 device		aw_syscon
 
 # IO Domains
 device		rk_iodomain
 
 # The `bpf' device enables the Berkeley Packet Filter.
 # Be aware of the administrative consequences of enabling this!
 # Note that 'bpf' is required for DHCP.
 device		bpf		# Berkeley packet filter
 
 # USB support
 options 	USB_DEBUG		# enable debug msgs
 options 	USB_HOST_ALIGN=64	# Align usb buffers to cache line size.
 device		aw_usbphy		# Allwinner USB PHY
 device		rk_usb2phy		# Rockchip USB2PHY
 device		rk_typec_phy		# Rockchip TypeC PHY
 device		dwcotg			# DWC OTG controller
 device		musb			# Mentor Graphics USB OTG controller
 device		ohci			# OHCI USB interface
 device		uhci			# UHCI USB interface
 device		ehci			# EHCI USB interface (USB 2.0)
 device		ehci_mv			# Marvell EHCI USB interface
 device		xhci			# XHCI USB interface (USB 3.0)
 device		dwc3			# Synopsys DWC controller
 device		aw_dwc3			# Allwinner DWC3 controller
 device		rk_dwc3			# Rockchip DWC3 controller
 device		usb			# USB Bus (required)
 device		ukbd			# Keyboard
 device		umass			# Disks/Mass storage - Requires scbus and da
 device		tegra210_xusb_fw	# Tegra XUSB firmware
 
 # USB ethernet support
 device		muge
 device		smcphy
 device		smsc
 device		ure
 
 # Sound support
 device sound
 device a10_codec
 
 # MMC/SD/SDIO Card slot support
 device		sdhci
 device		sdhci_xenon		# Marvell Xenon SD/MMC controller
 device		aw_mmc			# Allwinner SD/MMC controller
 device		mmc			# mmc/sd bus
 device		mmcsd			# mmc/sd flash cards
 device		dwmmc
 device		dwmmc_altera
 device		dwmmc_hisi
 device		rk_dwmmc
 device		rk_emmcphy
 
 # VirtIO support
 device		virtio
 device		virtio_pci
 device		virtio_mmio
 device		virtio_blk
 device		vtnet
 
 # Chip-specific errata
 options 	THUNDERX_PASS_1_1_ERRATA
 
 options 	FDT
 device		acpi
 
 # DTBs
 makeoptions	MODULES_EXTRA="dtb/allwinner dtb/freescale dtb/imx8 dtb/nvidia dtb/mv dtb/rockchip dtb/rpi"
 
 # HID support
 options 	HID_DEBUG	# enable debug msgs
 device		hid		# Generic HID support
diff --git a/sys/dev/cadence/if_cgem.c b/sys/dev/cadence/if_cgem.c
index 3c5277452469..77337e977dcc 100644
--- a/sys/dev/cadence/if_cgem.c
+++ b/sys/dev/cadence/if_cgem.c
@@ -1,1860 +1,1985 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2012-2014 Thomas Skibo <thomasskibo@yahoo.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 /*
  * A network interface driver for Cadence GEM Gigabit Ethernet
  * interface such as the one used in Xilinx Zynq-7000 SoC.
  *
  * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
  * (v1.4) November 16, 2012.  Xilinx doc UG585.  GEM is covered in Ch. 16
  * and register definitions are in appendix B.18.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/module.h>
 #include <sys/rman.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
 
 #include <machine/bus.h>
 
 #include <net/ethernet.h>
 #include <net/if.h>
 #include <net/if_arp.h>
 #include <net/if_dl.h>
 #include <net/if_media.h>
 #include <net/if_mib.h>
 #include <net/if_types.h>
 
 #ifdef INET
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
 #include <netinet/ip.h>
 #endif
 
 #include <net/bpf.h>
 #include <net/bpfdesc.h>
 
 #include <dev/fdt/fdt_common.h>
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
 
 #include <dev/mii/mii.h>
 #include <dev/mii/miivar.h>
 
+#ifdef EXT_RESOURCES
+#include <dev/extres/clk/clk.h>
+#endif
+
+#if INTPTR_MAX == INT64_MAX
+#define CGEM64
+#endif
+
 #include <dev/cadence/if_cgem_hw.h>
 
 #include "miibus_if.h"
 
 #define IF_CGEM_NAME "cgem"
 
 #define CGEM_NUM_RX_DESCS	512	/* size of receive descriptor ring */
 #define CGEM_NUM_TX_DESCS	512	/* size of transmit descriptor ring */
 
-#define MAX_DESC_RING_SIZE (MAX(CGEM_NUM_RX_DESCS*sizeof(struct cgem_rx_desc),\
-				CGEM_NUM_TX_DESCS*sizeof(struct cgem_tx_desc)))
-
 /* Default for sysctl rxbufs.  Must be < CGEM_NUM_RX_DESCS of course. */
 #define DEFAULT_NUM_RX_BUFS	256	/* number of receive bufs to queue. */
 
 #define TX_MAX_DMA_SEGS		8	/* maximum segs in a tx mbuf dma */
 
 #define CGEM_CKSUM_ASSIST	(CSUM_IP | CSUM_TCP | CSUM_UDP | \
 				 CSUM_TCP_IPV6 | CSUM_UDP_IPV6)
 
+#define HWTYPE_GENERIC_GEM	1
+#define HWTYPE_ZYNQ		2
+#define HWTYPE_ZYNQMP		3
+#define HWTYPE_SIFIVE_FU540	4
+
 static struct ofw_compat_data compat_data[] = {
-	{ "cadence,gem",		1 },
-	{ "cdns,macb",			1 },
-	{ "sifive,fu540-c000-gem",	1 },
-	{ NULL,				0 },
+	{ "cdns,zynq-gem",		HWTYPE_ZYNQ },
+	{ "cdns,zynqmp-gem",		HWTYPE_ZYNQMP },
+	{ "sifive,fu540-c000-gem",	HWTYPE_SIFIVE_FU540 },
+	{ "cdns,gem",			HWTYPE_GENERIC_GEM },
+	{ "cadence,gem",		HWTYPE_GENERIC_GEM },
+	{ NULL,				0 }
 };
 
 struct cgem_softc {
 	if_t			ifp;
 	struct mtx		sc_mtx;
 	device_t		dev;
 	device_t		miibus;
 	u_int			mii_media_active;	/* last active media */
 	int			if_old_flags;
 	struct resource		*mem_res;
 	struct resource		*irq_res;
 	void			*intrhand;
 	struct callout		tick_ch;
 	uint32_t		net_ctl_shadow;
+	uint32_t		net_cfg_shadow;
+#ifdef EXT_RESOURCES
+	clk_t			ref_clk;
+#else
 	int			ref_clk_num;
-	u_char			eaddr[6];
+#endif
+	int			neednullqs;
 
 	bus_dma_tag_t		desc_dma_tag;
 	bus_dma_tag_t		mbuf_dma_tag;
 
 	/* receive descriptor ring */
 	struct cgem_rx_desc	*rxring;
 	bus_addr_t		rxring_physaddr;
 	struct mbuf		*rxring_m[CGEM_NUM_RX_DESCS];
 	bus_dmamap_t		rxring_m_dmamap[CGEM_NUM_RX_DESCS];
 	int			rxring_hd_ptr;	/* where to put rcv bufs */
 	int			rxring_tl_ptr;	/* where to get receives */
 	int			rxring_queued;	/* how many rcv bufs queued */
 	bus_dmamap_t		rxring_dma_map;
 	int			rxbufs;		/* tunable number rcv bufs */
 	int			rxhangwar;	/* rx hang work-around */
 	u_int			rxoverruns;	/* rx overruns */
 	u_int			rxnobufs;	/* rx buf ring empty events */
 	u_int			rxdmamapfails;	/* rx dmamap failures */
 	uint32_t		rx_frames_prev;
 
 	/* transmit descriptor ring */
 	struct cgem_tx_desc	*txring;
 	bus_addr_t		txring_physaddr;
 	struct mbuf		*txring_m[CGEM_NUM_TX_DESCS];
 	bus_dmamap_t		txring_m_dmamap[CGEM_NUM_TX_DESCS];
 	int			txring_hd_ptr;	/* where to put next xmits */
 	int			txring_tl_ptr;	/* next xmit mbuf to free */
 	int			txring_queued;	/* num xmits segs queued */
-	bus_dmamap_t		txring_dma_map;
 	u_int			txfull;		/* tx ring full events */
 	u_int			txdefrags;	/* tx calls to m_defrag() */
 	u_int			txdefragfails;	/* tx m_defrag() failures */
 	u_int			txdmamapfails;	/* tx dmamap failures */
 
+	/* null descriptor rings */
+	void			*null_qs;
+	bus_addr_t		null_qs_physaddr;
+
 	/* hardware provided statistics */
 	struct cgem_hw_stats {
 		uint64_t		tx_bytes;
 		uint32_t		tx_frames;
 		uint32_t		tx_frames_bcast;
 		uint32_t		tx_frames_multi;
 		uint32_t		tx_frames_pause;
 		uint32_t		tx_frames_64b;
 		uint32_t		tx_frames_65to127b;
 		uint32_t		tx_frames_128to255b;
 		uint32_t		tx_frames_256to511b;
 		uint32_t		tx_frames_512to1023b;
 		uint32_t		tx_frames_1024to1536b;
 		uint32_t		tx_under_runs;
 		uint32_t		tx_single_collisn;
 		uint32_t		tx_multi_collisn;
 		uint32_t		tx_excsv_collisn;
 		uint32_t		tx_late_collisn;
 		uint32_t		tx_deferred_frames;
 		uint32_t		tx_carrier_sense_errs;
 
 		uint64_t		rx_bytes;
 		uint32_t		rx_frames;
 		uint32_t		rx_frames_bcast;
 		uint32_t		rx_frames_multi;
 		uint32_t		rx_frames_pause;
 		uint32_t		rx_frames_64b;
 		uint32_t		rx_frames_65to127b;
 		uint32_t		rx_frames_128to255b;
 		uint32_t		rx_frames_256to511b;
 		uint32_t		rx_frames_512to1023b;
 		uint32_t		rx_frames_1024to1536b;
 		uint32_t		rx_frames_undersize;
 		uint32_t		rx_frames_oversize;
 		uint32_t		rx_frames_jabber;
 		uint32_t		rx_frames_fcs_errs;
 		uint32_t		rx_frames_length_errs;
 		uint32_t		rx_symbol_errs;
 		uint32_t		rx_align_errs;
 		uint32_t		rx_resource_errs;
 		uint32_t		rx_overrun_errs;
 		uint32_t		rx_ip_hdr_csum_errs;
 		uint32_t		rx_tcp_csum_errs;
 		uint32_t		rx_udp_csum_errs;
 	} stats;
 };
 
 #define RD4(sc, off)		(bus_read_4((sc)->mem_res, (off)))
 #define WR4(sc, off, val)	(bus_write_4((sc)->mem_res, (off), (val)))
 #define BARRIER(sc, off, len, flags) \
 	(bus_barrier((sc)->mem_res, (off), (len), (flags))
 
 #define CGEM_LOCK(sc)		mtx_lock(&(sc)->sc_mtx)
 #define CGEM_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
 #define CGEM_LOCK_INIT(sc)	mtx_init(&(sc)->sc_mtx, \
 	    device_get_nameunit((sc)->dev), MTX_NETWORK_LOCK, MTX_DEF)
 #define CGEM_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->sc_mtx)
 #define CGEM_ASSERT_LOCKED(sc)	mtx_assert(&(sc)->sc_mtx, MA_OWNED)
 
 /* Allow platforms to optionally provide a way to set the reference clock. */
 int cgem_set_ref_clk(int unit, int frequency);
 
 static devclass_t cgem_devclass;
 
 static int cgem_probe(device_t dev);
 static int cgem_attach(device_t dev);
 static int cgem_detach(device_t dev);
 static void cgem_tick(void *);
 static void cgem_intr(void *);
 
 static void cgem_mediachange(struct cgem_softc *, struct mii_data *);
 
 static void
 cgem_get_mac(struct cgem_softc *sc, u_char eaddr[])
 {
 	int i;
 	uint32_t rnd;
 
 	/* See if boot loader gave us a MAC address already. */
 	for (i = 0; i < 4; i++) {
 		uint32_t low = RD4(sc, CGEM_SPEC_ADDR_LOW(i));
 		uint32_t high = RD4(sc, CGEM_SPEC_ADDR_HI(i)) & 0xffff;
 		if (low != 0 || high != 0) {
 			eaddr[0] = low & 0xff;
 			eaddr[1] = (low >> 8) & 0xff;
 			eaddr[2] = (low >> 16) & 0xff;
 			eaddr[3] = (low >> 24) & 0xff;
 			eaddr[4] = high & 0xff;
 			eaddr[5] = (high >> 8) & 0xff;
 			break;
 		}
 	}
 
 	/* No MAC from boot loader?  Assign a random one. */
 	if (i == 4) {
 		rnd = arc4random();
 
 		eaddr[0] = 'b';
 		eaddr[1] = 's';
 		eaddr[2] = 'd';
 		eaddr[3] = (rnd >> 16) & 0xff;
 		eaddr[4] = (rnd >> 8) & 0xff;
 		eaddr[5] = rnd & 0xff;
 
 		device_printf(sc->dev, "no mac address found, assigning "
 		    "random: %02x:%02x:%02x:%02x:%02x:%02x\n", eaddr[0],
 		    eaddr[1], eaddr[2], eaddr[3], eaddr[4], eaddr[5]);
 	}
 
 	/* Move address to first slot and zero out the rest. */
 	WR4(sc, CGEM_SPEC_ADDR_LOW(0), (eaddr[3] << 24) |
 	    (eaddr[2] << 16) | (eaddr[1] << 8) | eaddr[0]);
 	WR4(sc, CGEM_SPEC_ADDR_HI(0), (eaddr[5] << 8) | eaddr[4]);
 
 	for (i = 1; i < 4; i++) {
 		WR4(sc, CGEM_SPEC_ADDR_LOW(i), 0);
 		WR4(sc, CGEM_SPEC_ADDR_HI(i), 0);
 	}
 }
 
 /*
  * cgem_mac_hash():  map 48-bit address to a 6-bit hash. The 6-bit hash
- * corresponds to a bit in a 64-bit hash register.  Setting that bit in the hash
- * register enables reception of all frames with a destination address that
- * hashes to that 6-bit value.
+ * corresponds to a bit in a 64-bit hash register.  Setting that bit in the
+ * hash register enables reception of all frames with a destination address
+ * that hashes to that 6-bit value.
  *
  * The hash function is described in sec. 16.2.3 in the Zynq-7000 Tech
  * Reference Manual.  Bits 0-5 in the hash are the exclusive-or of
  * every sixth bit in the destination address.
  */
 static int
 cgem_mac_hash(u_char eaddr[])
 {
 	int hash;
 	int i, j;
 
 	hash = 0;
 	for (i = 0; i < 6; i++)
 		for (j = i; j < 48; j += 6)
 			if ((eaddr[j >> 3] & (1 << (j & 7))) != 0)
 				hash ^= (1 << i);
 
 	return hash;
 }
 
 static u_int
 cgem_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
 {
 	uint32_t *hashes = arg;
 	int index;
 
 	index = cgem_mac_hash(LLADDR(sdl));
 	if (index > 31)
 		hashes[0] |= (1U << (index - 32));
 	else
 		hashes[1] |= (1U << index);
 
 	return (1);
 }
 
 /*
  * After any change in rx flags or multi-cast addresses, set up hash registers
  * and net config register bits.
  */
 static void
 cgem_rx_filter(struct cgem_softc *sc)
 {
 	if_t ifp = sc->ifp;
 	uint32_t hashes[2] = { 0, 0 };
-	uint32_t net_cfg;
-
-	net_cfg = RD4(sc, CGEM_NET_CFG);
 
-	net_cfg &= ~(CGEM_NET_CFG_MULTI_HASH_EN |
+	sc->net_cfg_shadow &= ~(CGEM_NET_CFG_MULTI_HASH_EN |
 	    CGEM_NET_CFG_NO_BCAST | CGEM_NET_CFG_COPY_ALL);
 
 	if ((if_getflags(ifp) & IFF_PROMISC) != 0)
-		net_cfg |= CGEM_NET_CFG_COPY_ALL;
+		sc->net_cfg_shadow |= CGEM_NET_CFG_COPY_ALL;
 	else {
 		if ((if_getflags(ifp) & IFF_BROADCAST) == 0)
-			net_cfg |= CGEM_NET_CFG_NO_BCAST;
+			sc->net_cfg_shadow |= CGEM_NET_CFG_NO_BCAST;
 		if ((if_getflags(ifp) & IFF_ALLMULTI) != 0) {
 			hashes[0] = 0xffffffff;
 			hashes[1] = 0xffffffff;
 		} else
 			if_foreach_llmaddr(ifp, cgem_hash_maddr, hashes);
 
 		if (hashes[0] != 0 || hashes[1] != 0)
-			net_cfg |= CGEM_NET_CFG_MULTI_HASH_EN;
+			sc->net_cfg_shadow |= CGEM_NET_CFG_MULTI_HASH_EN;
 	}
 
 	WR4(sc, CGEM_HASH_TOP, hashes[0]);
 	WR4(sc, CGEM_HASH_BOT, hashes[1]);
-	WR4(sc, CGEM_NET_CFG, net_cfg);
+	WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
 }
 
 /* For bus_dmamap_load() callback. */
 static void
 cgem_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 {
 
 	if (nsegs != 1 || error != 0)
 		return;
 	*(bus_addr_t *)arg = segs[0].ds_addr;
 }
 
+/* Set up null queues for priority queues we actually can't disable. */
+static void
+cgem_null_qs(struct cgem_softc *sc)
+{
+	struct cgem_rx_desc *rx_desc;
+	struct cgem_tx_desc *tx_desc;
+	uint32_t queue_mask;
+	int n;
+
+	/* Read design config register 6 to determine number of queues. */
+	queue_mask = (RD4(sc, CGEM_DESIGN_CFG6) &
+	    CGEM_DESIGN_CFG6_DMA_PRIO_Q_MASK) >> 1;
+	if (queue_mask == 0)
+		return;
+
+	/* Create empty RX queue and empty TX buf queues. */
+	memset(sc->null_qs, 0, sizeof(struct cgem_rx_desc) +
+	    sizeof(struct cgem_tx_desc));
+	rx_desc = sc->null_qs;
+	rx_desc->addr = CGEM_RXDESC_OWN | CGEM_RXDESC_WRAP;
+	tx_desc = (struct cgem_tx_desc *)(rx_desc + 1);
+	tx_desc->ctl = CGEM_TXDESC_USED | CGEM_TXDESC_WRAP;
+
+	/* Point all valid ring base pointers to the null queues. */
+	for (n = 1; (queue_mask & 1) != 0; n++, queue_mask >>= 1) {
+		WR4(sc, CGEM_RX_QN_BAR(n), sc->null_qs_physaddr);
+		WR4(sc, CGEM_TX_QN_BAR(n), sc->null_qs_physaddr +
+		    sizeof(struct cgem_rx_desc));
+	}
+}
+
 /* Create DMA'able descriptor rings. */
 static int
 cgem_setup_descs(struct cgem_softc *sc)
 {
 	int i, err;
+	int desc_rings_size = CGEM_NUM_RX_DESCS * sizeof(struct cgem_rx_desc) +
+	    CGEM_NUM_TX_DESCS * sizeof(struct cgem_tx_desc);
+
+	if (sc->neednullqs)
+		desc_rings_size += sizeof(struct cgem_rx_desc) +
+		    sizeof(struct cgem_tx_desc);
 
 	sc->txring = NULL;
 	sc->rxring = NULL;
 
 	/* Allocate non-cached DMA space for RX and TX descriptors. */
-	err = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0,
-	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
-	    MAX_DESC_RING_SIZE, 1, MAX_DESC_RING_SIZE, 0,
+	err = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1,
+#ifdef CGEM64
+	    1ULL << 32,	/* Do not cross a 4G boundary. */
+#else
+	    0,
+#endif
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    desc_rings_size, 1, desc_rings_size, 0,
 	    busdma_lock_mutex, &sc->sc_mtx, &sc->desc_dma_tag);
 	if (err)
 		return (err);
 
 	/* Set up a bus_dma_tag for mbufs. */
 	err = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0,
-	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
-	    MCLBYTES, TX_MAX_DMA_SEGS, MCLBYTES, 0,
-	    busdma_lock_mutex, &sc->sc_mtx, &sc->mbuf_dma_tag);
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
+	    TX_MAX_DMA_SEGS, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx,
+	    &sc->mbuf_dma_tag);
 	if (err)
 		return (err);
 
-	/* Allocate DMA memory in non-cacheable space. */
+	/*
+	 * Allocate DMA memory in non-cacheable space.  We allocate transmit,
+	 * receive and null descriptor queues all at once because the
+	 * hardware only provides one register for the upper 32 bits of
+	 * rx and tx descriptor queues hardware addresses.
+	 */
 	err = bus_dmamem_alloc(sc->desc_dma_tag, (void **)&sc->rxring,
-	    BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->rxring_dma_map);
+#ifdef __arm__
+	    BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_ZERO,
+#else
+	    BUS_DMA_NOWAIT | BUS_DMA_NOCACHE | BUS_DMA_ZERO,
+#endif
+	    &sc->rxring_dma_map);
 	if (err)
 		return (err);
 
 	/* Load descriptor DMA memory. */
 	err = bus_dmamap_load(sc->desc_dma_tag, sc->rxring_dma_map,
-	    (void *)sc->rxring, CGEM_NUM_RX_DESCS*sizeof(struct cgem_rx_desc),
+	    (void *)sc->rxring, desc_rings_size,
 	    cgem_getaddr, &sc->rxring_physaddr, BUS_DMA_NOWAIT);
 	if (err)
 		return (err);
 
 	/* Initialize RX descriptors. */
 	for (i = 0; i < CGEM_NUM_RX_DESCS; i++) {
 		sc->rxring[i].addr = CGEM_RXDESC_OWN;
 		sc->rxring[i].ctl = 0;
 		sc->rxring_m[i] = NULL;
 		sc->rxring_m_dmamap[i] = NULL;
 	}
 	sc->rxring[CGEM_NUM_RX_DESCS - 1].addr |= CGEM_RXDESC_WRAP;
 
 	sc->rxring_hd_ptr = 0;
 	sc->rxring_tl_ptr = 0;
 	sc->rxring_queued = 0;
 
-	/* Allocate DMA memory for TX descriptors in non-cacheable space. */
-	err = bus_dmamem_alloc(sc->desc_dma_tag, (void **)&sc->txring,
-	    BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->txring_dma_map);
-	if (err)
-		return (err);
-
-	/* Load TX descriptor DMA memory. */
-	err = bus_dmamap_load(sc->desc_dma_tag, sc->txring_dma_map,
-	    (void *)sc->txring, CGEM_NUM_TX_DESCS*sizeof(struct cgem_tx_desc),
-	    cgem_getaddr, &sc->txring_physaddr, BUS_DMA_NOWAIT);
-	if (err)
-		return (err);
+	sc->txring = (struct cgem_tx_desc *)(sc->rxring + CGEM_NUM_RX_DESCS);
+	sc->txring_physaddr = sc->rxring_physaddr + CGEM_NUM_RX_DESCS *
+	    sizeof(struct cgem_rx_desc);
 
 	/* Initialize TX descriptor ring. */
 	for (i = 0; i < CGEM_NUM_TX_DESCS; i++) {
 		sc->txring[i].addr = 0;
 		sc->txring[i].ctl = CGEM_TXDESC_USED;
 		sc->txring_m[i] = NULL;
 		sc->txring_m_dmamap[i] = NULL;
 	}
 	sc->txring[CGEM_NUM_TX_DESCS - 1].ctl |= CGEM_TXDESC_WRAP;
 
 	sc->txring_hd_ptr = 0;
 	sc->txring_tl_ptr = 0;
 	sc->txring_queued = 0;
 
+	if (sc->neednullqs) {
+		sc->null_qs = (void *)(sc->txring + CGEM_NUM_TX_DESCS);
+		sc->null_qs_physaddr = sc->txring_physaddr +
+		    CGEM_NUM_TX_DESCS * sizeof(struct cgem_tx_desc);
+
+		cgem_null_qs(sc);
+	}
+
 	return (0);
 }
 
 /* Fill receive descriptor ring with mbufs. */
 static void
 cgem_fill_rqueue(struct cgem_softc *sc)
 {
 	struct mbuf *m = NULL;
 	bus_dma_segment_t segs[TX_MAX_DMA_SEGS];
 	int nsegs;
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	while (sc->rxring_queued < sc->rxbufs) {
 		/* Get a cluster mbuf. */
 		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
 		if (m == NULL)
 			break;
 
 		m->m_len = MCLBYTES;
 		m->m_pkthdr.len = MCLBYTES;
 		m->m_pkthdr.rcvif = sc->ifp;
 
 		/* Load map and plug in physical address. */
 		if (bus_dmamap_create(sc->mbuf_dma_tag, 0,
 		    &sc->rxring_m_dmamap[sc->rxring_hd_ptr])) {
 			sc->rxdmamapfails++;
 			m_free(m);
 			break;
 		}
 		if (bus_dmamap_load_mbuf_sg(sc->mbuf_dma_tag,
 		    sc->rxring_m_dmamap[sc->rxring_hd_ptr], m,
 		    segs, &nsegs, BUS_DMA_NOWAIT)) {
 			sc->rxdmamapfails++;
 			bus_dmamap_destroy(sc->mbuf_dma_tag,
 				   sc->rxring_m_dmamap[sc->rxring_hd_ptr]);
 			sc->rxring_m_dmamap[sc->rxring_hd_ptr] = NULL;
 			m_free(m);
 			break;
 		}
 		sc->rxring_m[sc->rxring_hd_ptr] = m;
 
 		/* Sync cache with receive buffer. */
 		bus_dmamap_sync(sc->mbuf_dma_tag,
 		    sc->rxring_m_dmamap[sc->rxring_hd_ptr],
 		    BUS_DMASYNC_PREREAD);
 
 		/* Write rx descriptor and increment head pointer. */
 		sc->rxring[sc->rxring_hd_ptr].ctl = 0;
+#ifdef CGEM64
+		sc->rxring[sc->rxring_hd_ptr].addrhi = segs[0].ds_addr >> 32;
+#endif
 		if (sc->rxring_hd_ptr == CGEM_NUM_RX_DESCS - 1) {
 			sc->rxring[sc->rxring_hd_ptr].addr = segs[0].ds_addr |
 			    CGEM_RXDESC_WRAP;
 			sc->rxring_hd_ptr = 0;
 		} else
 			sc->rxring[sc->rxring_hd_ptr++].addr = segs[0].ds_addr;
 
 		sc->rxring_queued++;
 	}
 }
 
 /* Pull received packets off of receive descriptor ring. */
 static void
 cgem_recv(struct cgem_softc *sc)
 {
 	if_t ifp = sc->ifp;
 	struct mbuf *m, *m_hd, **m_tl;
 	uint32_t ctl;
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	/* Pick up all packets in which the OWN bit is set. */
 	m_hd = NULL;
 	m_tl = &m_hd;
 	while (sc->rxring_queued > 0 &&
-	   (sc->rxring[sc->rxring_tl_ptr].addr & CGEM_RXDESC_OWN) != 0) {
+	    (sc->rxring[sc->rxring_tl_ptr].addr & CGEM_RXDESC_OWN) != 0) {
 		ctl = sc->rxring[sc->rxring_tl_ptr].ctl;
 
 		/* Grab filled mbuf. */
 		m = sc->rxring_m[sc->rxring_tl_ptr];
 		sc->rxring_m[sc->rxring_tl_ptr] = NULL;
 
 		/* Sync cache with receive buffer. */
 		bus_dmamap_sync(sc->mbuf_dma_tag,
 		    sc->rxring_m_dmamap[sc->rxring_tl_ptr],
 		    BUS_DMASYNC_POSTREAD);
 
 		/* Unload and destroy dmamap. */
 		bus_dmamap_unload(sc->mbuf_dma_tag,
 		    sc->rxring_m_dmamap[sc->rxring_tl_ptr]);
 		bus_dmamap_destroy(sc->mbuf_dma_tag,
 		    sc->rxring_m_dmamap[sc->rxring_tl_ptr]);
 		sc->rxring_m_dmamap[sc->rxring_tl_ptr] = NULL;
 
 		/* Increment tail pointer. */
 		if (++sc->rxring_tl_ptr == CGEM_NUM_RX_DESCS)
 			sc->rxring_tl_ptr = 0;
 		sc->rxring_queued--;
 
 		/*
 		 * Check FCS and make sure entire packet landed in one mbuf
 		 * cluster (which is much bigger than the largest ethernet
 		 * packet).
 		 */
 		if ((ctl & CGEM_RXDESC_BAD_FCS) != 0 ||
 		    (ctl & (CGEM_RXDESC_SOF | CGEM_RXDESC_EOF)) !=
 		    (CGEM_RXDESC_SOF | CGEM_RXDESC_EOF)) {
 			/* discard. */
 			m_free(m);
 			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 			continue;
 		}
 
 		/* Ready it to hand off to upper layers. */
 		m->m_data += ETHER_ALIGN;
 		m->m_len = (ctl & CGEM_RXDESC_LENGTH_MASK);
 		m->m_pkthdr.rcvif = ifp;
 		m->m_pkthdr.len = m->m_len;
 
 		/*
 		 * Are we using hardware checksumming?  Check the status in the
 		 * receive descriptor.
 		 */
 		if ((if_getcapenable(ifp) & IFCAP_RXCSUM) != 0) {
 			/* TCP or UDP checks out, IP checks out too. */
 			if ((ctl & CGEM_RXDESC_CKSUM_STAT_MASK) ==
 			    CGEM_RXDESC_CKSUM_STAT_TCP_GOOD ||
 			    (ctl & CGEM_RXDESC_CKSUM_STAT_MASK) ==
 			    CGEM_RXDESC_CKSUM_STAT_UDP_GOOD) {
 				m->m_pkthdr.csum_flags |=
 				    CSUM_IP_CHECKED | CSUM_IP_VALID |
 				    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
 				m->m_pkthdr.csum_data = 0xffff;
 			} else if ((ctl & CGEM_RXDESC_CKSUM_STAT_MASK) ==
 			    CGEM_RXDESC_CKSUM_STAT_IP_GOOD) {
 				/* Only IP checks out. */
 				m->m_pkthdr.csum_flags |=
 				    CSUM_IP_CHECKED | CSUM_IP_VALID;
 				m->m_pkthdr.csum_data = 0xffff;
 			}
 		}
 
 		/* Queue it up for delivery below. */
 		*m_tl = m;
 		m_tl = &m->m_next;
 	}
 
 	/* Replenish receive buffers. */
 	cgem_fill_rqueue(sc);
 
 	/* Unlock and send up packets. */
 	CGEM_UNLOCK(sc);
 	while (m_hd != NULL) {
 		m = m_hd;
 		m_hd = m_hd->m_next;
 		m->m_next = NULL;
 		if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
 		if_input(ifp, m);
 	}
 	CGEM_LOCK(sc);
 }
 
 /* Find completed transmits and free their mbufs. */
 static void
 cgem_clean_tx(struct cgem_softc *sc)
 {
 	struct mbuf *m;
 	uint32_t ctl;
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	/* free up finished transmits. */
 	while (sc->txring_queued > 0 &&
 	    ((ctl = sc->txring[sc->txring_tl_ptr].ctl) &
 	    CGEM_TXDESC_USED) != 0) {
 		/* Sync cache. */
 		bus_dmamap_sync(sc->mbuf_dma_tag,
 		    sc->txring_m_dmamap[sc->txring_tl_ptr],
 		    BUS_DMASYNC_POSTWRITE);
 
 		/* Unload and destroy DMA map. */
 		bus_dmamap_unload(sc->mbuf_dma_tag,
 		    sc->txring_m_dmamap[sc->txring_tl_ptr]);
 		bus_dmamap_destroy(sc->mbuf_dma_tag,
 		    sc->txring_m_dmamap[sc->txring_tl_ptr]);
 		sc->txring_m_dmamap[sc->txring_tl_ptr] = NULL;
 
 		/* Free up the mbuf. */
 		m = sc->txring_m[sc->txring_tl_ptr];
 		sc->txring_m[sc->txring_tl_ptr] = NULL;
 		m_freem(m);
 
 		/* Check the status. */
 		if ((ctl & CGEM_TXDESC_AHB_ERR) != 0) {
 			/* Serious bus error. log to console. */
+#ifdef CGEM64
+			device_printf(sc->dev,
+			    "cgem_clean_tx: AHB error, addr=0x%x%08x\n",
+			    sc->txring[sc->txring_tl_ptr].addrhi,
+			    sc->txring[sc->txring_tl_ptr].addr);
+#else
 			device_printf(sc->dev,
 			    "cgem_clean_tx: AHB error, addr=0x%x\n",
 			    sc->txring[sc->txring_tl_ptr].addr);
+#endif
 		} else if ((ctl & (CGEM_TXDESC_RETRY_ERR |
 		    CGEM_TXDESC_LATE_COLL)) != 0) {
 			if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
 		} else
 			if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1);
 
 		/*
 		 * If the packet spanned more than one tx descriptor, skip
-		 * descriptors until we find the end so that only start-of-frame
-		 * descriptors are processed.
+		 * descriptors until we find the end so that only
+		 * start-of-frame descriptors are processed.
 		 */
 		while ((ctl & CGEM_TXDESC_LAST_BUF) == 0) {
 			if ((ctl & CGEM_TXDESC_WRAP) != 0)
 				sc->txring_tl_ptr = 0;
 			else
 				sc->txring_tl_ptr++;
 			sc->txring_queued--;
 
 			ctl = sc->txring[sc->txring_tl_ptr].ctl;
 
 			sc->txring[sc->txring_tl_ptr].ctl =
 			    ctl | CGEM_TXDESC_USED;
 		}
 
 		/* Next descriptor. */
 		if ((ctl & CGEM_TXDESC_WRAP) != 0)
 			sc->txring_tl_ptr = 0;
 		else
 			sc->txring_tl_ptr++;
 		sc->txring_queued--;
 
 		if_setdrvflagbits(sc->ifp, 0, IFF_DRV_OACTIVE);
 	}
 }
 
 /* Start transmits. */
 static void
 cgem_start_locked(if_t ifp)
 {
 	struct cgem_softc *sc = (struct cgem_softc *) if_getsoftc(ifp);
 	struct mbuf *m;
 	bus_dma_segment_t segs[TX_MAX_DMA_SEGS];
 	uint32_t ctl;
 	int i, nsegs, wrap, err;
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	if ((if_getdrvflags(ifp) & IFF_DRV_OACTIVE) != 0)
 		return;
 
 	for (;;) {
 		/* Check that there is room in the descriptor ring. */
 		if (sc->txring_queued >=
 		    CGEM_NUM_TX_DESCS - TX_MAX_DMA_SEGS * 2) {
 			/* Try to make room. */
 			cgem_clean_tx(sc);
 
 			/* Still no room? */
 			if (sc->txring_queued >=
 			    CGEM_NUM_TX_DESCS - TX_MAX_DMA_SEGS * 2) {
 				if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
 				sc->txfull++;
 				break;
 			}
 		}
 
 		/* Grab next transmit packet. */
 		m = if_dequeue(ifp);
 		if (m == NULL)
 			break;
 
 		/* Create and load DMA map. */
 		if (bus_dmamap_create(sc->mbuf_dma_tag, 0,
 			&sc->txring_m_dmamap[sc->txring_hd_ptr])) {
 			m_freem(m);
 			sc->txdmamapfails++;
 			continue;
 		}
 		err = bus_dmamap_load_mbuf_sg(sc->mbuf_dma_tag,
 		    sc->txring_m_dmamap[sc->txring_hd_ptr], m, segs, &nsegs,
 		    BUS_DMA_NOWAIT);
 		if (err == EFBIG) {
 			/* Too many segments!  defrag and try again. */
 			struct mbuf *m2 = m_defrag(m, M_NOWAIT);
 
 			if (m2 == NULL) {
 				sc->txdefragfails++;
 				m_freem(m);
 				bus_dmamap_destroy(sc->mbuf_dma_tag,
 				    sc->txring_m_dmamap[sc->txring_hd_ptr]);
 				sc->txring_m_dmamap[sc->txring_hd_ptr] = NULL;
 				continue;
 			}
 			m = m2;
 			err = bus_dmamap_load_mbuf_sg(sc->mbuf_dma_tag,
 			    sc->txring_m_dmamap[sc->txring_hd_ptr], m, segs,
 			    &nsegs, BUS_DMA_NOWAIT);
 			sc->txdefrags++;
 		}
 		if (err) {
 			/* Give up. */
 			m_freem(m);
 			bus_dmamap_destroy(sc->mbuf_dma_tag,
 			    sc->txring_m_dmamap[sc->txring_hd_ptr]);
 			sc->txring_m_dmamap[sc->txring_hd_ptr] = NULL;
 			sc->txdmamapfails++;
 			continue;
 		}
 		sc->txring_m[sc->txring_hd_ptr] = m;
 
 		/* Sync tx buffer with cache. */
 		bus_dmamap_sync(sc->mbuf_dma_tag,
 		    sc->txring_m_dmamap[sc->txring_hd_ptr],
 		    BUS_DMASYNC_PREWRITE);
 
 		/* Set wrap flag if next packet might run off end of ring. */
 		wrap = sc->txring_hd_ptr + nsegs + TX_MAX_DMA_SEGS >=
 		    CGEM_NUM_TX_DESCS;
 
 		/*
 		 * Fill in the TX descriptors back to front so that USED bit in
 		 * first descriptor is cleared last.
 		 */
 		for (i = nsegs - 1; i >= 0; i--) {
 			/* Descriptor address. */
 			sc->txring[sc->txring_hd_ptr + i].addr =
 			    segs[i].ds_addr;
-
+#ifdef CGEM64
+			sc->txring[sc->txring_hd_ptr + i].addrhi =
+			    segs[i].ds_addr >> 32;
+#endif
 			/* Descriptor control word. */
 			ctl = segs[i].ds_len;
 			if (i == nsegs - 1) {
 				ctl |= CGEM_TXDESC_LAST_BUF;
 				if (wrap)
 					ctl |= CGEM_TXDESC_WRAP;
 			}
 			sc->txring[sc->txring_hd_ptr + i].ctl = ctl;
 
 			if (i != 0)
 				sc->txring_m[sc->txring_hd_ptr + i] = NULL;
 		}
 
 		if (wrap)
 			sc->txring_hd_ptr = 0;
 		else
 			sc->txring_hd_ptr += nsegs;
 		sc->txring_queued += nsegs;
 
 		/* Kick the transmitter. */
 		WR4(sc, CGEM_NET_CTRL, sc->net_ctl_shadow |
 		    CGEM_NET_CTRL_START_TX);
 
 		/* If there is a BPF listener, bounce a copy to him. */
 		ETHER_BPF_MTAP(ifp, m);
 	}
 }
 
 static void
 cgem_start(if_t ifp)
 {
 	struct cgem_softc *sc = (struct cgem_softc *) if_getsoftc(ifp);
 
 	CGEM_LOCK(sc);
 	cgem_start_locked(ifp);
 	CGEM_UNLOCK(sc);
 }
 
 static void
 cgem_poll_hw_stats(struct cgem_softc *sc)
 {
 	uint32_t n;
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	sc->stats.tx_bytes += RD4(sc, CGEM_OCTETS_TX_BOT);
 	sc->stats.tx_bytes += (uint64_t)RD4(sc, CGEM_OCTETS_TX_TOP) << 32;
 
 	sc->stats.tx_frames += RD4(sc, CGEM_FRAMES_TX);
 	sc->stats.tx_frames_bcast += RD4(sc, CGEM_BCAST_FRAMES_TX);
 	sc->stats.tx_frames_multi += RD4(sc, CGEM_MULTI_FRAMES_TX);
 	sc->stats.tx_frames_pause += RD4(sc, CGEM_PAUSE_FRAMES_TX);
 	sc->stats.tx_frames_64b += RD4(sc, CGEM_FRAMES_64B_TX);
 	sc->stats.tx_frames_65to127b += RD4(sc, CGEM_FRAMES_65_127B_TX);
 	sc->stats.tx_frames_128to255b += RD4(sc, CGEM_FRAMES_128_255B_TX);
 	sc->stats.tx_frames_256to511b += RD4(sc, CGEM_FRAMES_256_511B_TX);
 	sc->stats.tx_frames_512to1023b += RD4(sc, CGEM_FRAMES_512_1023B_TX);
 	sc->stats.tx_frames_1024to1536b += RD4(sc, CGEM_FRAMES_1024_1518B_TX);
 	sc->stats.tx_under_runs += RD4(sc, CGEM_TX_UNDERRUNS);
 
 	n = RD4(sc, CGEM_SINGLE_COLL_FRAMES);
 	sc->stats.tx_single_collisn += n;
 	if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, n);
 	n = RD4(sc, CGEM_MULTI_COLL_FRAMES);
 	sc->stats.tx_multi_collisn += n;
 	if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, n);
 	n = RD4(sc, CGEM_EXCESSIVE_COLL_FRAMES);
 	sc->stats.tx_excsv_collisn += n;
 	if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, n);
 	n = RD4(sc, CGEM_LATE_COLL);
 	sc->stats.tx_late_collisn += n;
 	if_inc_counter(sc->ifp, IFCOUNTER_COLLISIONS, n);
 
 	sc->stats.tx_deferred_frames += RD4(sc, CGEM_DEFERRED_TX_FRAMES);
 	sc->stats.tx_carrier_sense_errs += RD4(sc, CGEM_CARRIER_SENSE_ERRS);
 
 	sc->stats.rx_bytes += RD4(sc, CGEM_OCTETS_RX_BOT);
 	sc->stats.rx_bytes += (uint64_t)RD4(sc, CGEM_OCTETS_RX_TOP) << 32;
 
 	sc->stats.rx_frames += RD4(sc, CGEM_FRAMES_RX);
 	sc->stats.rx_frames_bcast += RD4(sc, CGEM_BCAST_FRAMES_RX);
 	sc->stats.rx_frames_multi += RD4(sc, CGEM_MULTI_FRAMES_RX);
 	sc->stats.rx_frames_pause += RD4(sc, CGEM_PAUSE_FRAMES_RX);
 	sc->stats.rx_frames_64b += RD4(sc, CGEM_FRAMES_64B_RX);
 	sc->stats.rx_frames_65to127b += RD4(sc, CGEM_FRAMES_65_127B_RX);
 	sc->stats.rx_frames_128to255b += RD4(sc, CGEM_FRAMES_128_255B_RX);
 	sc->stats.rx_frames_256to511b += RD4(sc, CGEM_FRAMES_256_511B_RX);
 	sc->stats.rx_frames_512to1023b += RD4(sc, CGEM_FRAMES_512_1023B_RX);
 	sc->stats.rx_frames_1024to1536b += RD4(sc, CGEM_FRAMES_1024_1518B_RX);
 	sc->stats.rx_frames_undersize += RD4(sc, CGEM_UNDERSZ_RX);
 	sc->stats.rx_frames_oversize += RD4(sc, CGEM_OVERSZ_RX);
 	sc->stats.rx_frames_jabber += RD4(sc, CGEM_JABBERS_RX);
 	sc->stats.rx_frames_fcs_errs += RD4(sc, CGEM_FCS_ERRS);
 	sc->stats.rx_frames_length_errs += RD4(sc, CGEM_LENGTH_FIELD_ERRS);
 	sc->stats.rx_symbol_errs += RD4(sc, CGEM_RX_SYMBOL_ERRS);
 	sc->stats.rx_align_errs += RD4(sc, CGEM_ALIGN_ERRS);
 	sc->stats.rx_resource_errs += RD4(sc, CGEM_RX_RESOURCE_ERRS);
 	sc->stats.rx_overrun_errs += RD4(sc, CGEM_RX_OVERRUN_ERRS);
 	sc->stats.rx_ip_hdr_csum_errs += RD4(sc, CGEM_IP_HDR_CKSUM_ERRS);
 	sc->stats.rx_tcp_csum_errs += RD4(sc, CGEM_TCP_CKSUM_ERRS);
 	sc->stats.rx_udp_csum_errs += RD4(sc, CGEM_UDP_CKSUM_ERRS);
 }
 
 static void
 cgem_tick(void *arg)
 {
 	struct cgem_softc *sc = (struct cgem_softc *)arg;
 	struct mii_data *mii;
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	/* Poll the phy. */
 	if (sc->miibus != NULL) {
 		mii = device_get_softc(sc->miibus);
 		mii_tick(mii);
 	}
 
 	/* Poll statistics registers. */
 	cgem_poll_hw_stats(sc);
 
 	/* Check for receiver hang. */
 	if (sc->rxhangwar && sc->rx_frames_prev == sc->stats.rx_frames) {
 		/*
 		 * Reset receiver logic by toggling RX_EN bit.  1usec
 		 * delay is necessary especially when operating at 100mbps
 		 * and 10mbps speeds.
 		 */
 		WR4(sc, CGEM_NET_CTRL, sc->net_ctl_shadow &
 		    ~CGEM_NET_CTRL_RX_EN);
 		DELAY(1);
 		WR4(sc, CGEM_NET_CTRL, sc->net_ctl_shadow);
 	}
 	sc->rx_frames_prev = sc->stats.rx_frames;
 
 	/* Next callout in one second. */
 	callout_reset(&sc->tick_ch, hz, cgem_tick, sc);
 }
 
 /* Interrupt handler. */
 static void
 cgem_intr(void *arg)
 {
 	struct cgem_softc *sc = (struct cgem_softc *)arg;
 	if_t ifp = sc->ifp;
 	uint32_t istatus;
 
 	CGEM_LOCK(sc);
 
 	if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) {
 		CGEM_UNLOCK(sc);
 		return;
 	}
 
 	/* Read interrupt status and immediately clear the bits. */
 	istatus = RD4(sc, CGEM_INTR_STAT);
 	WR4(sc, CGEM_INTR_STAT, istatus);
 
 	/* Packets received. */
 	if ((istatus & CGEM_INTR_RX_COMPLETE) != 0)
 		cgem_recv(sc);
 
 	/* Free up any completed transmit buffers. */
 	cgem_clean_tx(sc);
 
 	/* Hresp not ok.  Something is very bad with DMA.  Try to clear. */
 	if ((istatus & CGEM_INTR_HRESP_NOT_OK) != 0) {
 		device_printf(sc->dev,
 		    "cgem_intr: hresp not okay! rx_status=0x%x\n",
 		    RD4(sc, CGEM_RX_STAT));
 		WR4(sc, CGEM_RX_STAT, CGEM_RX_STAT_HRESP_NOT_OK);
 	}
 
 	/* Receiver overrun. */
 	if ((istatus & CGEM_INTR_RX_OVERRUN) != 0) {
 		/* Clear status bit. */
 		WR4(sc, CGEM_RX_STAT, CGEM_RX_STAT_OVERRUN);
 		sc->rxoverruns++;
 	}
 
 	/* Receiver ran out of bufs. */
 	if ((istatus & CGEM_INTR_RX_USED_READ) != 0) {
 		WR4(sc, CGEM_NET_CTRL, sc->net_ctl_shadow |
 		    CGEM_NET_CTRL_FLUSH_DPRAM_PKT);
 		cgem_fill_rqueue(sc);
 		sc->rxnobufs++;
 	}
 
 	/* Restart transmitter if needed. */
 	if (!if_sendq_empty(ifp))
 		cgem_start_locked(ifp);
 
 	CGEM_UNLOCK(sc);
 }
 
 /* Reset hardware. */
 static void
 cgem_reset(struct cgem_softc *sc)
 {
 
 	CGEM_ASSERT_LOCKED(sc);
 
+	/* Determine data bus width from design configuration register. */
+	switch (RD4(sc, CGEM_DESIGN_CFG1) &
+	    CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_MASK) {
+	case CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_64:
+		sc->net_cfg_shadow = CGEM_NET_CFG_DBUS_WIDTH_64;
+		break;
+	case CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_128:
+		sc->net_cfg_shadow = CGEM_NET_CFG_DBUS_WIDTH_128;
+		break;
+	default:
+		sc->net_cfg_shadow = CGEM_NET_CFG_DBUS_WIDTH_32;
+	}
+
 	WR4(sc, CGEM_NET_CTRL, 0);
-	WR4(sc, CGEM_NET_CFG, 0);
+	WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
 	WR4(sc, CGEM_NET_CTRL, CGEM_NET_CTRL_CLR_STAT_REGS);
 	WR4(sc, CGEM_TX_STAT, CGEM_TX_STAT_ALL);
 	WR4(sc, CGEM_RX_STAT, CGEM_RX_STAT_ALL);
 	WR4(sc, CGEM_INTR_DIS, CGEM_INTR_ALL);
 	WR4(sc, CGEM_HASH_BOT, 0);
 	WR4(sc, CGEM_HASH_TOP, 0);
 	WR4(sc, CGEM_TX_QBAR, 0);	/* manual says do this. */
 	WR4(sc, CGEM_RX_QBAR, 0);
 
 	/* Get management port running even if interface is down. */
-	WR4(sc, CGEM_NET_CFG, CGEM_NET_CFG_DBUS_WIDTH_32 |
-	    CGEM_NET_CFG_MDC_CLK_DIV_64);
+	sc->net_cfg_shadow |= CGEM_NET_CFG_MDC_CLK_DIV_48;
+	WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
 
 	sc->net_ctl_shadow = CGEM_NET_CTRL_MGMT_PORT_EN;
 	WR4(sc, CGEM_NET_CTRL, sc->net_ctl_shadow);
 }
 
 /* Bring up the hardware. */
 static void
 cgem_config(struct cgem_softc *sc)
 {
 	if_t ifp = sc->ifp;
-	uint32_t net_cfg;
 	uint32_t dma_cfg;
 	u_char *eaddr = if_getlladdr(ifp);
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	/* Program Net Config Register. */
-	net_cfg = CGEM_NET_CFG_DBUS_WIDTH_32 |
-	    CGEM_NET_CFG_MDC_CLK_DIV_64 |
-	    CGEM_NET_CFG_FCS_REMOVE |
+	sc->net_cfg_shadow &= (CGEM_NET_CFG_MDC_CLK_DIV_MASK |
+	    CGEM_NET_CFG_DBUS_WIDTH_MASK);
+	sc->net_cfg_shadow |= (CGEM_NET_CFG_FCS_REMOVE |
 	    CGEM_NET_CFG_RX_BUF_OFFSET(ETHER_ALIGN) |
-	    CGEM_NET_CFG_GIGE_EN |
-	    CGEM_NET_CFG_1536RXEN |
-	    CGEM_NET_CFG_FULL_DUPLEX |
-	    CGEM_NET_CFG_SPEED100;
+	    CGEM_NET_CFG_GIGE_EN | CGEM_NET_CFG_1536RXEN |
+	    CGEM_NET_CFG_FULL_DUPLEX | CGEM_NET_CFG_SPEED100);
 
 	/* Enable receive checksum offloading? */
 	if ((if_getcapenable(ifp) & IFCAP_RXCSUM) != 0)
-		net_cfg |=  CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN;
+		sc->net_cfg_shadow |=  CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN;
 
-	WR4(sc, CGEM_NET_CFG, net_cfg);
+	WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
 
 	/* Program DMA Config Register. */
 	dma_cfg = CGEM_DMA_CFG_RX_BUF_SIZE(MCLBYTES) |
 	    CGEM_DMA_CFG_RX_PKTBUF_MEMSZ_SEL_8K |
 	    CGEM_DMA_CFG_TX_PKTBUF_MEMSZ_SEL |
 	    CGEM_DMA_CFG_AHB_FIXED_BURST_LEN_16 |
+#ifdef CGEM64
+	    CGEM_DMA_CFG_ADDR_BUS_64 |
+#endif
 	    CGEM_DMA_CFG_DISC_WHEN_NO_AHB;
 
 	/* Enable transmit checksum offloading? */
 	if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0)
 		dma_cfg |= CGEM_DMA_CFG_CHKSUM_GEN_OFFLOAD_EN;
 
 	WR4(sc, CGEM_DMA_CFG, dma_cfg);
 
 	/* Write the rx and tx descriptor ring addresses to the QBAR regs. */
-	WR4(sc, CGEM_RX_QBAR, (uint32_t) sc->rxring_physaddr);
-	WR4(sc, CGEM_TX_QBAR, (uint32_t) sc->txring_physaddr);
+	WR4(sc, CGEM_RX_QBAR, (uint32_t)sc->rxring_physaddr);
+	WR4(sc, CGEM_TX_QBAR, (uint32_t)sc->txring_physaddr);
+#ifdef CGEM64
+	WR4(sc, CGEM_RX_QBAR_HI, (uint32_t)(sc->rxring_physaddr >> 32));
+	WR4(sc, CGEM_TX_QBAR_HI, (uint32_t)(sc->txring_physaddr >> 32));
+#endif
 
 	/* Enable rx and tx. */
 	sc->net_ctl_shadow |= (CGEM_NET_CTRL_TX_EN | CGEM_NET_CTRL_RX_EN);
 	WR4(sc, CGEM_NET_CTRL, sc->net_ctl_shadow);
 
 	/* Set receive address in case it changed. */
 	WR4(sc, CGEM_SPEC_ADDR_LOW(0), (eaddr[3] << 24) |
 	    (eaddr[2] << 16) | (eaddr[1] << 8) | eaddr[0]);
 	WR4(sc, CGEM_SPEC_ADDR_HI(0), (eaddr[5] << 8) | eaddr[4]);
 
 	/* Set up interrupts. */
 	WR4(sc, CGEM_INTR_EN, CGEM_INTR_RX_COMPLETE | CGEM_INTR_RX_OVERRUN |
 	    CGEM_INTR_TX_USED_READ | CGEM_INTR_RX_USED_READ |
 	    CGEM_INTR_HRESP_NOT_OK);
 }
 
 /* Turn on interface and load up receive ring with buffers. */
 static void
 cgem_init_locked(struct cgem_softc *sc)
 {
 	struct mii_data *mii;
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	if ((if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING) != 0)
 		return;
 
 	cgem_config(sc);
 	cgem_fill_rqueue(sc);
 
 	if_setdrvflagbits(sc->ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE);
 
-	mii = device_get_softc(sc->miibus);
-	mii_mediachg(mii);
+	if (sc->miibus != NULL) {
+		mii = device_get_softc(sc->miibus);
+		mii_mediachg(mii);
+	}
 
 	callout_reset(&sc->tick_ch, hz, cgem_tick, sc);
 }
 
 static void
 cgem_init(void *arg)
 {
 	struct cgem_softc *sc = (struct cgem_softc *)arg;
 
 	CGEM_LOCK(sc);
 	cgem_init_locked(sc);
 	CGEM_UNLOCK(sc);
 }
 
 /* Turn off interface.  Free up any buffers in transmit or receive queues. */
 static void
 cgem_stop(struct cgem_softc *sc)
 {
 	int i;
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	callout_stop(&sc->tick_ch);
 
 	/* Shut down hardware. */
 	cgem_reset(sc);
 
 	/* Clear out transmit queue. */
+	memset(sc->txring, 0, CGEM_NUM_TX_DESCS * sizeof(struct cgem_tx_desc));
 	for (i = 0; i < CGEM_NUM_TX_DESCS; i++) {
 		sc->txring[i].ctl = CGEM_TXDESC_USED;
-		sc->txring[i].addr = 0;
 		if (sc->txring_m[i]) {
 			/* Unload and destroy dmamap. */
 			bus_dmamap_unload(sc->mbuf_dma_tag,
 			    sc->txring_m_dmamap[i]);
 			bus_dmamap_destroy(sc->mbuf_dma_tag,
 			    sc->txring_m_dmamap[i]);
 			sc->txring_m_dmamap[i] = NULL;
 			m_freem(sc->txring_m[i]);
 			sc->txring_m[i] = NULL;
 		}
 	}
 	sc->txring[CGEM_NUM_TX_DESCS - 1].ctl |= CGEM_TXDESC_WRAP;
 
 	sc->txring_hd_ptr = 0;
 	sc->txring_tl_ptr = 0;
 	sc->txring_queued = 0;
 
 	/* Clear out receive queue. */
+	memset(sc->rxring, 0, CGEM_NUM_RX_DESCS * sizeof(struct cgem_rx_desc));
 	for (i = 0; i < CGEM_NUM_RX_DESCS; i++) {
 		sc->rxring[i].addr = CGEM_RXDESC_OWN;
-		sc->rxring[i].ctl = 0;
 		if (sc->rxring_m[i]) {
 			/* Unload and destroy dmamap. */
 			bus_dmamap_unload(sc->mbuf_dma_tag,
 			    sc->rxring_m_dmamap[i]);
 			bus_dmamap_destroy(sc->mbuf_dma_tag,
 			    sc->rxring_m_dmamap[i]);
 			sc->rxring_m_dmamap[i] = NULL;
 
 			m_freem(sc->rxring_m[i]);
 			sc->rxring_m[i] = NULL;
 		}
 	}
 	sc->rxring[CGEM_NUM_RX_DESCS - 1].addr |= CGEM_RXDESC_WRAP;
 
 	sc->rxring_hd_ptr = 0;
 	sc->rxring_tl_ptr = 0;
 	sc->rxring_queued = 0;
 
 	/* Force next statchg or linkchg to program net config register. */
 	sc->mii_media_active = 0;
 }
 
 static int
 cgem_ioctl(if_t ifp, u_long cmd, caddr_t data)
 {
 	struct cgem_softc *sc = if_getsoftc(ifp);
 	struct ifreq *ifr = (struct ifreq *)data;
 	struct mii_data *mii;
 	int error = 0, mask;
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:
 		CGEM_LOCK(sc);
 		if ((if_getflags(ifp) & IFF_UP) != 0) {
 			if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) {
 				if (((if_getflags(ifp) ^ sc->if_old_flags) &
 				    (IFF_PROMISC | IFF_ALLMULTI)) != 0) {
 					cgem_rx_filter(sc);
 				}
 			} else {
 				cgem_init_locked(sc);
 			}
 		} else if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) {
 			if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING);
 			cgem_stop(sc);
 		}
 		sc->if_old_flags = if_getflags(ifp);
 		CGEM_UNLOCK(sc);
 		break;
 
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
 		/* Set up multi-cast filters. */
 		if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) {
 			CGEM_LOCK(sc);
 			cgem_rx_filter(sc);
 			CGEM_UNLOCK(sc);
 		}
 		break;
 
 	case SIOCSIFMEDIA:
 	case SIOCGIFMEDIA:
+		if (sc->miibus == NULL)
+			return (ENXIO);
 		mii = device_get_softc(sc->miibus);
 		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
 		break;
 
 	case SIOCSIFCAP:
 		CGEM_LOCK(sc);
 		mask = if_getcapenable(ifp) ^ ifr->ifr_reqcap;
 
 		if ((mask & IFCAP_TXCSUM) != 0) {
 			if ((ifr->ifr_reqcap & IFCAP_TXCSUM) != 0) {
 				/* Turn on TX checksumming. */
 				if_setcapenablebit(ifp, IFCAP_TXCSUM |
 				    IFCAP_TXCSUM_IPV6, 0);
 				if_sethwassistbits(ifp, CGEM_CKSUM_ASSIST, 0);
 
 				WR4(sc, CGEM_DMA_CFG,
 				    RD4(sc, CGEM_DMA_CFG) |
 				    CGEM_DMA_CFG_CHKSUM_GEN_OFFLOAD_EN);
 			} else {
 				/* Turn off TX checksumming. */
 				if_setcapenablebit(ifp, 0, IFCAP_TXCSUM |
 				    IFCAP_TXCSUM_IPV6);
 				if_sethwassistbits(ifp, 0, CGEM_CKSUM_ASSIST);
 
 				WR4(sc, CGEM_DMA_CFG,
 				    RD4(sc, CGEM_DMA_CFG) &
 				    ~CGEM_DMA_CFG_CHKSUM_GEN_OFFLOAD_EN);
 			}
 		}
 		if ((mask & IFCAP_RXCSUM) != 0) {
 			if ((ifr->ifr_reqcap & IFCAP_RXCSUM) != 0) {
 				/* Turn on RX checksumming. */
 				if_setcapenablebit(ifp, IFCAP_RXCSUM |
 				    IFCAP_RXCSUM_IPV6, 0);
-				WR4(sc, CGEM_NET_CFG,
-				    RD4(sc, CGEM_NET_CFG) |
-				    CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN);
+				sc->net_cfg_shadow |=
+				    CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN;
+				WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
 			} else {
 				/* Turn off RX checksumming. */
 				if_setcapenablebit(ifp, 0, IFCAP_RXCSUM |
 				    IFCAP_RXCSUM_IPV6);
-				WR4(sc, CGEM_NET_CFG,
-				    RD4(sc, CGEM_NET_CFG) &
-				    ~CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN);
+				sc->net_cfg_shadow &=
+				    ~CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN;
+				WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
 			}
 		}
 		if ((if_getcapenable(ifp) & (IFCAP_RXCSUM | IFCAP_TXCSUM)) ==
 		    (IFCAP_RXCSUM | IFCAP_TXCSUM))
 			if_setcapenablebit(ifp, IFCAP_VLAN_HWCSUM, 0);
 		else
 			if_setcapenablebit(ifp, 0, IFCAP_VLAN_HWCSUM);
 
 		CGEM_UNLOCK(sc);
 		break;
 	default:
 		error = ether_ioctl(ifp, cmd, data);
 		break;
 	}
 
 	return (error);
 }
 
 /* MII bus support routines.
  */
-static void
-cgem_child_detached(device_t dev, device_t child)
-{
-	struct cgem_softc *sc = device_get_softc(dev);
-
-	if (child == sc->miibus)
-		sc->miibus = NULL;
-}
-
 static int
 cgem_ifmedia_upd(if_t ifp)
 {
 	struct cgem_softc *sc = (struct cgem_softc *) if_getsoftc(ifp);
 	struct mii_data *mii;
 	struct mii_softc *miisc;
 	int error = 0;
 
 	mii = device_get_softc(sc->miibus);
 	CGEM_LOCK(sc);
 	if ((if_getflags(ifp) & IFF_UP) != 0) {
 		LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
 			PHY_RESET(miisc);
 		error = mii_mediachg(mii);
 	}
 	CGEM_UNLOCK(sc);
 
 	return (error);
 }
 
 static void
 cgem_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr)
 {
 	struct cgem_softc *sc = (struct cgem_softc *) if_getsoftc(ifp);
 	struct mii_data *mii;
 
 	mii = device_get_softc(sc->miibus);
 	CGEM_LOCK(sc);
 	mii_pollstat(mii);
 	ifmr->ifm_active = mii->mii_media_active;
 	ifmr->ifm_status = mii->mii_media_status;
 	CGEM_UNLOCK(sc);
 }
 
 static int
 cgem_miibus_readreg(device_t dev, int phy, int reg)
 {
 	struct cgem_softc *sc = device_get_softc(dev);
 	int tries, val;
 
 	WR4(sc, CGEM_PHY_MAINT, CGEM_PHY_MAINT_CLAUSE_22 |
 	    CGEM_PHY_MAINT_MUST_10 | CGEM_PHY_MAINT_OP_READ |
 	    (phy << CGEM_PHY_MAINT_PHY_ADDR_SHIFT) |
 	    (reg << CGEM_PHY_MAINT_REG_ADDR_SHIFT));
 
 	/* Wait for completion. */
 	tries=0;
 	while ((RD4(sc, CGEM_NET_STAT) & CGEM_NET_STAT_PHY_MGMT_IDLE) == 0) {
 		DELAY(5);
 		if (++tries > 200) {
 			device_printf(dev, "phy read timeout: %d\n", reg);
 			return (-1);
 		}
 	}
 
 	val = RD4(sc, CGEM_PHY_MAINT) & CGEM_PHY_MAINT_DATA_MASK;
 
 	if (reg == MII_EXTSR)
 		/*
 		 * MAC does not support half-duplex at gig speeds.
 		 * Let mii(4) exclude the capability.
 		 */
 		val &= ~(EXTSR_1000XHDX | EXTSR_1000THDX);
 
 	return (val);
 }
 
 static int
 cgem_miibus_writereg(device_t dev, int phy, int reg, int data)
 {
 	struct cgem_softc *sc = device_get_softc(dev);
 	int tries;
 
 	WR4(sc, CGEM_PHY_MAINT, CGEM_PHY_MAINT_CLAUSE_22 |
 	    CGEM_PHY_MAINT_MUST_10 | CGEM_PHY_MAINT_OP_WRITE |
 	    (phy << CGEM_PHY_MAINT_PHY_ADDR_SHIFT) |
 	    (reg << CGEM_PHY_MAINT_REG_ADDR_SHIFT) |
 	    (data & CGEM_PHY_MAINT_DATA_MASK));
 
 	/* Wait for completion. */
 	tries = 0;
 	while ((RD4(sc, CGEM_NET_STAT) & CGEM_NET_STAT_PHY_MGMT_IDLE) == 0) {
 		DELAY(5);
 		if (++tries > 200) {
 			device_printf(dev, "phy write timeout: %d\n", reg);
 			return (-1);
 		}
 	}
 
 	return (0);
 }
 
 static void
 cgem_miibus_statchg(device_t dev)
 {
 	struct cgem_softc *sc  = device_get_softc(dev);
 	struct mii_data *mii = device_get_softc(sc->miibus);
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
 	    (IFM_ACTIVE | IFM_AVALID) &&
 	    sc->mii_media_active != mii->mii_media_active)
 		cgem_mediachange(sc, mii);
 }
 
 static void
 cgem_miibus_linkchg(device_t dev)
 {
 	struct cgem_softc *sc  = device_get_softc(dev);
 	struct mii_data *mii = device_get_softc(sc->miibus);
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
 	    (IFM_ACTIVE | IFM_AVALID) &&
 	    sc->mii_media_active != mii->mii_media_active)
 		cgem_mediachange(sc, mii);
 }
 
 /*
  * Overridable weak symbol cgem_set_ref_clk().  This allows platforms to
  * provide a function to set the cgem's reference clock.
  */
 static int __used
 cgem_default_set_ref_clk(int unit, int frequency)
 {
 
 	return 0;
 }
 __weak_reference(cgem_default_set_ref_clk, cgem_set_ref_clk);
 
 /* Call to set reference clock and network config bits according to media. */
 static void
 cgem_mediachange(struct cgem_softc *sc,	struct mii_data *mii)
 {
-	uint32_t net_cfg;
 	int ref_clk_freq;
 
 	CGEM_ASSERT_LOCKED(sc);
 
 	/* Update hardware to reflect media. */
-	net_cfg = RD4(sc, CGEM_NET_CFG);
-	net_cfg &= ~(CGEM_NET_CFG_SPEED100 | CGEM_NET_CFG_GIGE_EN |
+	sc->net_cfg_shadow &= ~(CGEM_NET_CFG_SPEED100 | CGEM_NET_CFG_GIGE_EN |
 	    CGEM_NET_CFG_FULL_DUPLEX);
 
 	switch (IFM_SUBTYPE(mii->mii_media_active)) {
 	case IFM_1000_T:
-		net_cfg |= (CGEM_NET_CFG_SPEED100 |
+		sc->net_cfg_shadow |= (CGEM_NET_CFG_SPEED100 |
 		    CGEM_NET_CFG_GIGE_EN);
 		ref_clk_freq = 125000000;
 		break;
 	case IFM_100_TX:
-		net_cfg |= CGEM_NET_CFG_SPEED100;
+		sc->net_cfg_shadow |= CGEM_NET_CFG_SPEED100;
 		ref_clk_freq = 25000000;
 		break;
 	default:
 		ref_clk_freq = 2500000;
 	}
 
 	if ((mii->mii_media_active & IFM_FDX) != 0)
-		net_cfg |= CGEM_NET_CFG_FULL_DUPLEX;
+		sc->net_cfg_shadow |= CGEM_NET_CFG_FULL_DUPLEX;
 
-	WR4(sc, CGEM_NET_CFG, net_cfg);
+	WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
 
+#ifdef EXT_RESOURCES
+	if (sc->ref_clk != NULL) {
+		CGEM_UNLOCK(sc);
+		if (clk_set_freq(sc->ref_clk, ref_clk_freq, 0))
+			device_printf(sc->dev, "could not set ref clk to %d\n",
+			    ref_clk_freq);
+		CGEM_LOCK(sc);
+	}
+#else
 	/* Set the reference clock if necessary. */
 	if (cgem_set_ref_clk(sc->ref_clk_num, ref_clk_freq))
 		device_printf(sc->dev,
 		    "cgem_mediachange: could not set ref clk%d to %d.\n",
 		    sc->ref_clk_num, ref_clk_freq);
+#endif
 
 	sc->mii_media_active = mii->mii_media_active;
 }
 
 static void
 cgem_add_sysctls(device_t dev)
 {
 	struct cgem_softc *sc = device_get_softc(dev);
 	struct sysctl_ctx_list *ctx;
 	struct sysctl_oid_list *child;
 	struct sysctl_oid *tree;
 
 	ctx = device_get_sysctl_ctx(dev);
 	child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
 
 	SYSCTL_ADD_INT(ctx, child, OID_AUTO, "rxbufs", CTLFLAG_RW,
 	    &sc->rxbufs, 0, "Number receive buffers to provide");
 
 	SYSCTL_ADD_INT(ctx, child, OID_AUTO, "rxhangwar", CTLFLAG_RW,
 	    &sc->rxhangwar, 0, "Enable receive hang work-around");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "_rxoverruns", CTLFLAG_RD,
 	    &sc->rxoverruns, 0, "Receive overrun events");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "_rxnobufs", CTLFLAG_RD,
 	    &sc->rxnobufs, 0, "Receive buf queue empty events");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "_rxdmamapfails", CTLFLAG_RD,
 	    &sc->rxdmamapfails, 0, "Receive DMA map failures");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "_txfull", CTLFLAG_RD,
 	    &sc->txfull, 0, "Transmit ring full events");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "_txdmamapfails", CTLFLAG_RD,
 	    &sc->txdmamapfails, 0, "Transmit DMA map failures");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "_txdefrags", CTLFLAG_RD,
 	    &sc->txdefrags, 0, "Transmit m_defrag() calls");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "_txdefragfails", CTLFLAG_RD,
 	    &sc->txdefragfails, 0, "Transmit m_defrag() failures");
 
 	tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats",
 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "GEM statistics");
 	child = SYSCTL_CHILDREN(tree);
 
 	SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_bytes", CTLFLAG_RD,
 	    &sc->stats.tx_bytes, "Total bytes transmitted");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames", CTLFLAG_RD,
 	    &sc->stats.tx_frames, 0, "Total frames transmitted");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames_bcast", CTLFLAG_RD,
 	    &sc->stats.tx_frames_bcast, 0,
 	    "Number broadcast frames transmitted");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames_multi", CTLFLAG_RD,
 	    &sc->stats.tx_frames_multi, 0,
 	    "Number multicast frames transmitted");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames_pause",
 	    CTLFLAG_RD, &sc->stats.tx_frames_pause, 0,
 	    "Number pause frames transmitted");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames_64b", CTLFLAG_RD,
 	    &sc->stats.tx_frames_64b, 0,
 	    "Number frames transmitted of size 64 bytes or less");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames_65to127b", CTLFLAG_RD,
 	    &sc->stats.tx_frames_65to127b, 0,
 	    "Number frames transmitted of size 65-127 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames_128to255b",
 	    CTLFLAG_RD, &sc->stats.tx_frames_128to255b, 0,
 	    "Number frames transmitted of size 128-255 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames_256to511b",
 	    CTLFLAG_RD, &sc->stats.tx_frames_256to511b, 0,
 	    "Number frames transmitted of size 256-511 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames_512to1023b",
 	    CTLFLAG_RD, &sc->stats.tx_frames_512to1023b, 0,
 	    "Number frames transmitted of size 512-1023 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_frames_1024to1536b",
 	    CTLFLAG_RD, &sc->stats.tx_frames_1024to1536b, 0,
 	    "Number frames transmitted of size 1024-1536 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_under_runs",
 	    CTLFLAG_RD, &sc->stats.tx_under_runs, 0,
 	    "Number transmit under-run events");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_single_collisn",
 	    CTLFLAG_RD, &sc->stats.tx_single_collisn, 0,
 	    "Number single-collision transmit frames");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_multi_collisn",
 	    CTLFLAG_RD, &sc->stats.tx_multi_collisn, 0,
 	    "Number multi-collision transmit frames");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_excsv_collisn",
 	    CTLFLAG_RD, &sc->stats.tx_excsv_collisn, 0,
 	    "Number excessive collision transmit frames");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_late_collisn",
 	    CTLFLAG_RD, &sc->stats.tx_late_collisn, 0,
 	    "Number late-collision transmit frames");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_deferred_frames",
 	    CTLFLAG_RD, &sc->stats.tx_deferred_frames, 0,
 	    "Number deferred transmit frames");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_carrier_sense_errs",
 	    CTLFLAG_RD, &sc->stats.tx_carrier_sense_errs, 0,
 	    "Number carrier sense errors on transmit");
 
 	SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_bytes", CTLFLAG_RD,
 	    &sc->stats.rx_bytes, "Total bytes received");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames", CTLFLAG_RD,
 	    &sc->stats.rx_frames, 0, "Total frames received");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_bcast",
 	    CTLFLAG_RD, &sc->stats.rx_frames_bcast, 0,
 	    "Number broadcast frames received");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_multi",
 	    CTLFLAG_RD, &sc->stats.rx_frames_multi, 0,
 	    "Number multicast frames received");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_pause",
 	    CTLFLAG_RD, &sc->stats.rx_frames_pause, 0,
 	    "Number pause frames received");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_64b",
 	    CTLFLAG_RD, &sc->stats.rx_frames_64b, 0,
 	    "Number frames received of size 64 bytes or less");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_65to127b",
 	    CTLFLAG_RD, &sc->stats.rx_frames_65to127b, 0,
 	    "Number frames received of size 65-127 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_128to255b",
 	    CTLFLAG_RD, &sc->stats.rx_frames_128to255b, 0,
 	    "Number frames received of size 128-255 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_256to511b",
 	    CTLFLAG_RD, &sc->stats.rx_frames_256to511b, 0,
 	    "Number frames received of size 256-511 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_512to1023b",
 	    CTLFLAG_RD, &sc->stats.rx_frames_512to1023b, 0,
 	    "Number frames received of size 512-1023 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_1024to1536b",
 	    CTLFLAG_RD, &sc->stats.rx_frames_1024to1536b, 0,
 	    "Number frames received of size 1024-1536 bytes");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_undersize",
 	    CTLFLAG_RD, &sc->stats.rx_frames_undersize, 0,
 	    "Number undersize frames received");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_oversize",
 	    CTLFLAG_RD, &sc->stats.rx_frames_oversize, 0,
 	    "Number oversize frames received");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_jabber",
 	    CTLFLAG_RD, &sc->stats.rx_frames_jabber, 0,
 	    "Number jabber frames received");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_fcs_errs",
 	    CTLFLAG_RD, &sc->stats.rx_frames_fcs_errs, 0,
 	    "Number frames received with FCS errors");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_length_errs",
 	    CTLFLAG_RD, &sc->stats.rx_frames_length_errs, 0,
 	    "Number frames received with length errors");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_symbol_errs",
 	    CTLFLAG_RD, &sc->stats.rx_symbol_errs, 0,
 	    "Number receive symbol errors");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_align_errs",
 	    CTLFLAG_RD, &sc->stats.rx_align_errs, 0,
 	    "Number receive alignment errors");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_resource_errs",
 	    CTLFLAG_RD, &sc->stats.rx_resource_errs, 0,
 	    "Number frames received when no rx buffer available");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_overrun_errs",
 	    CTLFLAG_RD, &sc->stats.rx_overrun_errs, 0,
 	    "Number frames received but not copied due to receive overrun");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_ip_hdr_csum_errs",
 	    CTLFLAG_RD, &sc->stats.rx_ip_hdr_csum_errs, 0,
 	    "Number frames received with IP header checksum errors");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_tcp_csum_errs",
 	    CTLFLAG_RD, &sc->stats.rx_tcp_csum_errs, 0,
 	    "Number frames received with TCP checksum errors");
 
 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_frames_udp_csum_errs",
 	    CTLFLAG_RD, &sc->stats.rx_udp_csum_errs, 0,
 	    "Number frames received with UDP checksum errors");
 }
 
 static int
 cgem_probe(device_t dev)
 {
 
 	if (!ofw_bus_status_okay(dev))
 		return (ENXIO);
 
 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
 		return (ENXIO);
 
 	device_set_desc(dev, "Cadence CGEM Gigabit Ethernet Interface");
 	return (0);
 }
 
 static int
 cgem_attach(device_t dev)
 {
 	struct cgem_softc *sc = device_get_softc(dev);
 	if_t ifp = NULL;
-	phandle_t node;
-	pcell_t cell;
 	int rid, err;
 	u_char eaddr[ETHER_ADDR_LEN];
+	int hwtype;
+#ifndef EXT_RESOURCES
+	phandle_t node;
+	pcell_t cell;
+#endif
 
 	sc->dev = dev;
 	CGEM_LOCK_INIT(sc);
 
+	/* Key off of compatible string and set hardware-specific options. */
+	hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+	if (hwtype == HWTYPE_ZYNQMP)
+		sc->neednullqs = 1;
+	if (hwtype == HWTYPE_ZYNQ)
+		sc->rxhangwar = 1;
+
+#ifdef EXT_RESOURCES
+	if (hwtype == HWTYPE_ZYNQ || hwtype == HWTYPE_ZYNQMP) {
+		if (clk_get_by_ofw_name(dev, 0, "tx_clk", &sc->ref_clk) != 0)
+			device_printf(dev,
+			    "could not retrieve reference clock.\n");
+		else if (clk_enable(sc->ref_clk) != 0)
+			device_printf(dev, "could not enable clock.\n");
+	}
+	else if (hwtype == HWTYPE_SIFIVE_FU540) {
+		if (clk_get_by_ofw_name(dev, 0, "pclk", &sc->ref_clk) != 0)
+			device_printf(dev,
+			    "could not retrieve reference clock.\n");
+		else if (clk_enable(sc->ref_clk) != 0)
+			device_printf(dev, "could not enable clock.\n");
+	}
+#else
 	/* Get reference clock number and base divider from fdt. */
 	node = ofw_bus_get_node(dev);
 	sc->ref_clk_num = 0;
 	if (OF_getprop(node, "ref-clock-num", &cell, sizeof(cell)) > 0)
 		sc->ref_clk_num = fdt32_to_cpu(cell);
+#endif
 
 	/* Get memory resource. */
 	rid = 0;
 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
 	    RF_ACTIVE);
 	if (sc->mem_res == NULL) {
 		device_printf(dev, "could not allocate memory resources.\n");
 		return (ENOMEM);
 	}
 
 	/* Get IRQ resource. */
 	rid = 0;
-	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+	    RF_ACTIVE);
 	if (sc->irq_res == NULL) {
 		device_printf(dev, "could not allocate interrupt resource.\n");
 		cgem_detach(dev);
 		return (ENOMEM);
 	}
 
 	/* Set up ifnet structure. */
 	ifp = sc->ifp = if_alloc(IFT_ETHER);
 	if (ifp == NULL) {
 		device_printf(dev, "could not allocate ifnet structure\n");
 		cgem_detach(dev);
 		return (ENOMEM);
 	}
 	if_setsoftc(ifp, sc);
 	if_initname(ifp, IF_CGEM_NAME, device_get_unit(dev));
 	if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
 	if_setinitfn(ifp, cgem_init);
 	if_setioctlfn(ifp, cgem_ioctl);
 	if_setstartfn(ifp, cgem_start);
 	if_setcapabilitiesbit(ifp, IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 |
 	    IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM, 0);
 	if_setsendqlen(ifp, CGEM_NUM_TX_DESCS);
 	if_setsendqready(ifp);
 
 	/* Disable hardware checksumming by default. */
 	if_sethwassist(ifp, 0);
 	if_setcapenable(ifp, if_getcapabilities(ifp) &
 	    ~(IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 | IFCAP_VLAN_HWCSUM));
 
 	sc->if_old_flags = if_getflags(ifp);
 	sc->rxbufs = DEFAULT_NUM_RX_BUFS;
-	sc->rxhangwar = 1;
 
 	/* Reset hardware. */
 	CGEM_LOCK(sc);
 	cgem_reset(sc);
 	CGEM_UNLOCK(sc);
 
 	/* Attach phy to mii bus. */
 	err = mii_attach(dev, &sc->miibus, ifp,
 	    cgem_ifmedia_upd, cgem_ifmedia_sts, BMSR_DEFCAPMASK,
 	    MII_PHY_ANY, MII_OFFSET_ANY, 0);
-	if (err) {
-		device_printf(dev, "attaching PHYs failed\n");
-		cgem_detach(dev);
-		return (err);
-	}
+	if (err)
+		device_printf(dev, "warning: attaching PHYs failed\n");
 
 	/* Set up TX and RX descriptor area. */
 	err = cgem_setup_descs(sc);
 	if (err) {
 		device_printf(dev, "could not set up dma mem for descs.\n");
 		cgem_detach(dev);
 		return (ENOMEM);
 	}
 
 	/* Get a MAC address. */
 	cgem_get_mac(sc, eaddr);
 
 	/* Start ticks. */
 	callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0);
 
 	ether_ifattach(ifp, eaddr);
 
 	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE |
 	    INTR_EXCL, NULL, cgem_intr, sc, &sc->intrhand);
 	if (err) {
 		device_printf(dev, "could not set interrupt handler.\n");
 		ether_ifdetach(ifp);
 		cgem_detach(dev);
 		return (err);
 	}
 
 	cgem_add_sysctls(dev);
 
 	return (0);
 }
 
 static int
 cgem_detach(device_t dev)
 {
 	struct cgem_softc *sc = device_get_softc(dev);
 	int i;
 
 	if (sc == NULL)
 		return (ENODEV);
 
 	if (device_is_attached(dev)) {
 		CGEM_LOCK(sc);
 		cgem_stop(sc);
 		CGEM_UNLOCK(sc);
 		callout_drain(&sc->tick_ch);
 		if_setflagbits(sc->ifp, 0, IFF_UP);
 		ether_ifdetach(sc->ifp);
 	}
 
 	if (sc->miibus != NULL) {
 		device_delete_child(dev, sc->miibus);
 		sc->miibus = NULL;
 	}
 
 	/* Release resources. */
 	if (sc->mem_res != NULL) {
 		bus_release_resource(dev, SYS_RES_MEMORY,
 		    rman_get_rid(sc->mem_res), sc->mem_res);
 		sc->mem_res = NULL;
 	}
 	if (sc->irq_res != NULL) {
 		if (sc->intrhand)
 			bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
 		bus_release_resource(dev, SYS_RES_IRQ,
 		    rman_get_rid(sc->irq_res), sc->irq_res);
 		sc->irq_res = NULL;
 	}
 
 	/* Release DMA resources. */
 	if (sc->rxring != NULL) {
 		if (sc->rxring_physaddr != 0) {
 			bus_dmamap_unload(sc->desc_dma_tag,
 			    sc->rxring_dma_map);
 			sc->rxring_physaddr = 0;
+			sc->txring_physaddr = 0;
+			sc->null_qs_physaddr = 0;
 		}
 		bus_dmamem_free(sc->desc_dma_tag, sc->rxring,
 				sc->rxring_dma_map);
 		sc->rxring = NULL;
+		sc->txring = NULL;
+		sc->null_qs = NULL;
+
 		for (i = 0; i < CGEM_NUM_RX_DESCS; i++)
 			if (sc->rxring_m_dmamap[i] != NULL) {
 				bus_dmamap_destroy(sc->mbuf_dma_tag,
 				    sc->rxring_m_dmamap[i]);
 				sc->rxring_m_dmamap[i] = NULL;
 			}
-	}
-	if (sc->txring != NULL) {
-		if (sc->txring_physaddr != 0) {
-			bus_dmamap_unload(sc->desc_dma_tag,
-			    sc->txring_dma_map);
-			sc->txring_physaddr = 0;
-		}
-		bus_dmamem_free(sc->desc_dma_tag, sc->txring,
-				sc->txring_dma_map);
-		sc->txring = NULL;
 		for (i = 0; i < CGEM_NUM_TX_DESCS; i++)
 			if (sc->txring_m_dmamap[i] != NULL) {
 				bus_dmamap_destroy(sc->mbuf_dma_tag,
 				    sc->txring_m_dmamap[i]);
 				sc->txring_m_dmamap[i] = NULL;
 			}
 	}
 	if (sc->desc_dma_tag != NULL) {
 		bus_dma_tag_destroy(sc->desc_dma_tag);
 		sc->desc_dma_tag = NULL;
 	}
 	if (sc->mbuf_dma_tag != NULL) {
 		bus_dma_tag_destroy(sc->mbuf_dma_tag);
 		sc->mbuf_dma_tag = NULL;
 	}
 
+#ifdef EXT_RESOURCES
+	if (sc->ref_clk != NULL) {
+		clk_release(sc->ref_clk);
+		sc->ref_clk = NULL;
+	}
+#endif
+
 	bus_generic_detach(dev);
 
 	CGEM_LOCK_DESTROY(sc);
 
 	return (0);
 }
 
 static device_method_t cgem_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		cgem_probe),
 	DEVMETHOD(device_attach,	cgem_attach),
 	DEVMETHOD(device_detach,	cgem_detach),
 
-	/* Bus interface */
-	DEVMETHOD(bus_child_detached,	cgem_child_detached),
-
 	/* MII interface */
 	DEVMETHOD(miibus_readreg,	cgem_miibus_readreg),
 	DEVMETHOD(miibus_writereg,	cgem_miibus_writereg),
 	DEVMETHOD(miibus_statchg,	cgem_miibus_statchg),
 	DEVMETHOD(miibus_linkchg,	cgem_miibus_linkchg),
 
 	DEVMETHOD_END
 };
 
 static driver_t cgem_driver = {
 	"cgem",
 	cgem_methods,
 	sizeof(struct cgem_softc),
 };
 
 DRIVER_MODULE(cgem, simplebus, cgem_driver, cgem_devclass, NULL, NULL);
 DRIVER_MODULE(miibus, cgem, miibus_driver, miibus_devclass, NULL, NULL);
 MODULE_DEPEND(cgem, miibus, 1, 1, 1);
 MODULE_DEPEND(cgem, ether, 1, 1, 1);
+SIMPLEBUS_PNP_INFO(compat_data);
diff --git a/sys/dev/cadence/if_cgem_hw.h b/sys/dev/cadence/if_cgem_hw.h
index fced73327d91..784b131a885e 100644
--- a/sys/dev/cadence/if_cgem_hw.h
+++ b/sys/dev/cadence/if_cgem_hw.h
@@ -1,384 +1,446 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2012-2013 Thomas Skibo
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $FreeBSD$
  */
 
 /*
  * Hardware and register defines for Cadence GEM Gigabit Ethernet
  * controller such as the one used in Zynq-7000 SoC.
  *
  * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
  * (v1.4) November 16, 2012.  Xilinx doc UG585.  GEM is covered in Ch. 16
  * and register definitions are in appendix B.18.
+ *
+ * Additional Reference: Zynq UltraScale+ Device Register Reference
+ * (UG1087 v1.7 Feb 8,2019):
+ * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
  */
 
 #ifndef _IF_CGEM_HW_H_
 #define _IF_CGEM_HW_H_
 
 /* Cadence GEM hardware register definitions. */
 #define CGEM_NET_CTRL			0x000	/* Network Control */
 #define   CGEM_NET_CTRL_FLUSH_DPRAM_PKT		(1 << 18)
 #define   CGEM_NET_CTRL_TX_PFC_PRI_PAUSE_FRAME	(1 << 17)
 #define   CGEM_NET_CTRL_EN_PFC_PRI_PAUSE_RX	(1 << 16)
 #define   CGEM_NET_CTRL_STORE_RX_TSTAMP		(1 << 15)
 #define   CGEM_NET_CTRL_TX_ZEROQ_PAUSE_FRAME	(1 << 12)
 #define   CGEM_NET_CTRL_TX_PAUSE_FRAME		(1 << 11)
 #define   CGEM_NET_CTRL_TX_HALT			(1 << 10)
 #define   CGEM_NET_CTRL_START_TX		(1 << 9)
 #define   CGEM_NET_CTRL_BACK_PRESSURE		(1 << 8)
 #define   CGEM_NET_CTRL_WREN_STAT_REGS		(1 << 7)
 #define   CGEM_NET_CTRL_INCR_STAT_REGS		(1 << 6)
 #define   CGEM_NET_CTRL_CLR_STAT_REGS		(1 << 5)
 #define   CGEM_NET_CTRL_MGMT_PORT_EN		(1 << 4)
 #define   CGEM_NET_CTRL_TX_EN			(1 << 3)
 #define   CGEM_NET_CTRL_RX_EN			(1 << 2)
 #define   CGEM_NET_CTRL_LOOP_LOCAL		(1 << 1)
 
 #define CGEM_NET_CFG			0x004	/* Netowrk Configuration */
 #define   CGEM_NET_CFG_UNIDIR_EN		(1U << 31)
 #define   CGEM_NET_CFG_IGNORE_IPG_RX_ER		(1 << 30)
 #define   CGEM_NET_CFG_RX_BAD_PREAMBLE		(1 << 29)
 #define   CGEM_NET_CFG_IPG_STRETCH_EN		(1 << 28)
 #define   CGEM_NET_CFG_SGMII_EN			(1 << 27)
 #define   CGEM_NET_CFG_IGNORE_RX_FCS		(1 << 26)
 #define   CGEM_NET_CFG_RX_HD_WHILE_TX		(1 << 25)
 #define   CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN	(1 << 24)
 #define   CGEM_NET_CFG_DIS_CP_PAUSE_FRAME	(1 << 23)
 #define   CGEM_NET_CFG_DBUS_WIDTH_32		(0 << 21)
 #define   CGEM_NET_CFG_DBUS_WIDTH_64		(1 << 21)
 #define   CGEM_NET_CFG_DBUS_WIDTH_128		(2 << 21)
 #define   CGEM_NET_CFG_DBUS_WIDTH_MASK		(3 << 21)
 #define   CGEM_NET_CFG_MDC_CLK_DIV_8		(0 << 18)
 #define   CGEM_NET_CFG_MDC_CLK_DIV_16		(1 << 18)
 #define   CGEM_NET_CFG_MDC_CLK_DIV_32		(2 << 18)
 #define   CGEM_NET_CFG_MDC_CLK_DIV_48		(3 << 18)
 #define   CGEM_NET_CFG_MDC_CLK_DIV_64		(4 << 18)
 #define   CGEM_NET_CFG_MDC_CLK_DIV_96		(5 << 18)
 #define   CGEM_NET_CFG_MDC_CLK_DIV_128		(6 << 18)
 #define   CGEM_NET_CFG_MDC_CLK_DIV_224		(7 << 18)
 #define   CGEM_NET_CFG_MDC_CLK_DIV_MASK		(7 << 18)
 #define   CGEM_NET_CFG_FCS_REMOVE		(1 << 17)
 #define   CGEM_NET_CFG_LEN_ERR_FRAME_DISC	(1 << 16)
 #define   CGEM_NET_CFG_RX_BUF_OFFSET_SHFT	14
 #define   CGEM_NET_CFG_RX_BUF_OFFSET_MASK	(3 << 14)
 #define   CGEM_NET_CFG_RX_BUF_OFFSET(n)		((n) << 14)
 #define   CGEM_NET_CFG_PAUSE_EN			(1 << 13)
 #define   CGEM_NET_CFG_RETRY_TEST		(1 << 12)
 #define   CGEM_NET_CFG_PCS_SEL			(1 << 11)
 #define   CGEM_NET_CFG_GIGE_EN			(1 << 10)
 #define   CGEM_NET_CFG_EXT_ADDR_MATCH_EN	(1 << 9)
 #define   CGEM_NET_CFG_1536RXEN			(1 << 8)
 #define   CGEM_NET_CFG_UNI_HASH_EN		(1 << 7)
 #define   CGEM_NET_CFG_MULTI_HASH_EN		(1 << 6)
 #define   CGEM_NET_CFG_NO_BCAST			(1 << 5)
 #define   CGEM_NET_CFG_COPY_ALL			(1 << 4)
 #define   CGEM_NET_CFG_DISC_NON_VLAN		(1 << 2)
 #define   CGEM_NET_CFG_FULL_DUPLEX		(1 << 1)
 #define   CGEM_NET_CFG_SPEED100			(1 << 0)
 
 #define CGEM_NET_STAT			0x008	/* Network Status */
 #define   CGEM_NET_STAT_PFC_PRI_PAUSE_NEG	(1 << 6)
 #define   CGEM_NET_STAT_PCS_AUTONEG_PAUSE_TX_RES (1 << 5)
 #define   CGEM_NET_STAT_PCS_AUTONEG_PAUSE_RX_RES (1 << 4)
 #define   CGEM_NET_STAT_PCS_AUTONEG_DUP_RES	(1 << 3)
 #define   CGEM_NET_STAT_PHY_MGMT_IDLE		(1 << 2)
 #define   CGEM_NET_STAT_MDIO_IN_PIN_STATUS	(1 << 1)
 #define   CGEM_NET_STAT_PCS_LINK_STATE		(1 << 0)
 
 #define CGEM_USER_IO			0x00C	/* User I/O */
 
 #define CGEM_DMA_CFG			0x010	/* DMA Config */
+#define   CGEM_DMA_CFG_ADDR_BUS_64		(1 << 30)
 #define   CGEM_DMA_CFG_DISC_WHEN_NO_AHB		(1 << 24)
 #define   CGEM_DMA_CFG_RX_BUF_SIZE_SHIFT	16
 #define   CGEM_DMA_CFG_RX_BUF_SIZE_MASK		(0xff << 16)
 #define   CGEM_DMA_CFG_RX_BUF_SIZE(sz)		((((sz) + 63) / 64)  <<  16)
 #define   CGEM_DMA_CFG_CHKSUM_GEN_OFFLOAD_EN	(1 << 11)
 #define   CGEM_DMA_CFG_TX_PKTBUF_MEMSZ_SEL	(1 << 10)
 #define   CGEM_DMA_CFG_RX_PKTBUF_MEMSZ_SEL_1K	(0 << 8)
 #define   CGEM_DMA_CFG_RX_PKTBUF_MEMSZ_SEL_2K	(1 << 8)
 #define   CGEM_DMA_CFG_RX_PKTBUF_MEMSZ_SEL_4K	(2 << 8)
 #define   CGEM_DMA_CFG_RX_PKTBUF_MEMSZ_SEL_8K	(3 << 8)
 #define   CGEM_DMA_CFG_RX_PKTBUF_MEMSZ_SEL_MASK	(3 << 8)
 #define   CGEM_DMA_CFG_AHB_ENDIAN_SWAP_PKT_EN	(1 << 7)
 #define   CGEM_DMA_CFG_AHB_ENDIAN_SWAP_MGMT_EN	(1 << 6)
 #define   CGEM_DMA_CFG_AHB_FIXED_BURST_LEN_1	(1 << 0)
 #define   CGEM_DMA_CFG_AHB_FIXED_BURST_LEN_4	(4 << 0)
 #define   CGEM_DMA_CFG_AHB_FIXED_BURST_LEN_8	(8 << 0)
 #define   CGEM_DMA_CFG_AHB_FIXED_BURST_LEN_16	(16 << 0)
 #define   CGEM_DMA_CFG_AHB_FIXED_BURST_LEN_MASK	(0x1f << 0)
 
 #define CGEM_TX_STAT			0x014	/* Transmit Status */
 #define   CGEM_TX_STAT_HRESP_NOT_OK		(1 << 8)
 #define   CGEM_TX_STAT_LATE_COLL		(1 << 7)
 #define   CGEM_TX_STAT_UNDERRUN			(1 << 6)
 #define   CGEM_TX_STAT_COMPLETE			(1 << 5)
 #define   CGEM_TX_STAT_CORRUPT_AHB_ERR		(1 << 4)
 #define   CGEM_TX_STAT_GO			(1 << 3)
 #define   CGEM_TX_STAT_RETRY_LIMIT_EXC		(1 << 2)
 #define   CGEM_TX_STAT_COLLISION		(1 << 1)
 #define   CGEM_TX_STAT_USED_BIT_READ		(1 << 0)
 #define   CGEM_TX_STAT_ALL			0x1ff
 
 #define CGEM_RX_QBAR			0x018	/* Receive Buf Q Base Addr */
 #define CGEM_TX_QBAR			0x01C	/* Transmit Buf Q Base Addr */
 
 #define CGEM_RX_STAT			0x020	/* Receive Status */
 #define   CGEM_RX_STAT_HRESP_NOT_OK		(1 << 3)
 #define   CGEM_RX_STAT_OVERRUN			(1 << 2)
 #define   CGEM_RX_STAT_FRAME_RECD		(1 << 1)
 #define   CGEM_RX_STAT_BUF_NOT_AVAIL		(1 << 0)
 #define   CGEM_RX_STAT_ALL			0xf
 
 #define CGEM_INTR_STAT			0x024	/* Interrupt Status */
 #define CGEM_INTR_EN			0x028	/* Interrupt Enable */
 #define CGEM_INTR_DIS			0x02C	/* Interrupt Disable */
 #define CGEM_INTR_MASK			0x030	/* Interrupt Mask */
 #define   CGEM_INTR_TSU_SEC_INCR		(1 << 26)
 #define   CGEM_INTR_PDELAY_RESP_TX		(1 << 25)
 #define   CGEM_INTR_PDELAY_REQ_TX		(1 << 24)
 #define   CGEM_INTR_PDELAY_RESP_RX		(1 << 23)
 #define   CGEM_INTR_PDELAY_REQ_RX		(1 << 22)
 #define   CGEM_INTR_SYNX_TX			(1 << 21)
 #define   CGEM_INTR_DELAY_REQ_TX		(1 << 20)
 #define   CGEM_INTR_SYNC_RX			(1 << 19)
 #define   CGEM_INTR_DELAY_REQ_RX		(1 << 18)
 #define   CGEM_INTR_PARTNER_PG_RX		(1 << 17)
 #define   CGEM_INTR_AUTONEG_COMPL		(1 << 16)
 #define   CGEM_INTR_EXT_INTR			(1 << 15)
 #define   CGEM_INTR_PAUSE_TX			(1 << 14)
 #define   CGEM_INTR_PAUSE_ZERO			(1 << 13)
 #define   CGEM_INTR_PAUSE_NONZEROQ_RX		(1 << 12)
 #define   CGEM_INTR_HRESP_NOT_OK		(1 << 11)
 #define   CGEM_INTR_RX_OVERRUN			(1 << 10)
 #define   CGEM_INTR_LINK_CHNG			(1 << 9)
 #define   CGEM_INTR_TX_COMPLETE			(1 << 7)
 #define   CGEM_INTR_TX_CORRUPT_AHB_ERR		(1 << 6)
 #define   CGEM_INTR_RETRY_EX_LATE_COLLISION	(1 << 5)
 #define   CGEM_INTR_TX_USED_READ		(1 << 3)
 #define   CGEM_INTR_RX_USED_READ		(1 << 2)
 #define   CGEM_INTR_RX_COMPLETE			(1 << 1)
 #define   CGEM_INTR_MGMT_SENT			(1 << 0)
 #define   CGEM_INTR_ALL				0x7FFFEFF
 
 #define CGEM_PHY_MAINT			0x034	/* PHY Maintenenace */
 #define   CGEM_PHY_MAINT_CLAUSE_22		(1 << 30)
 #define   CGEM_PHY_MAINT_OP_SHIFT		28
 #define   CGEM_PHY_MAINT_OP_MASK		(3 << 28)
 #define   CGEM_PHY_MAINT_OP_READ		(2 << 28)
 #define   CGEM_PHY_MAINT_OP_WRITE		(1 << 28)
 #define   CGEM_PHY_MAINT_PHY_ADDR_SHIFT		23
 #define   CGEM_PHY_MAINT_PHY_ADDR_MASK		(0x1f << 23)
 #define   CGEM_PHY_MAINT_REG_ADDR_SHIFT		18
 #define   CGEM_PHY_MAINT_REG_ADDR_MASK		(0x1f << 18)
 #define   CGEM_PHY_MAINT_MUST_10		(2 << 16)
 #define   CGEM_PHY_MAINT_DATA_MASK		0xffff
 
 #define CGEM_RX_PAUSEQ			0x038	/* Received Pause Quantum */
 #define CGEM_TX_PAUSEQ			0x03C	/* Transmit Puase Quantum */
 
 #define CGEM_HASH_BOT			0x080	/* Hash Reg Bottom [31:0] */
 #define CGEM_HASH_TOP			0x084	/* Hash Reg Top [63:32] */
 #define CGEM_SPEC_ADDR_LOW(n)		(0x088 + (n) * 8)
 #define CGEM_SPEC_ADDR_HI(n)		(0x08C + (n) * 8)
 
 #define CGEM_TYPE_ID_MATCH1		0x0A8	/* Type ID Match 1 */
 #define   CGEM_TYPE_ID_MATCH_COPY_EN		(1U << 31)
 #define CGEM_TYPE_ID_MATCH2		0x0AC	/* Type ID Match 2 */
 #define CGEM_TYPE_ID_MATCH3		0x0B0	/* Type ID Match 3 */
 #define CGEM_TYPE_ID_MATCH4		0x0B4	/* Type ID Match 4 */
 
 #define CGEM_WAKE_ON_LAN		0x0B8	/* Wake on LAN Register */
 #define   CGEM_WOL_MULTI_HASH_EN		(1 << 19)
 #define   CGEM_WOL_SPEC_ADDR1_EN		(1 << 18)
 #define   CGEM_WOL_ARP_REQ_EN			(1 << 17)
 #define   CGEM_WOL_MAGIC_PKT_EN			(1 << 16)
 #define   CGEM_WOL_ARP_REQ_IP_ADDR_MASK		0xffff
 
 #define CGEM_IPG_STRETCH		/* IPG Stretch Register */
 
 #define CGEM_STACKED_VLAN		0x0C0	/* Stacked VLAN Register */
 #define   CGEM_STACKED_VLAN_EN			(1U << 31)
 
 #define CGEM_TX_PFC_PAUSE		0x0C4	/* Transmit PFC Pause Reg */
 #define   CGEM_TX_PFC_PAUSEQ_SEL_SHIFT		8
 #define   CGEM_TX_PFC_PAUSEQ_SEL_MASK		(0xff << 8)
 #define   CGEM_TX_PFC_PAUSE_PRI_EN_VEC_VAL_MASK 0xff
 
 #define CGEM_SPEC_ADDR1_MASK_BOT	0x0C8	/* Specific Addr Mask1 [31:0]*/
 #define CGEM_SPEC_ADDR1_MASK_TOP	0x0CC	/* Specific Addr Mask1[47:32]*/
 #define CGEM_MODULE_ID			0x0FC	/* Module ID */
 #define CGEM_OCTETS_TX_BOT		0x100	/* Octets xmitted [31:0] */
 #define CGEM_OCTETS_TX_TOP		0x104	/* Octets xmitted [47:32] */
 #define CGEM_FRAMES_TX			0x108	/* Frames xmitted */
 #define CGEM_BCAST_FRAMES_TX		0x10C	/* Broadcast Frames xmitted */
 #define CGEM_MULTI_FRAMES_TX		0x110	/* Multicast Frames xmitted */
 #define CGEM_PAUSE_FRAMES_TX		0x114	/* Pause Frames xmitted */
 #define CGEM_FRAMES_64B_TX		0x118	/* 64-Byte Frames xmitted */
 #define CGEM_FRAMES_65_127B_TX		0x11C	/* 65-127 Byte Frames xmitted*/
 #define CGEM_FRAMES_128_255B_TX		0x120	/* 128-255 Byte Frames xmit */
 #define CGEM_FRAMES_256_511B_TX		0x124	/* 256-511 Byte Frames xmit */
 #define CGEM_FRAMES_512_1023B_TX	0x128	/* 512-1023 Byte frames xmit */
 #define CGEM_FRAMES_1024_1518B_TX	0x12C	/* 1024-1518 Byte frames xmit*/
 #define CGEM_TX_UNDERRUNS		0x134	/* Transmit Under-runs */
 #define CGEM_SINGLE_COLL_FRAMES		0x138	/* Single-Collision Frames */
 #define CGEM_MULTI_COLL_FRAMES		0x13C	/* Multi-Collision Frames */
 #define CGEM_EXCESSIVE_COLL_FRAMES	0x140	/* Excessive Collision Frames*/
 #define CGEM_LATE_COLL			0x144	/* Late Collisions */
 #define CGEM_DEFERRED_TX_FRAMES		0x148	/* Deferred Transmit Frames */
 #define CGEM_CARRIER_SENSE_ERRS		0x14C	/* Carrier Sense Errors */
 #define CGEM_OCTETS_RX_BOT		0x150	/* Octets Received [31:0] */
 #define CGEM_OCTETS_RX_TOP		0x154	/* Octets Received [47:32] */
 #define CGEM_FRAMES_RX			0x158	/* Frames Received */
 #define CGEM_BCAST_FRAMES_RX		0x15C	/* Broadcast Frames Received */
 #define CGEM_MULTI_FRAMES_RX		0x160	/* Multicast Frames Received */
 #define CGEM_PAUSE_FRAMES_RX		0x164	/* Pause Frames Reeived */
 #define CGEM_FRAMES_64B_RX		0x168	/* 64-Byte Frames Received */
 #define CGEM_FRAMES_65_127B_RX		0x16C	/* 65-127 Byte Frames Rx'd */
 #define CGEM_FRAMES_128_255B_RX		0x170	/* 128-255 Byte Frames Rx'd */
 #define CGEM_FRAMES_256_511B_RX		0x174	/* 256-511 Byte Frames Rx'd */
 #define CGEM_FRAMES_512_1023B_RX	0x178	/* 512-1023 Byte Frames Rx'd */
 #define CGEM_FRAMES_1024_1518B_RX	0x17C	/* 1024-1518 Byte Frames Rx'd*/
 #define CGEM_UNDERSZ_RX			0x184	/* Undersize Frames Rx'd */
 #define CGEM_OVERSZ_RX			0x188	/* Oversize Frames Rx'd */
 #define CGEM_JABBERS_RX			0x18C	/* Jabbers received */
 #define CGEM_FCS_ERRS			0x190	/* Frame Check Sequence Errs */
 #define CGEM_LENGTH_FIELD_ERRS		0x194	/* Length Firled Frame Errs */
 #define CGEM_RX_SYMBOL_ERRS		0x198	/* Receive Symbol Errs */
 #define CGEM_ALIGN_ERRS			0x19C	/* Alignment Errors */
 #define CGEM_RX_RESOURCE_ERRS		0x1A0	/* Receive Resoure Errors */
 #define CGEM_RX_OVERRUN_ERRS		0x1A4	/* Receive Overrun Errors */
 #define CGEM_IP_HDR_CKSUM_ERRS		0x1A8	/* IP Hdr Checksum Errors */
 #define CGEM_TCP_CKSUM_ERRS		0x1AC	/* TCP Checksum Errors */
 #define CGEM_UDP_CKSUM_ERRS		0x1B0	/* UDP Checksum Errors */
 #define CGEM_TIMER_STROBE_S		0x1C8	/* 1588 timer sync strobe s */
 #define CGEM_TIMER_STROBE_NS		0x1CC	/* timer sync strobe ns */
 #define CGEM_TIMER_S			0x1D0	/* 1588 timer seconds */
 #define CGEM_TIMER_NS			0x1D4	/* 1588 timer ns */
 #define CGEM_ADJUST			0x1D8	/* 1588 timer adjust */
 #define CGEM_INCR			0x1DC	/* 1588 timer increment */
 #define CGEM_PTP_TX_S			0x1E0	/* PTP Event Frame xmit secs */
 #define CGEM_PTP_TX_NS			0x1E4	/* PTP Event Frame xmit ns */
 #define CGEM_PTP_RX_S			0x1E8	/* PTP Event Frame rcv'd s */
 #define CGEM_PTP_RX_NS			0x1EC	/* PTP Event Frame rcv'd ns */
 #define CGEM_PTP_PEER_TX_S		0x1F0	/* PTP Peer Event xmit s */
 #define CGEM_PTP_PEER_TX_NS		0x1F4	/* PTP Peer Event xmit ns */
 #define CGEM_PTP_PEER_RX_S		0x1F8	/* PTP Peer Event rcv'd s */
 #define CGEM_PTP_PEER_RX_NS		0x1FC	/* PTP Peer Event rcv'd ns */
 
+#define CGEM_DESIGN_CFG1		0x280	/* Design Configuration 1 */
+#define   CGEM_DESIGN_CFG1_AXI_CACHE_WIDTH_MASK	(0xfU << 28)
+#define   CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_MASK	(7 << 25)
+#define   CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_32	(1 << 25)
+#define   CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_64	(2 << 25)
+#define   CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_128	(4 << 25)
+#define   CGEM_DESIGN_CFG1_IRQ_READ_CLR		(1 << 23)
+#define   CGEM_DESIGN_CFG1_NO_SNAPSHOT		(1 << 22)
+#define   CGEM_DESIGN_CFG1_NO_STATS		(1 << 21)
+#define   CGEM_DESIGN_CFG1_NO_SCAN_PINS		(1 << 20)
+#define   CGEM_DESIGN_CFG1_USER_IN_WIDTH_MASK	(0x1f << 15)
+#define   CGEM_DESIGN_CFG1_USER_OUT_WIDTH_MASK	(0x1f << 10)
+#define   CGEM_DESIGN_CFG1_USER_IO		(1 << 9)
+#define   CGEM_DESIGN_CFG1_APB_REV2		(1 << 8)
+#define   CGEM_DESIGN_CFG1_APB_REV1		(1 << 7)
+#define   CGEM_DESIGN_CFG1_EXT_FIFO_INTERFACE	(1 << 6)
+#define   CGEM_DESIGN_CFG1_NO_INT_LOOPBACK	(1 << 5)
+#define   CGEM_DESIGN_CFG1_INT_LOOPBACK		(1 << 4)
+#define   CGEM_DESIGN_CFG1_TDC_50		(1 << 3)
+#define   CGEM_DESIGN_CFG1_RDC_50		(1 << 2)
+#define   CGEM_DESIGN_CFG1_SERDES		(1 << 1)
+#define   CGEM_DESIGN_CFG1_NO_PCS		(1 << 0)
+
 #define CGEM_DESIGN_CFG2		0x284	/* Design Configuration 2 */
 #define   CGEM_DESIGN_CFG2_TX_PBUF_ADDR_SHIFT	26
 #define   CGEM_DESIGN_CFG2_TX_PBUF_ADDR_MASK	(0xf << 26)
 #define   CGEM_DESIGN_CFG2_RX_PBUF_ADDR_SHIFT	22
 #define   CGEM_DESIGN_CFG2_RX_PBUF_ADDR_MASK	(0xf << 22)
 #define   CGEM_DESIGN_CFG2_TX_PKT_BUF		(1 << 21)
 #define   CGEM_DESIGN_CFG2_RX_PKT_BUF		(1 << 20)
 #define   CGEM_DESIGN_CFG2_HPROT_VAL_SHIFT	16
 #define   CGEM_DESIGN_CFG2_HPROT_VAL_MASK	(0xf << 16)
 #define   CGEM_DESIGN_CFG2_JUMBO_MAX_LEN_MASK	0xffff
 
 #define CGEM_DESIGN_CFG3		0x288	/* Design Configuration 3 */
 #define   CGEM_DESIGN_CFG3_RX_BASE2_FIFO_SZ_MASK (0xffffU << 16)
 #define   CGEM_DESIGN_CFG3_RX_BASE2_FIFO_SZ_SHIFT 16
 #define   CGEM_DESIGN_CFG3_RX_FIFO_SIZE_MASK	0xffff
 
 #define CGEM_DESIGN_CFG4		0x28C	/* Design Configuration 4 */
 #define   CGEM_DESIGN_CFG4_TX_BASE2_FIFO_SZ_SHIFT 16
 #define   CGEM_DESIGN_CFG4_TX_BASE2_FIFO_SZ_MASK (0xffffU << 16)
 #define   CGEM_DESIGN_CFG4_TX_FIFO_SIZE_MASK	0xffff
 
 #define CGEM_DESIGN_CFG5		0x290	/* Design Configuration 5 */
 #define   CGEM_DESIGN_CFG5_TSU_CLK		(1 << 28)
 #define   CGEM_DESIGN_CFG5_RX_BUF_LEN_DEF_SHIFT 20
 #define   CGEM_DESIGN_CFG5_RX_BUF_LEN_DEF_MASK	(0xff << 20)
 #define   CGEM_DESIGN_CFG5_TX_PBUF_SIZE_DEF	(1 << 19)
 #define   CGEM_DESIGN_CFG5_RX_PBUF_SIZE_DEF_SHIFT 17
 #define   CGEM_DESIGN_CFG5_RX_PBUF_SIZE_DEF_MASK (3 << 17)
 #define   CGEM_DESIGN_CFG5_ENDIAN_SWAP_DEF_SHIFT 15
 #define   CGEM_DESIGN_CFG5_ENDIAN_SWAP_DEF_MASK (3 << 15)
 #define   CGEM_DESIGN_CFG5_MDC_CLOCK_DIV_SHIFT	12
 #define   CGEM_DESIGN_CFG5_MDC_CLOCK_DIV_MASK	(7 << 12)
 #define   CGEM_DESIGN_CFG5_DMA_BUS_WIDTH_SHIFT	10
 #define   CGEM_DESIGN_CFG5_DMA_BUS_WIDTH_MASK	(3 << 10)
 #define   CGEM_DESIGN_CFG5_PHY_IDENT		(1 << 9)
 #define   CGEM_DESIGN_CFG5_TSU			(1 << 8)
 #define   CGEM_DESIGN_CFG5_TX_FIFO_CNT_WIDTH_SHIFT 4
 #define   CGEM_DESIGN_CFG5_TX_FIFO_CNT_WIDTH_MASK (0xf << 4)
 #define   CGEM_DESIGN_CFG5_RX_FIFO_CNT_WIDTH_MASK 0xf
 
-/* Transmit Descriptors */
+#define CGEM_DESIGN_CFG6		0x294	/* Design Configuration 6 */
+#define   CGEM_DESIGN_CFG6_ADDR_64B		(1 << 23) /* 64-bit addr cap */
+#define   CGEM_DESIGN_CFG6_DMA_PRIO_Q_MASK	0xfffe
+#define   CGEM_DESIGN_CFG6_DMA_PRIO_Q(n)	(1 << (n))
+
+#define CGEM_TX_QN_BAR(n)		(0x440 + ((n) - 1) * 4)
+#define CGEM_RX_QN_BAR(n)		(0x480 + ((n) - 1) * 4)
+
+#define CGEM_TX_QBAR_HI			0x4C8
+#define CGEM_RX_QBAR_HI			0x4D4
+
+/*
+ * Transmit Descriptors:  two or four 32-bit words:
+ *	word0: address
+ *	word1: length and control
+ *	word2: address upper 32-bits (64-bit mode)
+ *	word3: unused (64-bit mode)
+ */
+
 struct cgem_tx_desc {
 	uint32_t	addr;
 	uint32_t	ctl;
 #define CGEM_TXDESC_USED			(1U << 31) /* done txmitting */
 #define CGEM_TXDESC_WRAP			(1 << 30)  /* end descr ring */
 #define CGEM_TXDESC_RETRY_ERR			(1 << 29)
 #define CGEM_TXDESC_AHB_ERR			(1 << 27)
 #define CGEM_TXDESC_LATE_COLL			(1 << 26)
 #define CGEM_TXDESC_CKSUM_GEN_STAT_MASK		(7 << 20)
 #define CGEM_TXDESC_CKSUM_GEN_STAT_VLAN_HDR_ERR (1 << 20)
 #define CGEM_TXDESC_CKSUM_GEN_STAT_SNAP_HDR_ERR (2 << 20)
 #define CGEM_TXDESC_CKSUM_GEN_STAT_IP_HDR_ERR	(3 << 20)
 #define CGEM_TXDESC_CKSUM_GEN_STAT_UNKNOWN_TYPE (4 << 20)
 #define CGEM_TXDESC_CKSUM_GEN_STAT_UNSUPP_FRAG	(5 << 20)
 #define CGEM_TXDESC_CKSUM_GEN_STAT_NOT_TCPUDP	(6 << 20)
 #define CGEM_TXDESC_CKSUM_GEN_STAT_SHORT_PKT	(7 << 20)
 #define CGEM_TXDESC_NO_CRC_APPENDED		(1 << 16)
 #define CGEM_TXDESC_LAST_BUF			(1 << 15)  /* last in frame */
 #define CGEM_TXDESC_LENGTH_MASK		0x3fff
+#ifdef CGEM64
+	uint32_t	addrhi;
+	uint32_t	unused;
+#endif
 };
 
+/*
+ * Receive Descriptors: two or four 32-bit words:
+ *	word0: address | WRAP and OWN flags
+ *	word1: length and control
+ *	word2: address upper 32 bits (64-bit mode)
+ *	word3: unused
+ */
+
 struct cgem_rx_desc {
 	uint32_t	addr;
 #define CGEM_RXDESC_WRAP			(1 << 1)  /* goes in addr! */
 #define CGEM_RXDESC_OWN				(1 << 0)  /* buf filled */
 	uint32_t	ctl;
 #define CGEM_RXDESC_BCAST			(1U << 31)/* all 1's bcast */
 #define CGEM_RXDESC_MULTI_MATCH			(1 << 30) /* mutlicast match */
 #define CGEM_RXDESC_UNICAST_MATCH		(1 << 29)
 #define CGEM_RXDESC_EXTERNAL_MATCH		(1 << 28) /* ext addr match */
 #define CGEM_RXDESC_SPEC_MATCH_SHIFT		25
 #define CGEM_RXDESC_SPEC_MATCH_MASK		(3 << 25)
 #define CGEM_RXDESC_TYPE_ID_MATCH_SHIFT		22
 #define CGEM_RXDESC_TYPE_ID_MATCH_MASK		(3 << 22)
 #define CGEM_RXDESC_CKSUM_STAT_MASK		(3 << 22) /* same as above */
 #define CGEM_RXDESC_CKSUM_STAT_NONE		(0 << 22)
 #define CGEM_RXDESC_CKSUM_STAT_IP_GOOD		(1 << 22)
 #define CGEM_RXDESC_CKSUM_STAT_TCP_GOOD		(2 << 22) /* and ip good */
 #define CGEM_RXDESC_CKSUM_STAT_UDP_GOOD		(3 << 22) /* and ip good */
 #define CGEM_RXDESC_VLAN_DETECTED		(1 << 21)
 #define CGEM_RXDESC_PRIO_DETECTED		(1 << 20)
 #define CGEM_RXDESC_VLAN_PRIO_SHIFT		17
 #define CGEM_RXDESC_VLAN_PRIO_MASK		(7 << 17)
 #define CGEM_RXDESC_CFI				(1 << 16)
 #define CGEM_RXDESC_EOF				(1 << 15) /* end of frame */
 #define CGEM_RXDESC_SOF				(1 << 14) /* start of frame */
 #define CGEM_RXDESC_BAD_FCS			(1 << 13)
 #define CGEM_RXDESC_LENGTH_MASK			0x1fff
+#ifdef CGEM64
+	uint32_t	addrhi;
+	uint32_t	unused;
+#endif
 };
 
 #endif /* _IF_CGEM_HW_H_ */
diff --git a/sys/dts/arm/zynq-7000.dtsi b/sys/dts/arm/zynq-7000.dtsi
index a48c7bb732a1..a2a585a39446 100644
--- a/sys/dts/arm/zynq-7000.dtsi
+++ b/sys/dts/arm/zynq-7000.dtsi
@@ -1,247 +1,247 @@
 /*-
  * Copyright (c) 2016 The FreeBSD Foundation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * $FreeBSD$
  */
 
 / {
 	compatible = "xlnx,zynq-7000";
 	#address-cells = <1>;
 	#size-cells = <1>;
 	interrupt-parent = <&GIC>;
 
 	// Reserve first half megabyte because it is not accessible to all
 	// bus masters.
 	memreserve = <0x00000000 0x00080000>;
 
 	// Zynq PS System registers.
 	//
  	ps7sys@f8000000 {
 		device_type = "soc";
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x0 0xf8000000 0xf10000>;
 
 		// SLCR block
 		slcr: slcr@7000 {
 			compatible = "xlnx,zy7_slcr";
 			reg = <0x0 0x1000>;
 		};
 
 		// Interrupt controller
 		GIC: gic {
 			compatible = "arm,gic";
 			interrupt-controller;
 			#address-cells = <0>;
 			#interrupt-cells = <3>;
 			reg = <0xf01000 0x1000>, // distributer registers
 			      <0xf00100 0x0100>; // CPU if registers
 		};
 
 		// L2 cache controller
 		pl310@f02000 {
 			compatible = "arm,pl310";
 			reg = <0xf02000 0x1000>;
 			interrupts = <0 2 4>;
 			interrupt-parent = <&GIC>;
 		};
 
 		// Device Config
 		devcfg: devcfg@7000 {
 			compatible = "xlnx,zy7_devcfg";
 			reg = <0x7000 0x1000>;
 			interrupts = <0 8 4>;
 			interrupt-parent = <&GIC>;
 		};
 
 		// triple timer counters0,1
 		ttc0: ttc@1000 {
 		 	compatible = "xlnx,ttc";
 			reg = <0x1000 0x1000>;
 		};
 		
 		ttc1: ttc@2000 {
 		 	compatible = "xlnx,ttc";
 		 	reg = <0x2000 0x1000>;
 		};
 
 		// ARM Cortex A9 TWD Timer
 		global_timer: timer@f00600 {
 			compatible = "arm,mpcore-timers";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0xf00200 0x100>,	// Global Timer Regs
 			      <0xf00600 0x20>;	// Private Timer Regs
 			interrupts = <1 11 1>, <1 13 1>;
 			interrupt-parent = <&GIC>;
 		};
 
 		// system watch-dog timer
 		swdt@5000 {
 			device_type = "watchdog";
 		 	compatible = "xlnx,zy7_wdt";
 		 	reg = <0x5000 0x1000>;
 		 	interrupts = <0 9 1>;
 		 	interrupt-parent = <&GIC>;
 		};
 
 		scuwdt@f00620 {
 		 	device_type = "watchdog";
 		 	compatible = "arm,mpcore_wdt";
 		 	reg = <0xf00620 0x20>;
 		 	interrupts = <1 14 1>;
 		 	interrupt-parent = <&GIC>;
 		 	reset = <1>;
 		};
 		
 	}; // pssys@f8000000
 
 	// Zynq PS I/O Peripheral registers.
 	//
 	ps7io@e0000000 {
 		device_type = "soc";
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x0 0xe0000000 0x300000>;
 
 		// UART controllers
 		uart0: uart@0000 {
 			device_type = "serial";
 			compatible = "cadence,uart";
 			status = "disabled";
 			reg = <0x0000 0x1000>;
 			interrupts = <0 27 4>;
 			interrupt-parent = <&GIC>;
 			clock-frequency = <50000000>;
 		};
 
 		uart1: uart@1000 {
 			device_type = "serial";
 			compatible = "cadence,uart";
 			status = "disabled";
 			reg = <0x1000 0x1000>;
 			interrupts = <0 50 4>;
 			interrupt-parent = <&GIC>;
 			clock-frequency = <50000000>;
 		};
 
 		// USB controllers
 		ehci0: ehci@2000 {
 			compatible = "xlnx,zy7_ehci";
 			status = "disabled";
 			reg = <0x2000 0x1000>;
 			interrupts = <0 21 4>;
 			interrupt-parent = <&GIC>;
 		};
 
 		ehci1: ehci@3000 {
 			compatible = "xlnx,zy7_ehci";
 			status = "disabled";
 			reg = <0x3000 0x1000>;
 			interrupts = <0 44 4>;
 			interrupt-parent = <&GIC>;
 		};
 
 		// GPIO controller
 		gpio: gpio@a000 {
 			compatible = "xlnx,zy7_gpio";
 			reg = <0xa000 0x1000>;
 		 	interrupts = <0 20 4>;
 		 	interrupt-parent = <&GIC>;
 		};
 
 		// Gigabit Ethernet controllers
 		eth0: eth@b000 {
-		        device_type = "network";
-		 	compatible = "cadence,gem";
+			device_type = "network";
+			compatible = "cdns,zynq-gem", "cadence,gem";
 			status = "disabled";
-		 	reg = <0xb000 0x1000>;
+			reg = <0xb000 0x1000>;
 			interrupts = <0 22 4>;
 			interrupt-parent = <&GIC>;
 			ref-clock-num = <0>;
 		};
 
 		eth1: eth@c000 {
-		        device_type = "network";
-		 	compatible = "cadence,gem";
+			device_type = "network";
+			compatible = "cdns,zynq-gem", "cadence,gem";
 			status = "disabled";
-		 	reg = <0xc000 0x1000>;
+			reg = <0xc000 0x1000>;
 			interrupts = <0 45 4>;
 			interrupt-parent = <&GIC>;
 			ref-clock-num = <1>;
 		};
 
 		// Quad-SPI controller
 		qspi0: qspi@d000 {
 			compatible = "xlnx,zy7_qspi";
 			status = "disabled";
 			reg = <0xd000 0x1000>;
 			interrupts = <0 19 4>;
 			interrupt-parent = <&GIC>;
 			ref-clock = <200000000>; // 200 Mhz
 			spi-clock = <50000000>;  // 50 Mhz
 		};
 
 		// SPI controllers
 		spi0: spi0@6000 {
 			compatible = "xlnx,zy7_spi";
 			status = "disabled";
 			reg = <0x6000 0x100>;
 			interrupts = <0 26 4>;
 			interrupt-parent = <&GIC>;
 		};
 
 		spi1: spi0@7000 {
 			compatible = "xlnx,zy7_spi";
 			status = "disabled";
 			reg = <0x7000 0x100>;
 			interrupts = <0 49 4>;
 			interrupt-parent = <&GIC>;
 		};
 
 		// SDIO controllers
 		sdhci0: sdhci@100000 {
 			compatible = "xlnx,zy7_sdhci";
 			status = "disabled";
 			reg = <0x100000 0x1000>;
 			interrupts = <0 24 4>;
 			interrupt-parent = <&GIC>;
 			max-frequency = <50000000>;
 		};
 
 		sdhci1: sdhci@101000 {
 			compatible = "xlnx,zy7_sdhci";
 			status = "disabled";
 			reg = <0x101000 0x1000>;
 			interrupts = <0 47 4>;
 			interrupt-parent = <&GIC>;
 			max-frequency = <50000000>;
 		};
 
 	}; // ps7io@e0000000
 };
 
diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC
index b1384a88c213..a04d5557c83c 100644
--- a/sys/riscv/conf/GENERIC
+++ b/sys/riscv/conf/GENERIC
@@ -1,173 +1,173 @@
 #
 # GENERIC -- Generic kernel configuration file for FreeBSD/RISC-V
 #
 # For more information on this file, please read the config(5) manual page,
 # and/or the handbook section on Kernel Configuration Files:
 #
 #    https://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
 #
 # The handbook is also available locally in /usr/share/doc/handbook
 # if you've installed the doc distribution, otherwise always see the
 # FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the
 # latest information.
 #
 # An exhaustive list of options and more detailed explanations of the
 # device lines is also present in the ../../conf/NOTES and NOTES files.
 # If you are in doubt as to the purpose or necessity of a line, check first
 # in NOTES.
 #
 # $FreeBSD$
 
 cpu		RISCV
 ident		GENERIC
 
 makeoptions	DEBUG=-g		# Build kernel with gdb(1) debug symbols
 makeoptions	WITH_CTF=1		# Run ctfconvert(1) for DTrace support
 
 options 	SCHED_ULE		# ULE scheduler
 options 	PREEMPTION		# Enable kernel thread preemption
 options 	VIMAGE			# Subsystem virtualization, e.g. VNET
 options 	INET			# InterNETworking
 options 	INET6			# IPv6 communications protocols
 options 	TCP_HHOOK		# hhook(9) framework for TCP
 options 	IPSEC_SUPPORT		# Allow kldload of ipsec and tcpmd5
 options		ROUTE_MPATH		# Multipath routing support
 options 	TCP_OFFLOAD		# TCP offload
 options 	SCTP_SUPPORT		# Allow kldload of SCTP
 options 	FFS			# Berkeley Fast Filesystem
 options 	SOFTUPDATES		# Enable FFS soft updates support
 options 	UFS_ACL			# Support for access control lists
 options 	UFS_DIRHASH		# Improve performance on big directories
 options 	UFS_GJOURNAL		# Enable gjournal-based UFS journaling
 options 	QUOTA			# Enable disk quotas for UFS
 options 	NFSCL			# Network Filesystem Client
 options 	NFSD			# Network Filesystem Server
 options 	NFSLOCKD		# Network Lock Manager
 options 	NFS_ROOT		# NFS usable as /, requires NFSCL
 options 	MSDOSFS			# MSDOS Filesystem
 options 	CD9660			# ISO 9660 Filesystem
 options 	PROCFS			# Process filesystem (requires PSEUDOFS)
 options 	PSEUDOFS		# Pseudo-filesystem framework
 options 	TMPFS			# Efficient memory filesystem
 options 	GEOM_PART_GPT		# GUID Partition Tables.
 options 	GEOM_RAID		# Soft RAID functionality.
 options 	GEOM_LABEL		# Provides labelization
 options 	SCSI_DELAY=5000		# Delay (in ms) before probing SCSI
 options 	KTRACE			# ktrace(1) support
 options 	STACK			# stack(9) support
 options 	SYSVSHM			# SYSV-style shared memory
 options 	SYSVMSG			# SYSV-style message queues
 options 	SYSVSEM			# SYSV-style semaphores
 options 	_KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
 options 	PRINTF_BUFR_SIZE=128	# Prevent printf output being interspersed.
 options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
 # options 	HWPMC_HOOKS		# Necessary kernel hooks for hwpmc(4)
 options 	AUDIT			# Security event auditing
 options 	CAPABILITY_MODE		# Capsicum capability mode
 options 	CAPABILITIES		# Capsicum capabilities
 options 	MAC			# TrustedBSD MAC Framework
 options 	KDTRACE_FRAME		# Ensure frames are compiled in
 options 	KDTRACE_HOOKS		# Kernel DTrace hooks
 options 	DDB_CTF			# Kernel ELF linker loads CTF data
 options 	FPE			# Floating-point extension support
 options 	RACCT			# Resource accounting framework
 options 	RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
 options 	RCTL			# Resource limits
 options 	SMP
 options 	INTRNG
 
 # RISC-V SBI console
 device		rcons
 
 # EXT_RESOURCES pseudo devices
 options 	EXT_RESOURCES
 device		clk
 device		syscon
 device		syscon_power
 device		riscv_syscon
 
 # Bus drivers
 device		pci
 
 # VirtIO support
 device		virtio			# Generic VirtIO bus (required)
 device		virtio_pci		# VirtIO PCI device
 device		vtnet			# VirtIO Ethernet device
 device		virtio_blk		# VirtIO Block device
 device		virtio_mmio		# VirtIO MMIO bus
 
 # DTrace support
 # device	dtrace
 # device	dtrace_profile
 # device	dtrace_sdt
 # device	dtrace_fbt
 # device	dtrace_systrace
 # device	dtrace_prototype
 # device	dtraceall
 
 # Serial (COM) ports
 device		uart		# Generic UART driver
 device		uart_lowrisc	# lowRISC UART driver
 device		uart_ns8250	# ns8250-type UART driver
 
 # RTC
 device		goldfish_rtc	# QEMU RTC
 
 # Ethernet drivers
+device		cgem		# Cadence GEM Gigabit Ethernet device
 device		miibus		# MII bus support
-device		cgem		# Cadence Gigabit Ethernet MAC
 device		xae		# Xilinx AXI Ethernet MAC
 
 # DMA support
 device		xdma		# DMA interface
 device		axidma		# Xilinx AXI DMA Controller
 
 # Uncomment for memory disk
 # options 	MD_ROOT
 # options 	MD_ROOT_SIZE=32768	# 32MB ram disk
 # makeoptions	MFS_IMAGE=/path/to/img
 # options 	ROOTDEVNAME=\"ufs:/dev/md0\"
 
 # Uncomment for virtio block device
 # options 	ROOTDEVNAME=\"ufs:/dev/vtbd0\"
 
 # Debugging support.  Always need this:
 options 	KDB			# Enable kernel debugger support.
 options 	KDB_TRACE		# Print a stack trace for a panic.
 # For full debugger support use (turn off in stable branch):
 options 	DDB			# Support DDB.
 # options 	GDB			# Support remote GDB.
 options 	DEADLKRES		# Enable the deadlock resolver
 options 	INVARIANTS		# Enable calls of extra sanity checking
 options 	INVARIANT_SUPPORT	# Extra sanity checks of internal structures, required by INVARIANTS
 options 	WITNESS			# Enable checks to detect deadlocks and cycles
 options 	WITNESS_SKIPSPIN	# Don't run witness on spinlocks for speed
 options 	MALLOC_DEBUG_MAXZONES=8	# Separate malloc(9) zones
 # options 	EARLY_PRINTF
 options 	VERBOSE_SYSINIT=0	# Support debug.verbose_sysinit, off by default
 
 # Kernel dump features.
 options		ZSTDIO			# zstd-compressed kernel and user dumps
 
 # Pseudo devices.
 device		crypto		# core crypto support
 device		loop		# Network loopback
 device		ether		# Ethernet support
 device		vlan		# 802.1Q VLAN support
 device		tuntap		# Packet tunnel.
 device		md		# Memory "disks"
 device		gif		# IPv6 and IPv4 tunneling
 device		firmware	# firmware assist module
 
 # The `bpf' device enables the Berkeley Packet Filter.
 # Be aware of the administrative consequences of enabling this!
 # Note that 'bpf' is required for DHCP.
 device		bpf		# Berkeley packet filter
 
 # Flattened Device Tree
 options 	FDT
 makeoptions	MODULES_EXTRA+="dtb/sifive"
 
 # SiFive device drivers
 device		fu540spi
 include		"../sifive/std.sifive"